MCU SDK 移植

更新时间:2022-10-27 02:21:22下载pdf

MCU SDK 是根据涂鸦 IoT 开发平台上定义的产品功能,自动生成的 MCU 代码。MCU SDK 已包含通讯架构及协议解析架构,您可以将 MCU SDK 直接添加到原有工程中,快速完成 MCU 程序开发。

资源要求

涂鸦 MCU SDK 对硬件 MCU 的要求如下:

  • 内存:4KB

  • RAM:与 DP 数据长度有关,约为 100B(OTA 功能需大于 260B)

  • 函数嵌套级数:9 级

    如果您的硬件 MCU 资源不足,可自行对接 串口协议,SDK 中的函数可以作为使用参考。

文件结构

下载 MCU SDK 的步骤,请参考 MCU 低代码开发。下载后,MCU SDK 由以下文件组成:

文件
说明
mcu_api.c 包含可供调用的函数。
mcu_api.h mcu_api.c 中的函数声明。
protocol.c 包含协议数据体的内容处理函数。您可以根据项目需求,在相应函数内添加代码,获取 Zigbee 模组向 MCU 发送的数据。
protocol.h protocol.h 包含以下信息:
  • MCU 要发送至 Zigbee 模组初始化所需的参数。
  • SDK 裁剪所定义的宏。用户可根据需要的功能打开相应的宏定义。
  • protocol.c 中的函数声明。
system.c 串口通讯协议解析的具体实现。
system.h system.h 包含以下信息:
  • 协议命令字的定义。
  • 部分全局变量的定义。
  • system.c 中的函数声明。
zigbee.h 包含 Zigbee 相关宏定义。

移植流程

  1. 编写 MCU 基础程序,移植 SDK 文件。
  2. 确认 protocol.h 宏定义。
  3. 移植 protocol.c 文件及函数调用。
  4. 添加 DP 上报下发函数调用。
  5. 添加产测功能。
  6. 添加配网功能。

编写 MCU 基础程序和移植 SDK

  1. 在原项目工程中,完成 MCU 相关外设初始化,包括串口、外部中断(按键)、定时器(指示灯闪烁)等。

  2. 将 MCU SDK 文件夹中的 .c.h 文件添加至相应头文件引用路径。

    MCU SDK 移植

    MCU SDK 移植

确认 protocol.h 宏定义

确认产品信息

  1. 定义 PID。PRODUCT_KEY 为产品 PID 宏定义。PID 即产品 ID, 为每个产品的唯一标识,可在 IoT 平台 的产品详情页面获取。

    #define PRODUCT_KEY "ax23rawjo4np****"
    

    如果 PRODUCT_KEY 和产品 PID 不一致,请更换为在涂鸦 IoT 开发平台创建产品生成的 PID 进行调试。

  2. 定义版本号。MCU_VER 为软件版本,默认为 1.0.0 。若 MCU 需要 OTA 功能,需要添加新的 MCU 版本号。

    #define MCU_VER "1.0.0"
    

设置 OTA 升级(可选)

如果需要支持 OTA 固件升级,请定义 SUPPORT_MCU_FIRM_UPDATE,开启 OTA 升级功能,默认关闭。

#define         SUPPORT_MCU_FIRM_UPDATE

OTA 升级流程参考 OTA 升级说明-平台配置

定义收发缓存(可选)

修改缓冲区大小,根据 DP 定义。

  • 串口接收和发送缓存大小要大于数据最长的 DP 数据长度,默认大小 24。

  • 如果需要 MCU OTA 升级的用户缓存大小建议大于 260 字节。

  • 如果 RAM 紧张,接收队列大小可以适当缩小。

    #define ZIGBEE_UART_QUEUE_LMT             256             // 数据接收对列大小
    #define ZIGBEE_UART_RECV_BUF_LMT          128             // 串口接收缓存
    #define ZIGBEE_UART_SEND_BUF_LMT          128             // 串口发送缓存
    

