MCU SDK使用

MCU SDK使用说明

1.简介

根据《涂鸦串口通讯协议》、产品功能数据点自动生成的MCU程序。MCU工程师可在此基础上进行快速开发。

2.如何获取

打开开发者后台网址 https://iot.tuya.com/

如已建立完产品,在“调试流程”处 点击下载MCU SDK

如果您没有贵公司的账号,请与贵司相关领导联系

3.文件结构

文件包括:

执行文件 头文件 说明
mcu_api.c mcu_api.h 内含WiFi相关函数,客户可按需调用
protocol.c protocol.h 客户根据项目需求,需修改这个2个文件,内含数据处理函数
system.c system.h 串口通讯协议的具体实现,可以不做了解
wifi.h

4.配置

4.1 修改产品信息(必要)

打开protocol.h 在开发者后台找到“产品Key” ,请确保代码与网站所列两者一致,该PID为每个产品的唯一标识,必须检查清楚是否为您所对应的产品ID,如果不是,修改为正确的ID;或重新下载最新SDK开发包,重新进行代码移植

#define PRODUCT_KEY "ZKtkyqNRJH7h3eL1"

4.2 MCU是否需要支固件升级(可选)

如需要支持MCU固件升级,请开启该宏

#define         SUPPORT_MCU_FIRM_UPDATE

WARNING!!! ​ 当前接收缓冲区为关闭固件更新功能的大小,固件升级包为256字节

如需要开启该功能,串口接收缓冲区会变大 ​

4.3 定义收发缓存(可选)

打开protocol.h ,修改缓冲区大小:仅当传输数据长度特别长时需要修改,一般情况使用默认值即可

#ifndef SUPPORT_MCU_FIRM_UPDATE
#define WIFI_UART_QUEUE_LMT             16              //数据接收队列大小,如MCU的RAM不够,可缩小
#define WIFI_UART_RECV_BUF_LMT          24              //根据用户DP数据大小量定,必须大于24
#else
#define WIFI_UART_QUEUE_LMT             128             //数据接收队列大小,如MCU的RAM不够,可缩小
#define WIFI_UART_RECV_BUF_LMT          300             //固件升级缓冲区,需大缓存,必须大于260
#endif

4.4 配置WIFI模块重置方式(必要)

打开protocol.h

1.如果wifi指示灯和按键是接在wifi模块上的(模块自处理工作模式),那么请开启

#ifdef          WIFI_CONTROL_SELF_MODE

然后根据实际的硬件连接,将指示灯和按键所连接的GPIO脚位填入下面两行

#ifdef          WIFI_CONTROL_SELF_MODE
	#define     WF_STATE_KEY            14                //wifi模块状态指示按键,请根据实际GPIO管脚设置
	#define     WF_RESERT_KEY           0                 //wifi模块重置按键,请根据实际GPIO管脚设置
#endif

2.如果灯和按键接在MCU上(模块和MCU配合处理工作模式),请保持 define 被注释状态

//#ifdef          WIFI_CONTROL_SELF_MODE

4.5 MCU是否需要支持校时功能(可选)

如需要支持校时功能,请开启该宏 #define SUPPORT_MCU_RTC_CHECK //开启校时功能

并在Protocol.c文件内mcu_write_rtctime实现代码

mcu_write_rtctime内部有#err提示,完成函数后请删除该#err

mcu在wifi模块正确联网后可调用mcu_get_system_time()函数发起校时功能

5.移植须知

  1. MCU必须在while中直接调用mcu_api.c 内的wifi_uart_service()函数

  2. 程序正常初始化完成后,建议不进行关串口中断,如必须关中断,关中断时间必须短,关中断会引起串口数据包丢失

  3. 请勿在中断/定时器中断内调用上报函数

6.启动WIFI服务

  1. 在需要使用到wifi相关文件的文件中include "wifi.h"文件

  2. 在MCU初始化调用mcu_api.c文件中的wifi_protocol_init()函数

  3. 将串口单字节发送函数填入protocol.c文件中uart_transmit_output函数内,并删除#error

  4. 在串口接收函数里面调用mcu_api.c文件内的uart_receive_input函数,并将接收到的字符作为参数传入

  5. 单片机进入while循环后调用mcu_api.c文件内的wifi_uart_service()函数

例如,在main.c中添加如下代码结构:

include "wifi.h"
...
void main(void)
{
	wifi_protocol_init();
	...
	while(1)
	{
		wifi_uart_service();
		...
	}
}

7.功能说明

7.1 功能点定义

在protocol.c文件中,确认下发结构体download_cmd内dpID及dp类型,如:

此为自动生成代码,如在开发平台有相关修改请重新下载MCU_SDK

#define DPID_SWITCH                     1                       //可读/可写
#define DPID_TEMPER_SET                 2                       //可读/可写

