更新时间:2024-11-20 02:13:22下载pdf
MCU SDK 是根据您在涂鸦开发者平台定义的产品功能自动生成的 MCU 开发包,能够协助您快速完成 MCU 程序的开发。为了减少您使用涂鸦 Wi-Fi 通用串口协议的对接成本,MCU SDK 已搭建通讯及协议解析架构。本文为您介绍移植 MCU SDK 的流程以及注意事项,将 MCU SDK 添加至工程并配置相关信息后,即可快速的完成 MCU 程序开发。
SDK 对 MCU 的要求如下。如果您的硬件资源不足,可自行对接串口协议,SDK 包中的函数可以作为使用参考。
内存:4KB
RAM:与设备功能的 DP 数据长度有关,约为 100B (OTA 功能需大于 260B)
函数嵌套级数:9 级
如果您使用的是 Arduino 开发板,请参考 Arduino 接入涂鸦快速入门。
文件 | 说明 |
---|---|
mcu_api.c |
包含可供调用的函数。 |
mcu_api.h |
mcu_api.c 中的函数声明。 |
protocol.c |
包含协议数据体的内容处理函数。您可以根据项目需求,在相应函数内添加代码,获取 Wi-Fi 模组向 MCU 发送的数据。 |
protocol.h |
protocol.h 包含以下信息:
|
system.c |
串口通讯协议解析的具体实现。 |
system.h |
system.h 包含以下信息:
|
wifi.h |
相关宏定义。 |
mcu_sdk
中,还有包含门锁功能相关函数的 lock_api.c
和 lock_api.h
文件。mcu_sdk
中,wifi.h
文件的名称替换为 gprs.h
。protocol.h
宏定义。protocol.c
文件及函数调用。在原项目工程中,完成 MCU 相关外设初始化,包括串口、外部中断(按键)、定时器(指示灯闪烁)等。
将 MCU SDK 文件夹中的 .c
和 .h
文件添加至相应头文件引用路径。
protocol.h
宏定义第一步:确认产品信息
定义 PID。PRODUCT_KEY
为产品 PID 宏定义。PID 即产品 ID, 为每个产品的唯一标识,可在 开发者平台 的产品详情页面查询。
#define PRODUCT_KEY "ax23rawjo4np****"
如果 PRODUCT_KEY
和产品 PID 不一致,请在 硬件开发 > 下载资料 下载最新 SDK 开发包后重试。
定义版本号。MCU_VER
为软件版本,默认为 1.0.0
。若 MCU 需要 OTA 功能,需要添加新的 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
设置红外功能。可以通过 ENABLE_MODULE_IR_FUN
设置红外的发送脚和接收脚的 I/O。
//#define ENABLE_MODULE_IR_FUN //启用模组的红外功能
#ifdef ENABLE_MODULE_IR_FUN
#define MODULE_IR_PIN_TX 5 //红外发送脚
#define MODULE_IR_PIN_RX 12 //红外接收脚
#endif
设置低功耗模式。可以通过 LONG_CONN_LOWPOWER
开启模组低功耗模式,默认关闭。
//#define LONG_CONN_LOWPOWER 0 //关闭低功耗模式
//#define LONG_CONN_LOWPOWER 1 //打开低功耗模式
第二步:设置 OTA 升级(可选)
开启 OTA 升级功能。如果需要支持 OTA 固件升级,请定义 SUPPORT_MCU_FIRM_UPDATE
,默认关闭。
#define SUPPORT_MCU_FIRM_UPDATE
定义单次发送固件包的大小。
#ifdef SUPPORT_MCU_FIRM_UPDATE
#define PACKAGE_SIZE 0 //单个固件包大小为 256 字节
//#define PACKAGE_SIZE 1 //单个固件包大小为 512 字节
//#define PACKAGE_SIZE 2 //单个固件包大小为 1024 字节
#endif
OTA 升级流程参见 OTA 升级说明-平台配置。
第三步:定义收发缓存(可选)
串口接收缓存:大小受到串口数据处理被调用的频率影响。如果 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
第五步:开启 Wi-Fi 产测功能(可选)
Wi-Fi 产测功能默认开启。为保证最终量产效率及品质,建议开启该功能。
#define WIFI_TEST_ENABLE //开启 Wi-Fi 产测功能(扫描指定路由)
详细产测流程,请参考 生产测试说明。
第六步:接入天气服务(可选)
模组成功连上路由之后,定义 WEATHER_ENABLE
即可开通天气服务功能。模组连接上云端后会立即下发天气数据,此后每隔 30 分钟下发 1 次。
开启天气服务功能。定义 WEATHER_ENABLE
。
//#define WEATHER_ENABLE //打开天气功能
选择支持的天气类型。您可以在 protocol.c
文件的 weather_choose
数组中,选择支持天气数据的参数。
#ifdef WEATHER_ENABLE
/**
* @var weather_choose
* @brief 天气数据参数选择数组
* @note 用户可以自定义需要的参数,注释或者取消注释即可,注意更改
*/
const char *weather_choose[WEATHER_CHOOSE_CNT] = {
"temp",
"humidity",
"condition",
"pm25",
/*"pressure",
"realFeel",
"uvi",
"tips",
"windDir",
"windLevel",
"windSpeed",
"sunRise",
"sunSet",
"aqi",
"so2 ",
"rank",
"pm10",
"o3",
"no2",
"co",*/
};
#endif
设置支持的天气的个数。将支持的参数个数在 WEATHER_CHOOSE_CNT
中定义。
#define WEATHER_CHOOSE_CNT 4
设置预报天数。新版固件的模组将支持最多 7 天的天气预报功能,预报的天数可以在 WEATHER_FORECAST_DAYS_NUM
宏定义中设置。
1
:表示只获取当天的数据。
0
或大于 7
:模组将回复错误信息,天气服务打开失败。
#define WEATHER_FORECAST_DAYS_NUM 1
模组发送的天气数据中带有天数的信息,此时 0
表示当天。
第七步:接入流服务(可选)
流服务一般用于扫地机类的 MCU,主要用于大量数据的传输。可以通过 WIFI_STREAM_ENABLE
开启。
//#define WIFI_STREAM_ENABLE
第八步:其他功能完善(可选)
其他功能可以通过完善相应函数实现。
将 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);
}
}
单片机进入 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()
函数。设备功能(DP,Data Point)主要有 6 种数据类型:
类型 | 说明 |
---|---|
bool | 通常为开关类的 DP,例如开关、ECO 和屏显。 |
enum | 通常用作有多种状态的 DP,例如工作模式、风速和风摆位置。 |
value | 通常用作数值类型的 DP,例如设定温度值、当前温度值和电量。 |
fault | 通常用于故障的上报,数据常用 bitmap 格式显示。 |
string | 通常用作字符串类型的 DP。需要以字符串形式传输的 DP 可以使用此类型。部分不便于使用 bool、enum、value 或 fault 类型的 DP,也可用此类型。 |
raw | 通常用作需要透传但对数据格式无要求(明文或者加密)的数据。发送端和接收端对数据的格式、组包和解析方式需要统一。 |
情景一:所有 DP 数据上报
在模组重启或者重新配网后,Wi-Fi 模组主动下发状态查询指令,此时需要 MCU 上报设备所有 DP 状态给 Wi-Fi 模组进行同步。
打开 protocol.c
找到函数 all_data_update(void)
。
把所有需要上报的 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);
上传设备功能(开关)状态实时状态,形成反馈。您也可以根据实际需要选择上报时机。
仅 MCU 与模组配合处理模式 工作模式需要设置配网功能及指示灯函数。
移植协议成功后,如果需要设备配网,还需要添加配网指令以及指示灯功能。配合处理模式的 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;
}
...
}
}
产测支持以下三种方式,请根据产品特性进行选择。
具体流程,请参考 生产测试说明。
请在初始化完成后再进行数据交互,避免不可预测的问题。
详情请参考 帧格式说明。
在 MCU 和模组上电后,需要进行初始化配置。初始化通信包括但不限于以下内容:
心跳包
心跳包是 MCU 和模组之间定时通信的数据,可作为验证 MCU 或者模组是否正常工作的依据。建议将 MCU 和模组上电后的第一次通信的帧作为心跳包。只有在心跳包发送和回复都正常的情况下,才可以进行通信。
查询产品信息
心跳包正常交互后,模组需要查询 MCU 固件以下信息。
设定模组的工作方式
用来设置模组工作方式,选择 MCU 与模组配合处理方式或者模组自处理方式。可根据 Wi-Fi 网络状态指示灯和模组重置按键的硬件连接位置选择。
Wi-Fi 模组初始化数据交互流程
App 和设备之间能够实现 DP 下发和上报,有两种情况:
MCU 与 Wi-Fi 模组在进行 OTA 数据交互时,数据包交互的数据量比较多,会出现一些异常情况。本小节介绍 Wi-Fi 模组的处理逻辑。
文件下载的逻辑和 OTA 实质上一样。可以将本章节中的 OTA 替换成 文件下载,作为文件下载逻辑的介绍。
OTA 过程 | 说明 |
---|---|
OTA 启动 | Wi-Fi 模组在检测到有 MCU OTA 时,会发送启动升级包。
|
OTA 数据传输 | Wi-Fi 模组在发送一包 OTA 数据之后,如果 5 秒内没有收到 MCU 的回复,会进行重发。若重发 3 次之后 MCU 依旧没有回复,就认为 OTA 失败。
|
OTA 传输完成 | 支持以下两种方式判断 OTA 传输是否完成。
|
该内容对您有帮助吗?
是意见反馈该内容对您有帮助吗?
是意见反馈