本工程使用了云米的WIFI模块,OTA通过XMODEM协议进行通信
单片机源程序如下:
- //================================================================================
- #define ALLOCATE_EXTERN
- #include "Include.h"
- //================================================================================
- void main()
- {
- IO_Init();
- SystemInit();
- IO_Init();
- Timer0_Init();
- Uart1_Init();
- EA = 1;
- WDT_INIT();
- Power_Up();
- //LVD_Init();//上电读取完Flash数据再打开低压检测,以免上一次数据未读取出来,就进入掉电而写入正确数据
- RSTFR = 0x00;
- while(1)
- {
- CLR_WDT;
- /* User code */
- Task_Handle();
- }
- }
复制代码- #include "Mi_Wifi.h"
- //命令
- #define COM_NULL 0 //无命令
- #define COM_MODEL 1 //发送设备型号
- #define COM_VERSION 2 //发送设备版本
- #define COM_BLE 3 //发送蓝牙配置
- #define COM_GET_DOWN 4 //获取下发指令
- #define COM_RESET 5 //发送复位指令
- #define COM_CONFIG 6 //发送配网指令
- #define COM_TEST 7 //发送产测指令
- #define COM_NET 8 //发送网络查询指令
- #define COM_GET_TIME 9 //发送获取网络时间指令
- #define COM_ACTIVE_UPLOAD 10 //主动上报
- #define COM_PASSIVE_UPLOAD 0X81 //被动上报,(查询或设置设置)
- #define COM_ERROR 0X82 //错误上报
- //串口发送相关变量
- u8 xdata Tx_Buf[TX_BUF_LENGTH]; //发送缓冲区
- u8 idata Tx_Index; //发送索引(中断发送时需要)
- u8 idata Tx_En; //发送允许状态,1=发送中,0=发送停止
- //命令处理相关变量
- u8 xdata Rx_Buf[RX_BUF_LENGTH]; //接收数据处理缓冲区
- u8 idata Rx_Index; //接收索引
- u8 idata Rx_Ok; //接收完成
- //其他变量
- u8 xdata Cur_Tx_Com; //当前发送的命令或数据
- u8 xdata Tx_Time; //发送循环时间
- u8 xdata Resend_Count; //重发计数
- u8 xdata Wifi_Status; //WIFI网络状态
- u8 xdata Wifi_Init_Flag; //WIFI初始化状态位
- u8 xdata Tx_Com_Loop; //发送命令循环,get_down,net,time
- //命令字符串
- u8 code Com_Null[] = "null"; //无指令
- u8 code Com_Ble[] = "ble_config set 4529 0005"; //蓝牙配置
- u8 code Com_Get_Down[] = "get_down"; //获取下行指令
- u8 code Com_Reset[] = "reboot"; //WIFI重启
- u8 code Com_Config[] = "restore"; //清除WIFI配置信息(配网)
- u8 code Com_Test[] = "factory"; //进入厂测模式
- u8 code Com_Net[] = "net"; //主动获取网络状态(注:该命令即将废弃。获取网络状态变化的更好方法,请见MIIO_net_change)
- u8 code Com_Get_Time[] = "time"; //获取网络时间
- //普通字符串
- u8 code str_ok[] = "ok";
- u8 code str_none[] = "none";
- u8 code str_down[] = "down";
- u8 code str_get_properties[] = "get_properties";
- u8 code str_set_properties[] = "set_properties";
- u8 code str_MIIO_net_change[] = "MIIO_net_change";
- u8 code str_error[] = "error";
- u8 code str_update_fw[] = "update_fw";
- u8 code str_result[] = "result";
- u8 code str_properties_changed[] = "properties_changed";
- u8 code str_result_error[] = "result "error"";
- //网络状态
- u8 code str_unprov[] = "unprov"; //未配置
- u8 code str_offline[] = "offline"; //离线
- u8 code str_local[] = "local"; //本地链接
- u8 code str_cloud[] = "cloud"; //连上云
- u8 code str_updating[] = "updating"; //升级中
- u8 code str_uap[] = "uap"; //UAP模式
- //命令表,方便发送命令
- u8 code * code Com_Table[] =
- {
- Com_Null, //下标0
- Com_Model, //下标1
- Com_Version, //下标2
- Com_Ble, //下标3
- Com_Get_Down, //下标4
- Com_Reset, //下标5
- Com_Config, //下标6
- Com_Test, //下标7
- Com_Net, //下标8
- Com_Get_Time, //下标9
- };
- //串口TX中调内调用
- void Uart_Tx()
- {
- if(Tx_En == 0)
- {
- return;
- }
-
- SBUF = Tx_Buf[Tx_Index];
-
- //判断发送结束,不作越界判断,自行把握发送数据长度
- if(Tx_Buf[Tx_Index] == '\r')
- {
- Tx_En = 0;
- }
- Tx_Index++;
- }
- //串口RX中断内调用,因为是一问一答通信方式,所以使用这种方式接收
- void Uart_Rx(u8 Data)
- {
- if(Rx_Ok)
- {
- return ;
- }
-
- Rx_Buf[Rx_Index] = Data;//保存数据
- Rx_Index++;
- //防止溢出,主动在接收缓冲区添加添加'\r'以结束接收,(一般不会出现此情况)
- if(Rx_Index == RX_BUF_LENGTH)
- {
- Rx_Buf[RX_BUF_LENGTH - 1] = '\r';
- }
- //判断帧接收完成(数据帧以字符'\r'结尾)
- if(Rx_Buf[Rx_Index - 1] == '\r')
- {
- Rx_Ok = 1;
- }
- }
- //wifi配置,需要时调用
- void Wifi_Config(u8 Config)
- {
- switch(Config)
- {
- case WIFI_CONFIG_NET:
- Wifi_Init_Flag |= 0x08;//进入配网
- break;
- case WIFI_CONFIG_TEST:
- Wifi_Init_Flag |= 0x04;//进入产测
- break;
- case WIFI_CONFIG_RESET:
- Wifi_Init_Flag |= 0x10;//复位
- break;
- default:
- break;
- }
- }
- //启动发送,利用串口发送中断发送,提高CPU使用率
- void Begin_Send()
- {
- Tx_Time = 11;//重置发送间隔时间n*10 ms
- Tx_En = 1;//置位发送中
- Tx_Index = 0;//清除发送索引
- TI = 1;//人为设置跳入中断,以启动发送
- }
- //布尔,整形,浮点值填充
- u8 Value_Fill(u8 xdata * data Tx_Ptr, Upload_Down data * data St_Temp)
- {
- if(St_Temp->Type == TYPE_BOOL)
- {
- //布尔类型数据填充上报
- if(St_Temp->Value.Long_Data)
- {
- return sprintf(Tx_Ptr, " true");
- }
- else
- {
- return sprintf(Tx_Ptr, " false");
- }
- }
- else if(St_Temp->Type == TYPE_INT)
- {
- //整形数据填充上报
- return sprintf(Tx_Ptr, " %lu", St_Temp->Value.Long_Data);
- }
- //浮点数据填充上报
- return sprintf(Tx_Ptr, " %g", St_Temp->Value.Float_Data);
- }
- //下发,查询属性处理,填写发送数据时,自行把握发送长度,否则缓冲区溢出
- void Attribute_Handle(u8 Oper, Upload_Down data * data St_Temp, u8 xdata * data Str)
- {
- u8 i;
- u8 xdata * data Tx_Ptr = &Tx_Buf;
- WIFI_DEBUG_OUT();//功能测试时使用,挂逻辑分析仪,看什么时候接收到数据,处理后返回什么数据,正常工程可屏蔽
- St_Temp->Siid = 0;
- St_Temp->Piid = 0;
- Tx_Ptr += sprintf(Tx_Ptr, str_result);
- while(*Str != '\r')//判断字符串结束
- {
- //查找字符' '(空格)
- if(*Str == ' ')
- {
- if(St_Temp->Siid == 0)
- {
- St_Temp->Siid = atol(Str);
- Str++;
- continue;
- }
- if(St_Temp->Piid == 0)
- {
- St_Temp->Piid = atol(Str);
- Str++;
- //设置字符串 down set_proterties 2 1 true\r
- //获取字符串 down set_proterties 2 1\r
- //设置值时2 1后面会有' '+参数,所以需要返回重新查找' ',而获取值时2 1结束,所以不能再返回查找' ',而是直接去处理
- if(Oper == SET_VALUE)
- {
- continue;
- }
- }
- St_Temp->Error = 0;//清除错误
- //遍历回调函数表,查找正确的处理函数
- i = 0;
- while(1)
- {
- if(Wifi_Handle_Table[i] == 0)//判断回调函数表结束
- {
- i = 0xff;
- break;//查找不到处理函数返回
- }
- if(Wifi_Handle_Table[i](Oper, St_Temp, Str + 1)) //回调函数调用
- {
- break;//正确处理后返回
- }
- i++;//指向下一个功能处理函数
- }
- Tx_Ptr += sprintf(Tx_Ptr, " %bu %bu", St_Temp->Siid, St_Temp->Piid); //填充SIID PIID
- if(i == 0xff)
- {
- //无此属性上报,格式:result siid piid -4003
- Tx_Ptr += sprintf(Tx_Ptr, " -4003");
- }
- else
- {
- //查询,成功格式:result siid piid 0 value 失败格式:result siid piid code(错误码)
- //下发,成功格式:result siid piid 0 失败格式:result siid piid code(错误码)
- Tx_Ptr += sprintf(Tx_Ptr, " %d", (s16)St_Temp->Error);//错误码填写
- if(Oper == GET_VALUE)
- {
- Tx_Ptr += Value_Fill(Tx_Ptr,St_Temp);//布尔,整形,浮点值填充
- }
- }
- //清除以重新获取SIID PIID
- St_Temp->Siid = 0;
- St_Temp->Piid = 0;
- }
- Str++;//指向下一个字符
- }
- Cur_Tx_Com = COM_PASSIVE_UPLOAD;//被动上报
- Resend_Count = 0;//重发计数清零
- *Tx_Ptr = '\r';//协议结束符
- Begin_Send();
- }
- //主动上报处理,填写发送数据时,自行把握发送长度,否则缓冲区溢出
- void Upload_Handle()
- {
- u8 i = 0;
- u8 Tx = 0;
- Upload_Down St_Temp;
- u8 xdata * data Tx_Ptr = &Tx_Buf;
- while(1)
- {
- if(Wifi_Handle_Table[i] == 0x00)//判断回调函数表结束
- {
- break;
- }
- if(Wifi_Handle_Table[i](SCAN_VALUE, &St_Temp, 0x00))//回调函数调用
- {
- //主动上报格式:properties_changed siid piid value
- if(Tx == 0)
- {
- Tx = 1;
- Tx_Ptr += sprintf(Tx_Ptr, str_properties_changed); //填充properties_changed
- }
- Tx_Ptr += sprintf(Tx_Ptr, " %bu %bu", St_Temp.Siid, St_Temp.Piid); //填充SIID PIID
- Tx_Ptr += Value_Fill(Tx_Ptr,&St_Temp);//布尔,整形,浮点值填充
- }
- i++;//指向下一个功能处理函数
- }
- if(Tx == 0)
- {
- return ;//无填充数据不进行数据发送
- }
- Cur_Tx_Com = COM_ACTIVE_UPLOAD;//主动上报
- Resend_Count = 0;//重发计数清零
- *Tx_Ptr = '\r';//协议结束符
- Begin_Send();//启动发送
- }
- //WIFI状态处理
- void Wifi_Status_Handle(u8 xdata * data String)
- {
- if(My_Strcmp(String, str_cloud, 5))
- {
- //连接上服务器
- Wifi_Status = NET_CLOUD;
- }
- else if(My_Strcmp(String, str_local, 5))
- {
- //本地连接
- Wifi_Status = NET_LOCAL;
- }
- else if(My_Strcmp(String, str_unprov, 6))
- {
- //未配置
- Wifi_Status = NET_UNPROV;
- }
- else if(My_Strcmp(String, str_offline, 7))
- {
- //离线
- Wifi_Status = NET_OFFLINE;
- }
- else if(My_Strcmp(String, str_uap, 3))
- {
- //UAP模式
- Wifi_Status = NET_UAP;
- }
- else if(My_Strcmp(String, str_updating, 8))
- {
- //升级中
- Wifi_Status = NET_UPDATEING;
- }
- }
- //WIFI下发指令处理
- void Rx_Handle()
- {
- Upload_Down St_Temp;
- u8 xdata * data Str = Rx_Buf;
- //Tx_Time = 0;//接收到回复后可以立即发送下一次数据,不管回复的是什么,,,正常使用没问题,但使用固件协议检测会失败,限制get_down指令间隔时间需要大于100ms
- if(My_Strcmp(Str, str_ok, 2))
- {
- switch(Cur_Tx_Com)
- {
- case COM_MODEL:
- Wifi_Init_Flag |= 0x80;//model
- break;
- case COM_VERSION:
- Wifi_Init_Flag |= 0x40;//版本应答
- break;
- case COM_BLE:
- Wifi_Init_Flag |= 0x20;//蓝牙应答
- break;
- case COM_RESET:
- Wifi_Init_Flag &= ~0x10;//复位应答
- break;
- case COM_CONFIG:
- Wifi_Init_Flag &= ~0x08;//配网应答
- break;
- case COM_TEST:
- Wifi_Init_Flag &= ~0x04;//测试应答
- break;
- }
- Cur_Tx_Com = COM_NULL;//清除当前发送命令
- }
- else if(My_Strcmp(Str, str_down, 4))
- {
- //下发命令解析
- Cur_Tx_Com = COM_NULL;
- Str += 5;//跳过"down "
- if(My_Strcmp(Str, str_none, 4))
- {
- //无指令
- }
- else if(My_Strcmp(Str, str_update_fw, 9))
- {
- //进入升级模式
- To_Update();
- }
- else if(My_Strcmp(Str, str_set_properties, 14))
- {
- //设置属性
- Str += 14;//跳过"set_properties "
- Attribute_Handle(SET_VALUE, &St_Temp, Str);
- }
- else if(My_Strcmp(Str, str_get_properties, 14))
- {
- //获取属性
- Str += 14;//跳过"get_properties"
- Attribute_Handle(GET_VALUE, &St_Temp, Str);
- }
- else if(My_Strcmp(Str, str_MIIO_net_change, 15))
- {
- //被动获取网络状态
- Wifi_Status_Handle(&Rx_Buf[21]);
- }
- else
- {
- //错误
- Cur_Tx_Com = COM_ERROR;//发送错误命令
- Resend_Count = 0;//重发计数清零
- sprintf (&Tx_Buf, "%s\r", str_result_error);
- Begin_Send();//启动发送
- }
- }
- else if(My_Strcmp(Str, str_error, 5))
- {
- if(Cur_Tx_Com == COM_BLE)
- {
- Wifi_Init_Flag |= 0x04;//蓝牙配置错误或WIFI单模跳过蓝牙配置
- }
- }
- else if(Cur_Tx_Com == COM_NET)
- {
- //主动获取网络状态
- Cur_Tx_Com = COM_NULL;//清除当前发送命令
- Wifi_Status_Handle(Str);
- }
- else if(Cur_Tx_Com == COM_GET_TIME)
- {
- //主动获取当前时间(一般不需要处理,如果有北京时间显示或其他依赖网络时间的应用时才需处理)
- Cur_Tx_Com = COM_NULL;//清除当前发送命令
- }
- }
- //WIFI服务程序--10毫秒调用一次
- void Wifi_Service()
- {
- if(Rx_Ok)
- {
- Rx_Handle();//调用处理
- Rx_Index = 0;
- Rx_Ok = 0;
- }
- //发送间隔时间控制
- if(Tx_Time)
- {
- Tx_Time--;
- return;
- }
- Tx_Com_Loop++;//循环
- //重发次数控制,
- if(Resend_Count >= 10)
- {
- Cur_Tx_Com = COM_NULL;//重发n次无响应后清除
- }
- if(Cur_Tx_Com != COM_NULL)
- {
- Resend_Count++;//重发计数增加
- Begin_Send();//直接重发Tx_Buf内的数据
- return ;
- }
- //发送相关信息
- if((Wifi_Init_Flag & 0x80) == 0)
- {
- Cur_Tx_Com = COM_MODEL;//发送设备MODEL
- }
- else if((Wifi_Init_Flag & 0x40) == 0)
- {
- Cur_Tx_Com = COM_VERSION;//发送程序版本号
- }
- else if((Wifi_Init_Flag & 0x20) == 0)
- {
- Cur_Tx_Com = COM_BLE;//发送ble相关
- }
- else if(Wifi_Init_Flag & 0x10)
- {
- Cur_Tx_Com = COM_RESET;//发送复位
- }
- else if(Wifi_Init_Flag & 0x08)
- {
- Cur_Tx_Com = COM_CONFIG;//发送WIFI重置,进入配网模式
- }
- else if(Wifi_Init_Flag & 0x04)
- {
- Cur_Tx_Com = COM_TEST;//发送WIFI进入产测模式
- }
- else if(Tx_Com_Loop >= 10)
- {
- Tx_Com_Loop = 0;
- Cur_Tx_Com = COM_NET;//主动获取网络状态
- }
- else if(Tx_Com_Loop == 5)
- {
- Cur_Tx_Com = COM_GET_TIME;//获取时间
- }
- else
- {
- Cur_Tx_Com = COM_GET_DOWN;
- //检测数据变化并上报数据,连接上网络才检测(连接上本地或者网络)
- if((Wifi_Status == NET_LOCAL) || (Wifi_Status == NET_CLOUD))
- {
- Upload_Handle();//调用后如果需要主动上报数据的话,Cur_Tx_Com的值应该是COM_ACTIVE_UPLOAD,并且数据已经填充进发送缓冲区了
- }
- }
-
- Resend_Count = 0;//重发计数清零
- if(Cur_Tx_Com == COM_ACTIVE_UPLOAD)
- {
- Begin_Send();//启动发送
- return;
- }
- sprintf(&Tx_Buf, "%s\r", Com_Table[Cur_Tx_Com]);//填充指令
- Begin_Send();//启动发送
- }
复制代码
HC89F3541(BOOTLOAD部分).7z
(54.02 KB, 售价: 1 E币)
HC89F3541-20210702(APP部分).7z
(150.46 KB, 售价: 1 E币)
【必读】版权免责声明
1、本主题所有言论和内容纯属会员个人意见,与本论坛立场无关。2、本站对所发内容真实性、客观性、可用性不做任何保证也不负任何责任,网友之间仅出于学习目的进行交流。3、对提供的数字内容不拥有任何权利,其版权归原著者拥有。请勿将该数字内容进行商业交易、转载等行为,该内容只为学习所提供,使用后发生的一切问题与本站无关。 4、本网站不保证本站提供的下载资源的准确性、安全性和完整性;同时本网站也不承担用户因使用这些下载资源对自己和他人造成任何形式的损失或伤害。 5、本网站所有软件和资料均为网友推荐收集整理而来,仅供学习用途使用,请务必下载后两小时内删除,禁止商用。6、如有侵犯你版权的,请及时联系我们(电子邮箱1370723259@qq.com)指出,本站将立即改正。
|
|