更新时间:2024-04-08 08:18:04下载pdf
MCU SDK 是根据涂鸦 IoT 开发平台定义的产品功能自动生成的 MCU 开发包,能够快速协助开发者完成 MCU 程序的开发。为了减少使用涂鸦 Wi-Fi 通用串口协议的对接成本,MCU SDK 已搭建通讯及协议解析架构,只需做简单的串口适配即可实现与无线通讯模组通讯,快速实现产品智能化。
本文将介绍 MCU SDK 的移植流程以及开发注意事项。
MCU SDK 对 资源要求如下:
内存:4KB。
RAM:与设备功能的 DP 数据长度有关,约为 100 字节。如果使用 MCU OTA 升级功能,RAM 需大于 260 字节。
函数嵌套级数:9 级。
如果当前项目的 MCU 资源不足,可自行对接 串口协议,SDK 中的函数可以作为使用参考。
下载 MCU SDK 的步骤,请参考 MCU 低代码开发。下载后,MCU SDK 由以下文件组成:
文件 | 说明 |
---|---|
mcu_api.c |
包含可供调用的函数。 |
mcu_api.h |
mcu_api.c 中的函数声明。 |
protocol.c |
包含协议数据体的内容处理函数。请根据项目需求,在相应函数内添加代码,获取涂鸦无线模组向 MCU 发送的数据。 |
protocol.h |
protocol.h 包含以下信息:
|
system.c |
串口通讯协议解析的具体实现。 |
system.h |
system.h 包含以下信息:
|
wifi.h |
包含相关宏定义。 |
针对部分特色产品品类的 mcu_sdk
,宏定义文件名会略有不同。
protocol.h
宏定义。protocol.c
文件及函数调用。在原项目工程中,完成 MCU 相关外设初始化,包括串口、外部中断(按键)、定时器(指示灯闪烁)等。
将 MCU SDK 文件夹中的 .c
和 .h
文件添加至相应头文件引用路径。
protocol.h
宏定义定义 PID。PRODUCT_KEY
为产品 PID 宏定义。PID 即产品 ID,为每个产品的唯一标识,可在 涂鸦 IoT 开发平台 的产品详情页面查询。
#define PRODUCT_KEY "ax23rawjo4np****"
如果 PRODUCT_KEY
和产品 PID 不一致,请在 硬件开发 > 下载资料 下载最新 SDK 开发包后重试。
定义版本号。MCU_VER
为软件版本,默认为 1.0.0
。若 MCU 需要 OTA 功能,每次升级 MCU 固件需要更改新的 MCU 版本号。
#define MCU_VER "1.0.0"
定义 Wi-Fi 配网模式。CONFIG_MODE
为配网方式,支持默认模式、安全模式、防误触模式。建议选择 防误触 模式。
三种配网模式说明:
默认模式:热点和快连配网模式互相切换。如果模组未配网或移除配网,上电后会处于待配网状态并一直保持。
#define CONFIG_MODE CONFIG_MODE_DEFAULT
安全模式:模组出厂上电后处于非配网状态,需要 MCU 发送重置命令才会进入相应的配网模式。当设备处于配网状态一段时间(默认 3 分钟)后,未被用户配走,模组便重新进入非配网状态,需要重新收到重置命令才会重新进入配网模式。
#define CONFIG_MODE CONFIG_MODE_LOWPOWER
防误触模式:模组被用户配网成功后,本地(MCU 发送重置命令)重置后,设备处于待配网状态,一段时间(默认 3 分钟)后没有被重新配网,模组会自动恢复重置前的用户网络连接。本地重置后设备中途异常断电,上电也会自动恢复重置前的用户网络连接。这种模式下,只有当设备被用户从 App 端移除,设备才不会记录上次用户的网络连接并重连。
#define CONFIG_MODE CONFIG_MODE_SPECIAL
定义配网模式时长。当模组工作模式选择了 安全模式 或 防误触模式,可以打开 CONFIG_MODE_DELAY_TIME
宏定义,设置配网模式的保持时间,设置范围为 3~10 分钟。默认值为 3 分钟。
#define CONFIG_MODE_DELAY_TIME 10
选择固定配网模式。可以通过 CONFIG_MODE_CHOOSE
设置,使热点和快连配网模式同时存在或者仅保存热点模式。
0
:配网方式为热点和快连模式共存,此时无需切换配网方式。
#define CONFIG_MODE_CHOOSE 0
1
:配网方式只有热点模式。
#define CONFIG_MODE_CHOOSE 1
设置功耗模式。可以通过 LONG_CONN_LOWPOWER
开启模组低功耗模式,默认关闭。
//#define LONG_CONN_LOWPOWER 0 //关闭低功耗模式
//#define LONG_CONN_LOWPOWER 1 //打开低功耗模式
串口接收缓存:大小受到串口数据处理被调用的频率影响。如果 MCU 对串口数据的处理较快,串口接收缓存大小可适当减小。
串口发送缓存:大小须大于数据最长的 DP 数据长度。
串口数据处理缓存:大小须大于数据最长的 DP 数据长度,还要根据是否需要 OTA 功能以及是否需要天气服务、天气服务类型数量和天数来调整大小,需要大于最大数据量的大小。
/******************************************************************************
3:定义收发缓存
如当前使用 MCU 的 RAM 不够,可修改为 24
******************************************************************************/
#ifndef SUPPORT_MCU_FIRM_UPDATE
#define WIFI_UART_RECV_BUF_LMT 16 //串口数据接收缓存区大小,如 MCU 的 RAM 不够,可缩小
#define WIFI_DATA_PROCESS_LMT 24 //串口数据处理缓存区大小,根据用户 DP 数据大小量定,必须大于 24
#else
#define WIFI_UART_RECV_BUF_LMT 128 //串口数据接收缓存区大小,如 MCU 的 RAM 不够,可缩小
//请在此处选择合适的串口数据处理缓存大小(根据上面 MCU 固件升级包选择的大小和是否开启天气服务,选择开启多大的缓存)
#define WIFI_DATA_PROCESS_LMT 300 //串口数据处理缓存大小,如需 MCU 固件升级,若单包大小选择 256,则缓存必须大于 260。若开启天气服务,则需要更大
//#define WIFI_DATA_PROCESS_LMT 600 //串口数据处理缓存大小,如需 MCU 固件升级,若单包大小选择 512,则缓存必须大于 520。若开启天气服务,则需要更大
//#define WIFI_DATA_PROCESS_LMT 1200 //串口数据处理缓存大小,如需 MCU 固件升级,若单包大小选择 1024,则缓存必须大于 1030。若开启天气服务,则需要更大
#endif
#define WIFIR_UART_SEND_BUF_LMT 48 //根据用户 DP 数据大小量确定,必须大于 48
如配网按键和 LED 接在 MCU 端,即选择 模组和 MCU 配合处理 工作模式(常用),保持 WIFI_CONTROL_SELF_MODE
宏定义处于被注释状态。
//#define WIFI_CONTROL_SELF_MODE //Wi-Fi 自处理按键及 LED 指示灯,如为 MCU 外接按键/LED 指示灯请关闭该宏
如配网指示灯和按键是接在 Wi-Fi 模组上的,即选择 模组自处理 工作模式,开启 WIFI_CONTROL_SELF_MODE
宏定义,然后根据实际的硬件连接,将指示灯和按键所连接的 GPIO 脚位填入下面两个宏定义。
#ifdef WIFI_CONTROL_SELF_MODE //模组自处理
#define WF_STATE_KEY 14 //Wi-Fi 模组状态指示按键,请根据实际 GPIO 管脚设置
#define WF_RESERT_KEY 0 //Wi-Fi 模组重置按键,请根据实际 GPIO 管脚设置
#endif
将 wifi.h
文件保存至存放 Wi-Fi 相关文件的文件夹中,例如 main.c
。
在 MCU 串口及其他外设初始化后,调用 mcu_api.c
文件中的 wifi_protocol_init()
函数。
将 MCU 串口单字节发送函数填入 protocol.c
文件中的 uart_transmit_output()
函数内,并删除 #error
。示例如下:
/**
* @brief 串口发送数据
* @param[in] {value} 串口要发送的 1 字节数据
* @return Null
*/
void uart_transmit_output(unsigned char value)
{
//#error "请将 MCU 串口发送函数填入该函数,并删除该行"
UART3_SendByte(value);
/*
//Example:
extern void Uart_PutChar(unsigned char value);
Uart_PutChar(value); //串口发送函数
*/
}
在串口接收中断服务函数里面调用 mcu_api.c
文件内的 uart_receive_input()
函数,并将接收到的字符作为参数传入。示例如下:
void USART3_IRQHandler(void)
{
unsigned char Res=0;
if((USART3->SR&UART_FLAG_RXNE) != 0)
{
Res=USART3->DR;
uart_receive_input(Res);
}
}
MCU 进入 while(1)
循环后调用 mcu_api.c
文件内的 wifi_uart_service()
函数。main.c
中示例代码结构如下:
#include "wifi.h"
...
void main(void)
{
wifi_protocol_init();
...
while(1)
{
wifi_uart_service();
...
}
...
}
while(1)
中直接调用 mcu_api.c
内的 wifi_uart_service()
函数。设备功能(Data Point,DP)主要有 6 种数据类型:
类型 | 说明 |
---|---|
bool | 通常为开关类的 DP,例如开关、ECO 和屏显。 |
enum | 通常用作有多种状态的 DP,例如工作模式、风速和风摆位置。 |
value | 通常用作数值类型的 DP,例如设定温度值、当前温度值和电量。 |
fault | 通常用于故障的上报,数据常用 bitmap 格式显示。 |
string | 通常用作字符串类型的 DP。需要以字符串形式传输的 DP 可以使用此类型。部分不便于使用 bool、enum、value 或 fault 类型的 DP,也可用此类型。 |
raw | 通常用作需要透传但对数据格式无要求(明文或者加密)的数据。发送端和接收端对数据的格式、组包和解析方式需要统一。 |
在模组重启或者重新配网后,Wi-Fi 模组主动下发状态查询指令,此时需要 MCU 上报设备所有 DP 状态给 Wi-Fi 模组进行同步。
打开 protocol.c
找到函数 all_data_update(void)
。
把所有需要上报的 DP 初值填入相应上报函数,为 App 提供开机显示初值。
请勿随意调用 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 状态发生变化时,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 型数据上报
在 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);
上传设备功能(开关)状态实时状态,形成反馈,也可以根据实际需要选择上报时机。
仅 MCU 与模组配合处理模式 工作模式需要设置配网功能及指示灯函数。
移植协议成功后,还需添加配网指令以及指示灯功能。根据 配网方式 编写配网触发方式,根据 模组工作方式 编写网络状态指示方式。可以根据实际情况自行决定,通常为按键触发和 LED 快闪/慢闪指示。
目前支持两种以下配网模式:
Wi-Fi 快连模式(Smart 模式,快闪):操作简便,以指示灯快闪做指示。
Wi-Fi 热点模式(AP 模式,慢闪):配网可靠,以指示灯慢闪做指示。
配网指令有 mcu_reset_wifi()
和 mcu_set_wifi_mode()
两个函数可以实现。通常在按键触发配网后,在按键处理函数中调用。
mcu_reset_wifi()
:调用后复位 Wi-Fi 模组,复位后之前的配网信息全部清除。mcu_reset_wifi()
每调用一次,Wi-Fi 模组在热点和快连之间切换一次配网模式。
mcu_set_wifi_mode()
:参数为 SMART_CONFIG
和 AP_CONFIG
。调用后清除配网信息,进入快连模式或者热点模式。
通常在 while(1)
中调用 mcu_get_wifi_work_state()
函数,来查询 Wi-Fi 状态。根据 Wi-Fi 状态,写入相应闪灯的模式。
设备联网状态 | 描述 | 状态值 | LED 显示 |
---|---|---|---|
状态 1 | 快连模式配置状态 | 0x00 | 快闪,间隔 250ms |
状态 2 | 热点模式配置状态 | 0x01 | 慢闪,间隔 1500ms |
状态 3 | Wi-Fi 已配置但未连上路由器 | 0x02 | 熄灭 |
状态 4 | Wi-Fi 已配置且连上路由器,局域网可控制 | 0x03 | 常亮 |
状态 5 | 已连上路由器且连接到云端,局域网和外网均可控制 | 0x04 | 常亮 |
状态 6 | Wi-Fi 设备处于低功耗模式 | 0x05 | 熄灭 |
状态 7 | Wi-Fi 设备处于快连和热点模式共存配置状态 | 0x06 | 快闪,间隔 250ms |
调用函数 mcu_get_wifi_work_state()
查询 Wi-Fi 连接状态,函数架构如下:
void main(void)
{
...
while(1)
{
...
switch(mcu_get_wifi_work_state())
{
case SMART_CONFIG_STATE:
//处于 Smart 配置状态,即 LED 快闪
break;
case AP_STATE:
//处于 AP 配置状态,即 LED 慢闪
break;
case WIFI_NOT_CONNECTED:
//Wi-Fi 配置完成,正在连接路由器,即 LED 常暗
break;
case WIFI_CONNECTED:
//路由器连接成功,即 LED 常亮
break;
default:break;
}
...
}
}
Wi-Fi 产测功能默认开启。为保证最终量产效率及品质,建议开启该功能。
#define WIFI_TEST_ENABLE //开启 Wi-Fi 产测功能(扫描指定路由)
MCU SDK 提供 MCU 固件 OTA 功能,MCU 待升级固件可通过 Wi-Fi 通信模组下载,并通过串口发送至 MCU。MCU 本地存储后切换新版本固件,即可完成 MCU OTA 功能。如需支持 MCU OTA 功能,请开启 SUPPORT_MCU_FIRM_UPDATE
,默认关闭。
#define SUPPORT_MCU_FIRM_UPDATE
更多 MCU OTA 功能介绍与使用,请参考 MCU OTA 服务。
Wi-Fi 和 Wi-Fi & 蓝牙通用协议接入支持多种扩展能力,可满足不同行业应用需求。关于扩展功能介绍与使用,请参考 扩展功能。
该内容对您有帮助吗?
是意见反馈该内容对您有帮助吗?
是意见反馈