MCU SDK 移植

更新时间:2022-02-16 03:30:01下载pdf

MCU SDK 是根据您在涂鸦 IoT 开发平台定义的产品功能自动生成的 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 包含以下信息:
  • MCU 要发送至 Wi-Fi 模组初始化所需的参数。
  • SDK 裁剪所定义的宏。用户可根据需要的功能打开相应的宏定义。
  • protocol.c 中的函数声明。
system.c 串口通讯协议解析的具体实现。
system.h system.h 包含以下信息:
  • 协议命令字的定义。
  • 部分全局变量的定义。
  • system.c 中的函数声明。
wifi.h 相关宏定义。
  • 在门锁设备类 mcu_sdk 中,还有包含门锁功能相关函数的 lock_api.clock_api.h 文件。
  • 在 GPRS 设备类 mcu_sdk 中,wifi.h 文件的名称替换为 gprs.h

移植流程

  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 不一致,请在 硬件开发 > 下载资料 下载最新 SDK 开发包后重试。

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

    #define MCU_VER "1.0.0"
    
  3. 定义 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
      
  4. 选择固定配网模式。可以通过 CONFIG_MODE_CHOOSE 设置,使热点和快连配网模式同时存在或者仅保存热点模式。

    • 0:配网方式为热点和快连模式共存,此时无需切换配网方式。

      #define CONFIG_MODE_CHOOSE        0
      
    • 1:配网方式只有热点模式。

      #define CONFIG_MODE_CHOOSE        1
      
  5. 设置红外功能。可以通过 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
    
  6. 设置低功耗模式。可以通过 LONG_CONN_LOWPOWER 开启模组低功耗模式,默认关闭。

    //#define LONG_CONN_LOWPOWER        0         //关闭低功耗模式
    //#define LONG_CONN_LOWPOWER        1         //打开低功耗模式
    

第二步:设置 OTA 升级(可选)

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

    #define         SUPPORT_MCU_FIRM_UPDATE
    
  2. 定义单次发送固件包的大小。

    #ifdef SUPPORT_MCU_FIRM_UPDATE
    #define PACKAGE_SIZE                     0        //单个固件包大小为 256 字节
    //#define PACKAGE_SIZE                   1        //单个固件包大小为 512 字节
    //#define PACKAGE_SIZE                   2        //单个固件包大小为 1024 字节
    #endif
    

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

    • OTA 升级通常要对 Flash 进行读写操作。每次写入 Flash 数据后,及时进行数据读取并和写入的数据进行校验,确保写入数据的正确性。
    • 添加 OTA 超时检测,防止 OTA 失败时 MCU 一致处于数据接收状态。
    • 每个 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 次。

  1. 开启天气服务功能。定义 WEATHER_ENABLE

    //#define         WEATHER_ENABLE                  //打开天气功能
    
  2. 选择支持的天气类型。您可以在 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
    
  3. 设置支持的天气的个数。将支持的参数个数在 WEATHER_CHOOSE_CNT 中定义。

    #define         WEATHER_CHOOSE_CNT              4
    
  4. 设置预报天数。新版固件的模组将支持最多 7 天的天气预报功能,预报的天数可以在 WEATHER_FORECAST_DAYS_NUM 宏定义中设置。

    • 1:表示只获取当天的数据。

    • 0 或大于 7:模组将回复错误信息,天气服务打开失败。

      #define         WEATHER_FORECAST_DAYS_NUM       1
      

      模组发送的天气数据中带有天数的信息,此时 0 表示当天。

第七步:接入流服务(可选)

流服务一般用于扫地机类的 MCU,主要用于大量数据的传输。可以通过 WIFI_STREAM_ENABLE 开启。

//#define         WIFI_STREAM_ENABLE

第八步:其他功能完善(可选)