移植 protocol.c 文件及函数调用

  1. zigbee.h 文件保存至存放 Zigbee 相关文件的文件夹中,例如 main.c 文件夹。

  2. 在 MCU 串口及其他外设初始化后调用 mcu_api.c 文件中的 zigbee_protocol_init() 函数。

  3. 将 MCU 串口单字节发送函数填入 protocol.c 文件中 uart_transmit_output 函数内,示例如下。

    /**
    * @brief encapsulates a generic send function, developer should use their own function to completing this fuction
    * @param[in] {value} send signle data
    * @return  void
    */
    void uart_transmit_output(unsigned char value);
    
    UART3_SendByte(value);
    
  4. 在串口接收中断服务函数里面调用 mcu_api.c 文件内的 uart_receive_input 函数,并将接收到的字符作为参数传入。

    /**
    * @brief copy receive data from uart receive interrupt
    * @param[in]  {value} Data received from interrupt
    * @return void
    */
    void uart_receive_input(unsigned char value)
    {
      #error "please call this function in the interrupt function of serial receive, and delete this line"
    
        if(1 == queue_out - queue_in) {
            //串口接收缓存已满
        }else if((queue_in > queue_out) && ((queue_in - queue_out) >= sizeof(zigbee_uart_rx_buf))) {
            //串口接收缓存已满
        }else {
            //串口接收缓存未满
            if(queue_in >= (unsigned char *)(zigbee_uart_rx_buf + sizeof(zigbee_uart_rx_buf))) {
                queue_in = (unsigned char *)(zigbee_uart_rx_buf);
            }
            *queue_in ++ = value;
        }
    }
    
    
  5. MCU 进入 while 循环后调用 mcu_api.c 文件内的 zigbee_uart_service()函数。main.c 中示例代码结构如下:

    include "zigbee.h"
    ...
    void main(void)
    {
    	zigbee_protocol_init();
    	...
    	while(1)
    	{
    		zigbee_uart_service();
    		...
    	}
    }
    

    MCU 必须在 while(1) 中直接调用 mcu_api.c 内的 zigbee_uart_service() 函数。程序正常初始化完成后,建议不进行关中断,如必须关中断,关中断时间必须短。关中断会引起串口数据包丢失,请勿在中断内调用上报函数。

DP 数据上报和下发函数处理

所有 DP 数据上报

在模组重启或者重新配网后,Zigbee 模组主动下发状态查询指令,此时需要 MCU 上报设备所有 DP 状态给 Zigbee 模组进行同步。

  1. 打开 protocol.c 找到函数 all_data_update(void)
  2. 把所有需要上报的 DP 初值填入相应上报函数,为面板提供开机显示初值。

请勿随意调用 all_data_update() 函数,该函数会在特定时间主动调用。

/**
 * @brief  系统所有 DP 信息上传,实现 App 和 MCU 数据同步
 * @param  Null
 * @return Null
 * @note   此函数 SDK 内部需调用,MCU 必须实现该函数内数据上报功能,包括只上报和可上报可下发型数据
 */
void all_data_update(void)
{
    //#error "请在此处理可下发可上报数据及只上报数据示例,处理完成后删除该行"

    /*
    //此代码为平台自动生成,请按照实际数据修改每个可下发可上报函数和只上报函数
    mcu_dp_bool_update(DPID_SWITCH,当前开关); //BOOL 型数据上报;
    mcu_dp_value_update(DPID_TEMP_SET,当前温度设置); //VALUE 型数据上报;
    mcu_dp_value_update(DPID_TEMP_CURRENT,当前温度); //VALUE 型数据上报;
    mcu_dp_enum_update(DPID_MODE,当前工作模式); //枚举型数据上报;
    mcu_dp_enum_update(DPID_FAN_SPEED_ENUM,当前风速); //枚举型数据上报;
    mcu_dp_enum_update(DPID_STATUS,当前状态); //枚举型数据上报;
    mcu_dp_bool_update(DPID_ECO,当前ECO模式); //BOOL 型数据上报;
    mcu_dp_bool_update(DPID_DRYING,当前干燥模式); //BOOL 型数据上报;
    mcu_dp_bool_update(DPID_VENTILATION,当前换气模式); //BOOL 型数据上报;
    mcu_dp_bool_update(DPID_HEAT,当前辅热); //BOOL 型数据上报;
    mcu_dp_bool_update(DPID_LIGHT,当前灯光); //BOOL 型数据上报;
    mcu_dp_bool_update(DPID_CHILD_LOCK,当前童锁); //BOOL 型数据上报;
    mcu_dp_bool_update(DPID_BEEP,当前蜂鸣); //BOOL 型数据上报;
    mcu_dp_value_update(DPID_HUMIDITY_SET,当前湿度设置); //VALUE 型数据上报;
    mcu_dp_value_update(DPID_HUMIDITY_CURRENT,当前湿度); //VALUE 型数据上报;
    mcu_dp_enum_update(DPID_TEMP_UNIT_CONVERT,当前温标切换); //枚举型数据上报;
    mcu_dp_enum_update(DPID_COUNTDOWN_SET,当前倒计时); //枚举型数据上报;
    mcu_dp_value_update(DPID_COUNTDOWN_LEFT,当前倒计时剩余时间); //VALUE 型数据上报;
    mcu_dp_fault_update(DPID_FAULT,当前故障告警); //故障型数据上报;
    mcu_dp_value_update(DPID_TEMP_CURRENT_F,当前温度-℉); //VALUE 型数据上报;
    mcu_dp_value_update(DPID_TEMP_SET_F,当前温度设置-℉); //VALUE 型数据上报;
    mcu_dp_bool_update(DPID_SLEEP,当前睡眠功能); //BOOL 型数据上报;
    mcu_dp_bool_update(DPID_CLEANING,当前自清洁); //BOOL 型数据上报;
    mcu_dp_bool_update(DPID_SWITCH_VERTICAL,当前上下摆风); //BOOL 型数据上报;
    mcu_dp_enum_update(DPID_GEAR_VERTICAL,当前上下摆风档位); //枚举型数据上报;
    mcu_dp_value_update(DPID_ANGLE_VERTICAL,当前上下摆风角度); //VALUE 型数据上报;
    mcu_dp_bool_update(DPID_SWITCH_HORIZONTAL,当前左右摆风); //BOOL 型数据上报;
    mcu_dp_enum_update(DPID_GEAR_HORIZONTAL,当前左右摆风档位); //枚举型数据上报;
    mcu_dp_value_update(DPID_ANGLE_HORIZONTAL,当前左右摆风角度); //VALUE 型数据上报;
    mcu_dp_bool_update(DPID_DISPLAY,当前屏显开关); //BOOL 型数据上报;
    */
}

