更新时间:2025-12-24 03:06:24下载pdf
MCU SDK 是根据涂鸦开发者平台定义的产品功能自动生成的 MCU 代码,能够协助您快速完成 MCU 程序的开发。本文为您介绍 Zigbee 通用方案移植 MCU SDK 的流程以及注意事项。本文将介绍 MCU SDK 的移植流程以及开发注意事项。
MCU SDK 对资源要求如下:
在移植 MCU SDK 前,您需要下载对应的 SDK 源码,具体请参考 MCU 低代码开发。下载后,MCU SDK 由以下文件组成:
| 文件 | 说明 |
|---|---|
zigbee.h |
提供通用宏的定义 |
system.h |
system.h 包含以下信息:
|
system.c |
system.c 包含以下信息:
|
protocol.h |
protocol.h 包含以下信息:
|
protocol.c |
protocol.c 包含以下信息:
|
mcu_api.h |
mcu_api.h 包含以下信息:
|
mcu_api.c |
mcu_api.c 包含以下信息:
|
开发时,要重点关注 mcu_api.h 和 mcu_api.c 文件,需要手动修改的代码部分都在这两个接口文件中。此外,还有涂鸦开发者平台配置相关的 protocol.h 和 protocol.c 文件,需要根据实际需求进行检查和修改。
MCU SDK 移植流程如下:
在正式移植 MCU SDK 前,需要您在自己的 MCU 平台上实现至少以下外设功能:
将 MCU SDK 文件夹中的 .c 和 .h 文件分别添加到项目工程的源文件和头文件引用路径下。
修改接口文件 mcu_api.h 和 mcu_api.c,主要分为四个部分:
需要把 MCU 串口接收到的数据以单字节的形式传入 uart_servive_rx_store(),然后周期性调用(主循环调用或定时器定时调用)uart_service_parse() 函数。
需要确认自身开发设备是否是低功耗设备,接口文件相关配置宏如下:
///< <USER MUST NOT CHANGE>
#define ROUTER_DEVICE 1
#define SLEEP_END_DEVICE 2
#define SCENE_SWITCH_DEVICE 3
#define LOW_LEVEL_WAKE_UP 1
#define LOW_PULSE_WAKE_UP 2
///< END <USER MUST NOT CHANGE>
///< <USER MUST CHECK AND CHANGE>
#define MCU_VER "1.0.0"
#define DEVICE_TYPE ROUTER_DEVICE
#if (DEVICE_TYPE == SLEEP_END_DEVICE)
#define MCU_WAKEUP_MODULE_METHOD LOW_LEVEL_WAKE_UP
#endif
///< END <USER MUST CHECK AND CHANGE>
如果您开发的是非低功耗设备(DEVICE_TYPE = ROUTER_DEVICE 或者 DEVICE_TYPE = SCENE_SWITCH_DEVICE),可以直接跳过这一部分修改。
如果您开发的是低功耗设备(DEVICE_TYPE = SLEEP_END_DEVICE),需要选择唤醒方式,实现基本流程如下(细节部分请参考 串口协议章节:低功耗唤醒部分),这一部分需要结合自身 MCU 平台定时器、GPIO 等外设实现一些等待和超时的逻辑。
#if (DEVICE_TYPE == SLEEP_END_DEVICE)
/*
* "g_zg_wait_mcu_time" depends on the user's chip platform, users should design it by themselves,
* users can set the "g_zg_wait_mcu_time" through the function "mcu_tx_set_zg_wait_mcu_time()".
*/
#if (MCU_WAKEUP_MODULE_METHOD == LOW_LEVEL_WAKE_UP)
void mcu_wakeup_zg_level_method(unsigned char *data, unsigned short data_len)
{
/*
*< USER TODO: wakeup zigbee module by low-level method end send data;
*sequence chart:
* ____ _____
*
* mcu wakeup module pin: |<---------------t1----------------->|
* | |
* |____________________________________|
*
* mcu uart tx pin : |<-t0->|<-send()->| |
* |______|__________|__________________|
*
* mcu uart rx pin : | |<-recv()->| |
* |_________________|__________|_______|
*
* t0: "g_mcu_wait_zg_time" mcu wait module wakeup time, 1-10ms, ZT module >=10ms;
*
* t1: "g_wakeup_stay_time" mcu wakeup module pin stay time, t1 must < 120s;
*
* 1. pull down the mcu wakeup module pin;
*
* 2. wait t0;
*
* 3. uart_send_bytes() send data;
*
* 4. wait uart_servive_rx_store() finish receiving data and uart_service_parse()
*
* finish analysing data;
*
* 6. pull up the mcu wakeup module pin; then the module will enter sleep mode after x ms;
*/
}
#elif (MCU_WAKEUP_MODULE_METHOD == LOW_PULSE_WAKE_UP)
void mcu_wakeup_zg_pulse_method(unsigned char *data, unsigned short data_len)
{
/*
*< USER TODO: wakeup zigbee module by low-level pulse method end send data;
*sequence chart:
* ____ ________________________________
*
* mcu wakeup module pin: |<-t0->| |
* |______| |
*
* mcu uart tx pin : | |<-send()->| |
* |______|__________|__________________|
*
* mcu uart rx pin : | |<-recv()->| |
* |_________________|__________|_______|
*
* t0: "g_mcu_wait_zg_time" mcu wakeup module pin pull down stay time;ZS module [1, 5]ms, ZT module >=10ms;
*
* 1. mcu wakeup module pin generate a low-level pulse lasting for t0 ms;
*
* 2. uart_send_bytes() send data;
*
* 3. wait uart_servive_rx_store() finish receiving data and uart_service_parse()
* finish analysing data;
*/
}
#endif
#endif
需要在函数 uart_send_bytes() 定义中实现串口单字节发送功能。
MCU SDK 已预留了协议解析后需要对特定命令进行一些处理的回调接口,可以根据自己的需求来填充这些函数,具体接口展示如下:
void mcu_recv_factory_recovery_cb(void)
{
//< USER TODO
}
. . .
. . .
省略部分
. . .
. . .
void mcu_recv_gw_nwk_status_cb(unsigned char nwk_status)
{
//< USER TODO
}
另外,还有一些可选择修改的宏定义,具体介绍如下:
| 宏定义 | 说明 | 注意事项 |
|---|---|---|
| MCU_VER | MCU 固件版本 | MCU 软件版本,默认 1.0.0;若 MCU 需要 OTA 功能,每次升级 MCU 固件需要更改新的 MCU 版本号 |
| DEVICE_TYPE | 设备类型 | 必须选择以下中的一项:
|
| MCU_WAKEUP_MODULE_METHOD | 低功耗设备 MCU 唤醒方式 | 必须从下面选择一项:
|
| SUPPORT_RECEIVE_BROADCAST_DATA | MCU 是否接收广播消息 | 默认:0x01
|
| ZG_WAIT_MCU_TIME_DEFAULT | Zigbee 设备(低功耗设备)唤醒 MCU 后,等待 MCU 串口通讯功能就绪的时间 | 默认:10 ms |
| MCU_WAIT_ZG_TIME_DEFAULT | MCU 唤醒 Zigbee 设备(低功耗设备)后,等待 Zigbee 设备(低功耗设备)串口通讯功能就绪的时间 | 默认:10 ms |
| UART_RX_BUF_LEN_LMT | 串口接收缓冲区数组大小 | 默认:256可以根据自身需求减小 |
| UART_TX_BUF_LEN_LMT | 串口发送缓冲区数组大小 | 默认:256可以根据自身需求减小 |
| UART_QUEUE_BUF_LEN_LMT | 串口接收队列大小 | 默认:512可以根据自身需求减小 |
| OTA_PACKET_SIZE | 单包 OTA 包大小 | 默认:0x30最大 0x30,可以根据自身需求减小 |
| MCU_SDK_DEBUG PRINT_DEBUG(fmt, …) |
日志相关接口 | 默认:关闭 可以根据自身需求配置打印函数后打开 |
协议相关文件 protocol.h 和 protocol.c 是通过在涂鸦开发者平台配置 DP 自动生成的,需要核查几处是否和自己预期的 DP 信息一致(可以在代码中全局搜索 USER_CHECK_MSG),以下为具体代码示例(仅供参考,实际情况中需根据您的配置决定):
//< USER_CHECK_MSG
///<product key(pid) the same as yours in the Tuya Developer Platform
#define PRODUCT_KEY "xn7xzluu" //开发平台创建产品后生成的 16 位字符的产品唯一标识
//< USER_CHECK_MSG END
//< USER_CHECK_MSG
///< dp id define
//开关 1(可下发可上报)
//备注:
#define DPID_SWITCH_1 1
. . .
省略部分
. . .
//随机定时(可下发可上报)
//备注:/#1 协议版本
///#2 节点长度
///#3 通道号(bit0:开关;bit1-bit7:通道号)
///#4 星期
///#5#6 起始时间(min)
///#7#8 结束时间(min)
#define DPID_RANDOM_TIMING 210
//< USER_CHECK_MSG END
//< USER_CHECK_MSG
/*----------------------------------------------------------
* DP list
* 1. please check the ID and type of each DP.
*--------------------------------------------------------*/
const DOWNLOAD_CMD_S download_cmd[] =
{
{DPID_SWITCH_1, DP_TYPE_BOOL},
{DPID_SWITCH_2, DP_TYPE_BOOL},
{DPID_SWITCH_3, DP_TYPE_BOOL},
{DPID_SWITCH_4, DP_TYPE_BOOL},
{DPID_SWITCH_5, DP_TYPE_BOOL},
{DPID_SWITCH_6, DP_TYPE_BOOL},
{DPID_COUNTDOWN_1, DP_TYPE_VALUE},
{DPID_COUNTDOWN_2, DP_TYPE_VALUE},
{DPID_COUNTDOWN_3, DP_TYPE_VALUE},
{DPID_COUNTDOWN_4, DP_TYPE_VALUE},
{DPID_COUNTDOWN_5, DP_TYPE_VALUE},
{DPID_COUNTDOWN_6, DP_TYPE_VALUE},
{DPID_SWITCH_ALL, DP_TYPE_BOOL},
{DPID_RELAY_STATUS, DP_TYPE_ENUM},
{DPID_LIGHT_MODE, DP_TYPE_ENUM},
{DPID_BACKLIGHT_SWITCH, DP_TYPE_BOOL},
{DPID_SWITCH_INCHING, DP_TYPE_STRING},
{DPID_ADD_ELE, DP_TYPE_VALUE},
{DPID_CUR_CURRENT, DP_TYPE_VALUE},
{DPID_CUR_POWER, DP_TYPE_VALUE},
{DPID_CUR_VOLTAGE, DP_TYPE_VALUE},
{DPID_TEST_BIT, DP_TYPE_VALUE},
{DPID_VOLTAGE_COE, DP_TYPE_VALUE},
{DPID_ELECTRIC_COE, DP_TYPE_VALUE},
{DPID_POWER_COE, DP_TYPE_VALUE},
{DPID_ELECTRICITY_COE, DP_TYPE_VALUE},
{DPID_RELAY_STATUS_1, DP_TYPE_ENUM},
{DPID_RELAY_STATUS_2, DP_TYPE_ENUM},
{DPID_RELAY_STATUS_3, DP_TYPE_ENUM},
{DPID_RELAY_STATUS_4, DP_TYPE_ENUM},
{DPID_RELAY_STATUS_5, DP_TYPE_ENUM},
{DPID_RELAY_STATUS_6, DP_TYPE_ENUM},
{DPID_CYCLE_TIMING, DP_TYPE_RAW},
{DPID_RANDOM_TIMING, DP_TYPE_RAW},
};
//< USER_CHECK_MSG END
这部分需确认每一个下发的 DP 是否需要执行对应操作;若需自行实现该逻辑,在 dp_msg_handle () 函数中需重点关注各 Case 分支对应的处理函数 —— 例如针对 “开关 1 下发消息”,需关注 dp_download_switch_1_handle () 函数,其余场景可依此类推。
/*****************************************************************************
函数名称:dp_download_switch_1_handle
功能描述:针对 `DPID_SWITCH_1` 的处理函数
输入参数:value:数据源数据
length:数据长度
返回参数:成功返回:SUCCESS,失败返回:ERROR
使用说明:可下发可上报类型,需要在处理完数据后上报处理结果至 App
*****************************************************************************/
static unsigned char dp_download_switch_1_handle(const unsigned char value[], unsigned short length)
{
//示例:当前 DP 类型为 BOOL
unsigned char ret;
//0:off/1:on
unsigned char switch_1;
switch_1 = mcu_get_dp_download_bool(value,length);
if(switch_1 == 0) {
//bool off
}else {
//bool on
}
//There should be a report after processing the DP
ret = mcu_dp_bool_update(DPID_SWITCH_1,switch_1);
if(ret == SUCCESS)
return SUCCESS;
else
return ERROR;
}
//< USER_CHECK_MSG END
static unsigned char dp_msg_handle(unsigned char dp_id, const unsigned char *value, unsigned short length)
{
unsigned char ret;
if (NULL == value) {
return ERROR;
}
switch (dp_id) {
case DPID_SWITCH_1:
//开关 1 处理函数
ret = dp_download_switch_1_handle(value,length);
break;
. . .
省略部分
. . .
case DPID_RANDOM_TIMING:
//随机定时处理函数
ret = dp_download_random_timing_handle(value,length);
break;
default :
break;
}
return ret;
}
这一部分由于模块在某些场景需要知道 MCU DP 数据(如重新配网、重启等),所以需要用户实现 “上报所有 DP 数据” 和 “上报单个 DP 数据” 功能,分别对应函数 all_data_update() 和 specific_dp_update() ,以此完成 App 和 MCU 数据同步。
static void all_data_update(void)
{
#error "Please handle the examples of data that can be issued and reported,as well as the data that can only be reported here. After processing,delete this line."
//< USER_CHECK_MSG
mcu_dp_bool_update(DPID_SWITCH_1, 1); //BOOL 型数据上报;
. . .
省略部分
. . .
//< USER_CHECK_MSG END
}
static void specific_dp_update(unsigned char dp_id)
{
switch (dp_id) {
case DPID_SWITCH_1: {
mcu_dp_bool_update(DPID_SWITCH_1, 1); //BOOL 型数据上报;
break;
}
. . .
省略部分
. . .
default: {
break;
}
}
} default :
break;
}
return ret;
}
该内容对您有帮助吗?
是意见反馈该内容对您有帮助吗?
是意见反馈