const DOWNLOAD_CMD_S download_cmd[] = 
{
  {DPID_SWITCH,                 DP_TYPE_BOOL},
  {DPID_TEMPER_SET,             DP_TYPE_VALUE},
};

7.2 MCU串口数据接收处理函数

在protocol.c文件dp_download_switch_1_handle()函数(根据dp点自动生成)内填入dp对应处理函数

static unsigned char dp_download_switch_1_handle(const unsigned char value[], unsigned short length)
{
	//示例:当前DP类型为BOOL
	unsigned char ret;
	//0:关/1:开
	unsigned char switch_1;

	switch_1 = mcu_get_dp_download_bool(value,length);
	if(switch_1 == 0)
	{
		//开关关
	}
	else
	{
		//开关开
	}

	//处理完DP数据后应有反馈
	ret = mcu_dp_bool_update(DPID_SWITCH_1,switch_1);
	if(ret == SUCCESS)
		return SUCCESS;
	else
		return ERROR;
	}

上述函数解析功能点之后,映射到相关执行函数,完成具体动作。本例为接收到开关数据,完成开关动作后调用mcu_dp_bool_update(DPID_SWITCH_1,switch_1);上传功能点(开关)状态,此接收处理函数已经自动调用改函数;当设备状态在非APP控制下发生变化,MCU中需要调用mcu_dp_bool_update(DPID_SWITCH_1,switch_1);上传功能点(开关)状态实时状态(7.4 单个数据上报中详解)

7.3 数据接收调试

  1. 使用涂鸦串口调试助手,完成“7.2配置验证”后,点击“添加命令”,可实现同时发送多条命令
  2. 点击命令下发
  3. 上一页添加的函数将会收到刚才下发的数据

7.4 单个数据上报

  1. 在mcu状态发生变化时,用户需要主动上报。
  2. 如果倒计时存在,那么需要每分钟上报倒计时剩余时间

上报格式为 mcu_dp_xxxx_updata(DPID_X,n),DPID_X与7.1功能点定义一致。
例如:

  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型数据上报
  mcu_dp_raw_update(DPID_SWITCH,1);                        //RAW型数据上报
  mcu_dp_bitmap_update(DPID_TEMPER_SET,25);                //故障型数据上报
  mcu_dp_enum_update(DPID_DAY,"1234",4);                   //枚举型数据上报

  //示例
  //可读可写型
  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型数据上报
  mcu_dp_bool_update(DPID_LOOK,0);
  mcu_dp_value_update(DPID_APPOINT,38);
  mcu_dp_string_update(DPID_WEEK,"456",3);

  //只读
  update_temper_handle();
  update_error_handle();

7.5 所有数据上报

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

  1. 打开protocol.c 找到函数all_data_update(void)
  2. 把所有需要上报的数据点在这个函数中罗列出
  3. wifi_sdk会在特定时刻(如开机)调用这个函数,以获取各个功能当前状态

用户请勿调用all_data_update(void)函数,该函数会在特定时间主动调用

void all_data_update(void)
{
  //请自行完成所有dp点数据上报
  /*
  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型数据上报
  mcu_dp_raw_update(DPID_SWITCH,1);                        //RAW型数据上报
  mcu_dp_bitmap_update(DPID_TEMPER_SET,25);                //故障型数据上报
  mcu_dp_enum_update(DPID_DAY,"1234",4);                   //枚举型数据上报
  */
  //示例
  //可读可写型
  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型数据上报
  mcu_dp_bool_update(DPID_LOOK,0);
  mcu_dp_value_update(DPID_APPOINT,38);
  mcu_dp_string_update(DPID_WEEK,"456",3);

  //只读
  update_temper_handle();
  update_error_handle();
}

7.6 重置WIFI

当wifi模块要连接新的路由器时,需要重置WIFI,调用下述函数:

mcu_reset_wifi();	

并可调用mcu_get_reset_wifi_flag()函数返回复位wifi结果;

或调用设置wifi模式mcu_api.c 文件内的:

mcu_set_wifi_mode(WIFI_CONFIG_E mode);

并可调用mcu_get_wifi_work_state()函数返回设置wifi结果.

7.7 重置WIFI–获取状态

说明:

  1. WIFI工作状态:1 smartconfig配置状态 2 AP配置状态 3 WIFI配置成功但未连上路由器 4 WIFI配置成功且连上路由器。 “模块自处理”工作模式相应的LED显示分别为:1 间隔闪烁250ms;2 间隔闪烁1500ms;3 长暗状态;4 长亮状态
  2. 当模块检测到MCU重启或MCU断线再上线的过程,则主动上报WIFI状态至MCU
  3. 当模块检测到WIFI状态发生变化,则主动上报WIFI状态至MCU
  4. 如设置模块工作模式为“模块自处理”,则MCU无需实现该协议

调用函数mcu_get_wifi_work_state()获取连接状态,通常使用方法如下:

void main(void)
{	
	...	

	while(1)
	{
		switch(mcu_get_wifi_work_state())
		{
			case SMART_CONFIG_STATE:
			//smart config 配置状态 LED快闪 ,led闪烁请用户完成
			break;
			case AP_STATE:
			//AP配置状态 LED慢闪
			break;
			case WIFI_CONNECTING:
			//WIFI配置完成,正在连接路由器,LED常暗
			break;
			case WIFI_CONNECTING:
			//路由器连接成功 LED常亮
			break;
			default:break;
		}	
		...	

	}	
}

7.8 MCU在线升级

1.打开protocol.h,开启宏定义,设置MCU版本号

#define         SUPPORT_MCU_FIRM_UPDATE                 //开启MCU固件升级功能(默认关闭)
#define MCU_VER "1.0.0"                                 //用户的软件版本,用于MCU固件升级,MCU升级版本需修改

如果数据包较大请根据实际需求调整缓冲区大小:

WIFI_UART_RECV_BUF_LMT          300            //固件升级缓冲区,需大缓存,必须大于260

相应的升级函数为protocol.c中:

/*****************************************************************************
函数名称 : mcu_firm_update_handle
功能描述 : MCU进入固件升级模式
输入参数 : value:固件缓冲区
           position:当前数据包在于固件位置
           length:当前固件包长度(固件包长度为0时,表示固件包发送完成)
返回参数 : 无
使用说明 : MCU需要自行实现该功能
*****************************************************************************/
unsigned char mcu_firm_update_handle(const unsigned char value[],unsigned short position,unsigned short length)
{
  #error "请自行完成MCU固件升级代码,完成后请删除该行"
  if(length == 0)
  {
    //固件数据发送完成
    
  }
  else
  {
    //固件数据处理
  }
  
  return SUCCESS;
}

MCU可调用mcu_api.c 文件内的mcu_firm_update_query()函数获取当前MCU固件更新情况

注:升级过程由手机发起,调试时可使用涂鸦串口调试助手点击升级启动

7.9 获取在线时间

1.MCU需要获取网络时间,打开protocol.h开启下面的define

#define         SUPPORT_MCU_RTC_CHECK                //开启校时功能

2.调用mcu_get_system_time(void)启动获取流程

3.获取到的时间会被送到protocol.c中的函数 mcu_write_rtctime(),请自行完成获取时间后存入MCU的操作

void mcu_write_rtctime(unsigned char time[])
{
	#error "请自行完成RTC时钟写入代码,并删除该行"
	/*
	time[0]为是否获取时间成功标志,为 0 表示失败,为 1表示成功
	time[1] 为 年 份 , 0x00 表 示2000 年
	time[2]为月份,从 1 开始到12 结束
 	time[3]为日期,从 1 开始到31 结束
	time[4]为时钟,从 0 开始到23 结束
	time[5]为分钟,从 0 开始到59 结束
	time[6]为秒钟,从 0 开始到59 结束
	time[7]为星期,从 1 开始到 7 结束,1代表星期一
	*/
	if(time[0] == 1)
	{
		//正确接收到wifi模块返回的本地时钟数据 

	}
	else
	{
		//获取本地时钟数据出错,有可能是当前wifi模块未联网
	}
}

7.10 产测

1.MCU需要支持wifi功能测试,打开protocol.h开启下面的define

#define         WIFI_TEST_ENABLE                //开启WIFI产测功能

2.MCU在需要wifi功能测试处调用mcu_api.c文件内 ​ mcu_start_wifitest()

3.在protocol.c文件wifi_test_result函数内查看测试结果, ​ void wifi_test_result(unsigned char result,unsigned char rssi) { #error “请自行实现wifi功能测试成功/失败代码,完成后请删除该行” if(result == 0) { //测试失败 if(rssi == 0x00) { //未扫描到名称为tuya_mdev_test路由器,请检查 } else if(rssi == 0x01) { //模块未授权 } } else { //测试成功 //rssi为信号强度(0-100, 0信号最差,100信号最强) } }

8.配置验证

使用WiFi模拟器进行MCU程序调试与验证,详细说明 WiFi模拟器使用说明 (WiFi模拟器又名涂鸦串口调试助手)

8.1验证

  1. 连接单片机的串口和电脑的串口

  2. 开发者后台下载涂鸦串口调试助手.exe 和 功能点调试文件(config.json)

  3. 打开涂鸦串口调试助手.exe

  4. 设定串口号后点击“打开串口”

  5. 点击浏览,打开刚下载的config.json

  6. 点击”开启心跳检测”

8.2验证成功

串口配置正常的返回数据 恭喜! MCU SDK移植成功

8.3错误分析

串口配置异常的返回数据

原因可能会有如下几种情况:

  • 电路板未上电
  • 串口号选错
  • 串口tx,rx 接反
  • 代码配置错误,请检查代码
  • 硬件配置错误,检查时钟是否准,波特率是否为9600

如上述几项均无法解决问题,可与我司联系 ​

400-881-8611