其他功能可以通过完善相应函数实现。

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

  1. wifi.h 文件保存至存放 Wi-Fi 相关文件的文件夹中,例如 main.c 文件夹。

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

  3. 将 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);	                                //串口发送函数
    */
    }
    
  4. 在串口接收中断服务函数里面调用 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);
    	}
    }
    
  5. 单片机进入 while(1) 循环后调用 mcu_api.c 文件内的 wifi_uart_service() 函数。main.c 中示例代码结构如下:

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

调用 DP 数据上报和下发函数

设备功能(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 模组进行同步。

  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); 上传设备功能(开关)状态实时状态,形成反馈。您也可以根据实际需要选择上报时机。

添加配网功能及指示灯函数

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 SDK 移植

  • mcu_set_wifi_mode():参数为 SMART_CONFIGAP_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 模组的数据通信

请在初始化完成后再进行数据交互,避免不可预测的问题。

帧格式

详情请参考 帧格式说明

初始化通信

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

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

心跳包

心跳包是 MCU 和模组之间定时通信的数据,可作为验证 MCU 或者模组是否正常工作的依据。建议将 MCU 和模组上电后的第一次通信的帧作为心跳包。只有在心跳包发送和回复都正常的情况下,才可以进行通信。

查询产品信息

心跳包正常交互后,模组需要查询 MCU 固件以下信息。

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

设定模组的工作方式

用来设置模组工作方式,选择 MCU 与模组配合处理方式或者模组自处理方式。可根据 Wi-Fi 网络状态指示灯和模组重置按键的硬件连接位置选择。

Wi-Fi 模组初始化数据交互流程

MCU SDK 移植

数据交互注意事项

  • 为避免不可预测的问题,请在初始化完成之后,再进行 DP 下发和上报、OTA 升级等正常数据通信。
  • 对于断电快连等 MCU 可以控制模组上下电的设备,请在设备完全初始化完成之后,再进行数据交互。

DP 上报和网络状态的关系

App 和设备之间能够实现 DP 下发和上报,有两种情况:

  • Wi-Fi 模组的网络状态为状态 5:设备连上路由和云端。此时 DP 可以正常上报。
  • Wi-Fi 模组的网络状态为状态 4:设备已连上路由器,但未连接到云端。手机可以连接到路由,此时 DP 可以在局域网进行控制。DP 也可以正常上报到 App。

OTA(或文件下载)交互

MCU 与 Wi-Fi 模组在进行 OTA 数据交互时,数据包交互的数据量比较多,会出现一些异常情况。本小节介绍 Wi-Fi 模组的处理逻辑。

文件下载的逻辑和 OTA 实质上一样。可以将本章节中的 OTA 替换成 文件下载,作为文件下载逻辑的介绍。

OTA 过程 说明
OTA 启动 Wi-Fi 模组在检测到有 MCU OTA 时,会发送启动升级包。
  • 如果 5 秒内没有收到 MCU 的回复,会进行重发。若重发 3 次之后 MCU 依旧没有回复,就认为 OTA 失败。
  • 如果固件包总字节数超出了 MCU 的处理范围,MCU 可以不做回复,让 Wi-Fi 模组自行退出 OTA。此时需检查在涂鸦 IoT 平台上传的文件是否正确。
OTA 数据传输 Wi-Fi 模组在发送一包 OTA 数据之后,如果 5 秒内没有收到 MCU 的回复,会进行重发。若重发 3 次之后 MCU 依旧没有回复,就认为 OTA 失败。
  • 如果 MCU 检测到 OTA 数据有误,可以不做回复,让 Wi-Fi 模组进行重发。此时需要注意包偏移是否正确,防止重发或漏发。
  • 如果 MCU 对 OTA 数据的处理速度太慢,会导致模组频繁重发数据,此时需要注意包偏移是否正确,防止重发或漏发。如果出现这种情况,建议调小固件包传输的大小。
OTA 传输完成 支持以下两种方式判断 OTA 传输是否完成。
  • 帧长度为 0x0004,即 OTA 数据包长度为 0。
  • 包偏移等于 Wi-Fi 模组发送升级启动帧时的固件包总长度。
建议同时使用以上两种方式检测 OTA 传输情况。