单个 DP 数据上报

在单个 DP 状态发生变化时,MCU 需要主动上报,App 更新显示内容。上报格式为 mcu_dp_xxxx_updata(DPID_X,n),其中 DPID_X 为状态改变的 DP。all_data_update() 内的函数,均可单独调用。例如:

mcu_dp_bool_update(DPID_SWITCH,1); //BOOL 型数据上报
mcu_dp_value_update(DPID_TEMPER_SET,25); //VALUE 型数据上报
mcu_dp_string_update(DPID_DAY,"1234",4); //STRING 型数据上报

DP 数据下发处理函数

protocol.c 文件中,每个可下发的 DP,都有一个单独下发数据处理函数。格式为 dp_download_xxx_handle()xxx 为可下发 DP。函数解析功能点之后,MCU 需在相应位置完成逻辑控制。
以接收到开关 DP 数据为例:

/*****************************************************************************
函数名称 : dp_download_switch_handle
功能描述 : 针对 DPID_SWITCH 的处理函数
输入参数 : value:数据源数据
          length:数据长度
返回参数 : 成功返回:SUCCESS/失败返回:ERROR
使用说明 : 可下发可上报类型,需要在处理完数据后上报处理结果至 App
*****************************************************************************/
static unsigned char dp_download_switch_handle(const unsigned char value[], unsigned short length)
{
  //示例:当前 DP 类型为 BOOL
  unsigned char ret;
  //0:关状态/1:开状态
  unsigned char switch1;

  switch1 = mcu_get_dp_download_bool(value,length);
  if(switch1 == 0)
  {
    //开关的关状态
    MCU_OFF_switch1();
  }
  else
  {
    //开关的开状态
    MCU_ON_switch1();
  }

  //处理完 DP 数据后的反馈
  ret = mcu_dp_bool_update(DPID_SWITCH,switch1);
  if(ret == SUCCESS)
    return SUCCESS;
  else
    return ERROR;
}

当设备状态在非 App 控制下发生变化时,MCU 中需要调用 mcu_dp_bool_update(DPID_SWITCH_1,switch_1); 上传功能(开关)状态实时状态,形成反馈。您也可以根据实际需要选择上报时机。

产测功能

Zigbee 通用固件提供了 RF 产测功能, 通过串口命令来触发模组的 RF 测试流程,测试完成之后会将测试结果通过串口返回给 MCU。该测试流程需要借助于涂鸦 Zigbee 产测功能。具体协议格式参考:Zigbee 三级架构 UART 通信协议

配网功能

MCU 决定何时开启 Zigbee 模块配网。当 MCU 收到 Zigbee 模块发送了当前网络状态后,可以发送 0x03 命令配置 Zigbee 模组,将模组配置为开始配网状态。
示例:0x55 aa 02 00 01 03 00 01 01 xx

MCU SDK 与模组数据通信

帧格式

帧格式参考 帧格式说明

初始化通信

在 MCU 和模组上电后,需要进行初始化配置。初始化通信包括但不限于以下内容:

  • 需要验证 MCU 与模组是否能正常工作。
  • 验证通信连接是否正常。
  • 获取模组激活所需要数据。
  • 获取模组工作方式。

查询产品信息

模组重新上电后,需要查询 MCU 固件的产品 PID、版本号和配网方式。

  • PID:产品 ID,用于产品激活。
  • 版本号:MCU 版本号,用于 OTA 升级完成后,验证是否升级成功。
  • 配网方式:模组的配网方式。

数据交互注意事项

  • 为避免出现不可预测的问题,建议 DP 下发和上报、OTA 升级等正常数据通信要在初始化完成之后进行。
  • 对于低功耗等 MCU 可以控制模组上下电的设备,数据交互要等设备整个初始化完成之后进行。