1200字范文,内容丰富有趣,写作的好帮手!
1200字范文 > 【单片机笔记】STM32+ESP8266通过AT指令WIFI连接阿里云MQTT服务器

【单片机笔记】STM32+ESP8266通过AT指令WIFI连接阿里云MQTT服务器

时间:2019-02-07 05:26:22

相关推荐

【单片机笔记】STM32+ESP8266通过AT指令WIFI连接阿里云MQTT服务器

上一篇使用USB转串口的方式通过ESP8266wifi模块的方式成功连接上了阿里云,现在就要通过单片机来替换电脑上位机了,这样单片机自动的去调用并发送串口数据更加方便,也更加符合一个产品的开发。板载的传感器有NTC温度,光强,这两个主要用来设备上传到平台,另外一个是RGB的灯,这个主要是用来平台下发设备的接收和解析。这里为了直观我直接用串口打印出来。只要数据部分对了其他的都好说。

网页上的运行状态图

温度曲线图

光强曲线图

颜色色值曲线图,这里其实是通过单片机随机函数生成的一个数据,所以变化也是比较大的,为了直观我也把这个值上传到平台。

平台下发数据、设备解析测试。

这里要注意一下,最开始我通过strstr方法来找出关键字“hue”,但是测了下不行,后来找到原因,估计是平台下发的josn数据包中含有多个0,比方说设备收到的是“123456\0789”,这里的‘\0’其实hex就是0x00,也正好是字符串的结尾标识符,这样通过strstr要找出“789”就找不到的,因为再者之前字符串就认为已经是断了,后来自己写了一个查找函数,解决!

网络部分和MQTT部分我都做了封装,非常方便参考和移植,不多说直接贴上代码:

main.c部分

#include "fy_includes.h"#include "fy_tlink.h"/*晶振使用的是16M 其他频率在system_stm32f10x.c中修改使用printf需要在fy_includes.h修改串口重定向为#define PRINTF_USART USART1 */_typdef_adc _adc;u16 adc_light;u16 adc_ntc;u16 battery;float temperature;u8 led_sta;u8 sta;void Adc_GetValue(void);u8 txbuf[256];u8 rxbuf[256];char mqtt_message[200];void Mqtt_Progress(u8 *buf,u16 len);void UsartTrance(void){while(1){Led_Tog();Delay_ms(500);}}int main(void){u8 cnt_2s=0;u16 cnt_5s=0;NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);Systick_Configuration();Led_Configuration();//UsartTrance();Key_Configuration();Adc_Configuration();Adc_DMA_Configuration((u32)&_adc.buf,ADC_FILTER*ADC_CH_MAX);Usart1_Configuration(115200);Usart2_Configuration(115200);Oled_Configuration();Usart1_SendString(" usart1 is ok!\r\n");//Usart2_SendString(" usart2 is ok!\r\n");Delay_ms(200);//UsartTrance();sta=0;//检查ESP8266if(_net.Init(rxbuf,sizeof(rxbuf),txbuf,sizeof(txbuf))!=0){Oled_ShowString(0,0*16,"Net Init OK!",8,16,1);//printf("Net Init OK!\r\n");sta++;}else{Oled_ShowString(0,0*16,"Net Init Error!",8,16,1);//printf("Net Init Error!\r\n");sta=0;}Oled_RefreshGram();if(sta==1){//连接热点if(_net.ConnectAP("ssid","password")!=0){Oled_ShowString(0,1*16,"Conncet AP OK!",8,16,1);//printf("Conncet AP OK!\r\n");sta++;}else {Oled_ShowString(0,1*16,"Conncet AP Error!",8,16,1);//printf("Conncet AP Error!\r\n");sta=0;}Oled_RefreshGram();}if(sta==2){//连接TCPif(_net.ConnectServer("TCP","a1ugBNniFGU.iot-as--",1883)!=0) {Oled_ShowString(0,2*16,"Conet Server OK!",8,16,1);//printf("Conncet Server OK!\r\n");sta++;}else{Oled_ShowString(0,2*16,"Server Error!",8,16,1);//printf("Conncet Server Error!\r\n");sta=0;}Oled_RefreshGram();}if(sta==3){//登录MQTT_mqtt.Init(rxbuf,sizeof(rxbuf),txbuf,sizeof(txbuf));if(_mqtt.Connect("123456|securemode=3,signmethod=hmacsha1,timestamp=789|",//ClientID"FY-STM32&a1ugBNniFGU",//Username"b447b9f26938d8eba6b2a4878066aae91839600c"//Password) != 0){Oled_ShowString(0,3*16,"Enter MQTT OK!",8,16,1);//printf("Enter MQTT OK!\r\n");sta++;}else{Oled_ShowString(0,3*16,"Enter MQTT Error",8,16,1);//printf("Enter MQTT Error!\r\n");sta=0;}Oled_RefreshGram();}if(sta==4){Oled_Clear();//订阅主题if(_mqtt.SubscribeTopic("/sys/a1ugBNniFGU/FY-STM32/thing/service/property/set",0,1) != 0){Oled_ShowString(0,0*16,"Subscribe OK!",8,16,1);//printf("SubscribeTopic OK!\r\n");}else{Oled_ShowString(0,0*16,"Subscribe Error!",8,16,1);//printf("SubscribeTopic Error!\r\n");}Oled_RefreshGram();}Delay_ms(1000);Oled_Clear();Oled_ShowString(32,0*16,"Mars Tech",8,16,1);Oled_ShowString(0,1*16," VCC: 0000 mV",8,16,1);Oled_ShowString(0,2*16,"Temp: 00.0 C",8,16,1);Oled_ShowString(0,3*16," LUX: 0000 ",8,16,1);Oled_RefreshGram();sta = 0;while(1){if(++cnt_2s>=200){cnt_2s=0;Adc_GetValue();temperature = Ntc_GetTemp(adc_ntc)*0.1f;Oled_ShowNum(8*6,1*16,battery,4,8,16);Oled_ShowNum(8*6,2*16,(u8)temperature,2,8,16);Oled_ShowNum(8*6+3*8,2*16,(u16)(temperature*10)%10,1,8,16);Oled_ShowNum(8*6,3*16,adc_light,4,8,16);Oled_RefreshGram();}if(++cnt_5s>=500){//cnt_5s=0;sprintf(mqtt_message,"{\"method\":\"thing.service.property.set\",\"id\":\"630262306\",\"params\":{\\"CurrentTemperature\":%.1f,\\"hue\":%d,\\"mlux\":%d\},\"version\":\"1.0.0\"}",temperature,rand()%0x00ffffff,adc_light);_mqtt.PublishData("/sys/a1ugBNniFGU/FY-STM32/thing/event/property/post",mqtt_message,0);}if(_mqtt.rxlen){Mqtt_Progress(_mqtt.rxbuf,_mqtt.rxlen);memset(_mqtt.rxbuf,0,_mqtt.rxlen);_mqtt.rxlen = 0;}Delay_ms(10); }}void Adc_GetValue(void){u32 sum[ADC_CH_MAX];memset(sum,0,sizeof(sum));for(u8 ch=0; ch<ADC_CH_MAX; ch++){for(u8 filter=0; filter<ADC_FILTER; filter++){sum[ch] += _adc.buf[filter][ch];//计算累加和}}adc_light = sum[ADC_LIGHT]/ADC_FILTER;adc_ntc = sum[ADC_NTC]/ADC_FILTER;battery = sum[ADC_VCC]/ADC_FILTER*3300/4095*11; //mV}u8 temp;void USART2_IRQHandler(void){static u8 rxlen = 0;if(USART_GetITStatus(USART2, USART_IT_RXNE) != RESET) //判断接收数据寄存器是否有数据{temp = USART2->DR;//USART1->DR = temp;//这里用作串口1打印WIFI模块发送的数据if(rxlen>=255) rxlen=0;rxbuf[rxlen++] = temp;rxlen%=sizeof(rxbuf);}if(USART_GetITStatus(USART2, USART_IT_IDLE)){temp = USART2->DR;temp = USART2->SR;_mqtt.rxlen = rxlen;//Mqtt_Progress(rxbuf,rxlen);//主循环做异步处理rxlen=0;}}//void *StrStr(void *dest,void *src);u8 *p;void Mqtt_Progress(u8 *buf,u16 len){ char *keyStr = "hue";u8 keyStrLen = strlen(keyStr)-1;u8 i,j;for(i=0;i<len-keyStrLen;i++){for(j=0;j<keyStrLen;j++){if(buf[i+j] != keyStr[j])break;}if(j==keyStrLen) break;}if(i<=len-keyStrLen){u16 temp = 0;p = &buf[i];while(*p != ':') p++;p++;while(*p != '}'){temp = temp *10 + (*p - '0');p++;}printf("receive message, hue = %d \r\n",temp);//Usart1_SendBuf(buf,len); }}/*********************************************END OF FILE********************************************/

net.c部分

#include "fy_network.h"//#define _DEBUG_NETstatic u8 Check(void);static u8 Init(u8 *prx,u16 rxlen,u8 *ptx,u16 txlen);static void Restore(void);static u8 ConnectAP(char* ssid,char* pswd);static u8 ConnectServer(char* mode,char* ip,u16 port);static u8 DisconnectServer(void);static u8 OpenTransmission(void);static void CloseTransmission(void);static void SendString(char* str);static void SendBuf(u8* buf,u16 len);_typdef_net _net={0,0,0,0,Check,Init,Restore,ConnectAP,ConnectServer,DisconnectServer,OpenTransmission,CloseTransmission,SendString,SendBuf};/*** 功能:初始化ESP8266* 参数:None* 返回值:初始化结果,非0为初始化成功,0为失败*/static u8 Init(u8 *prx,u16 rxlen,u8 *ptx,u16 txlen){_net.rxbuf = prx;_net.rxlen = rxlen;_net.txbuf = ptx;_net.txlen = txlen;memset(_net.rxbuf,0,_net.rxlen);memset(_net.txbuf,0,_net.txlen);_net.CloseTransmission();//退出透传 Delay_ms(500); _net.SendString("AT+RST\r\n"); //重启ESP8266 Delay_ms(800);if(_net.Check()==0) //使用AT指令检查ESP8266是否存在{return 0;}memset(_net.rxbuf,0,_net.rxlen); //清空接收缓冲_net.SendString("ATE0\r\n");//关闭回显 if(FindStr((char*)_net.rxbuf,"OK",500)==0) //设置不成功{return 0;}return 1;//设置成功}/*** 功能:恢复出厂设置* 参数:None* 返回值:None* 说明:此时ESP8266中的用户设置将全部丢失回复成出厂状态*/static void Restore(void){_net.CloseTransmission(); //退出透传Delay_ms(500);_net.SendString("AT+RESTORE\r\n");//恢复出厂 // NVIC_SystemReset(); //同时重启单片机 }/*** 功能:检查ESP8266是否正常* 参数:None* 返回值:ESP8266返回状态* 非0 ESP8266正常* 0 ESP8266有问题 */static u8 Check(void){u8 check_cnt=5;while(check_cnt--){memset(_net.rxbuf,0,_net.rxlen); //清空接收缓冲_net.SendString("AT\r\n");//发送AT握手指令if(FindStr((char*)_net.rxbuf,"OK",200) != 0){return 1;}}return 0;}/*** 功能:连接热点* 参数:* ssid:热点名* pwd:热点密码* 返回值:* 连接结果,非0连接成功,0连接失败* 说明: * 失败的原因有以下几种(UART通信和ESP8266正常情况下)* 1. WIFI名和密码不正确* 2. 路由器连接设备太多,未能给ESP8266分配IP*/static u8 ConnectAP(char* ssid,char* pswd){u8 cnt=5;while(cnt--){memset(_net.rxbuf,0,_net.rxlen);_net.SendString("AT+CWMODE_CUR=1\r\n"); //设置为STATION模式if(FindStr((char*)_net.rxbuf,"OK",200) != 0){break;} }if(cnt == 0) return 0;cnt=2;while(cnt--){memset(_net.txbuf,0,_net.txlen); //清空发送缓冲memset(_net.rxbuf,0,_net.rxlen); //清空接收缓冲sprintf((char*)_net.txbuf,"AT+CWJAP_CUR=\"%s\",\"%s\"\r\n",ssid,pswd);//连接目标AP_net.SendString((char*)_net.txbuf);if(FindStr((char*)_net.rxbuf,"OK",8000)!=0) //连接成功且分配到IP{return 1;}}return 0;}/*** 功能:使用指定协议(TCP/UDP)连接到服务器* 参数:* mode:协议类型 "TCP","UDP"* ip:目标服务器IP* port:目标是服务器端口号* 返回值:* 连接结果,非0连接成功,0连接失败* 说明: * 失败的原因有以下几种(UART通信和ESP8266正常情况下)* 1. 远程服务器IP和端口号有误* 2. 未连接AP* 3. 服务器端禁止添加(一般不会发生)*/static u8 ConnectServer(char* mode,char* ip,u16 port){u8 cnt;_net.CloseTransmission(); //多次连接需退出透传Delay_ms(500);//连接服务器cnt=2;while(cnt--){memset(_net.rxbuf,0,_net.rxlen);memset(_net.txbuf,0,_net.txlen); sprintf((char*)_net.txbuf,"AT+CIPSTART=\"%s\",\"%s\",%d\r\n",mode,ip,port);_net.SendString((char*)_net.txbuf);if(FindStr((char*)_net.rxbuf,"CONNECT",8000) !=0 ){break;}}if(cnt == 0) return 0;//设置透传模式if(_net.OpenTransmission()==0) return 0;//开启发送状态cnt=2;while(cnt--){memset(_net.rxbuf,0,_net.rxlen); _net.SendString("AT+CIPSEND\r\n");//开始处于透传发送状态if(FindStr((char*)_net.rxbuf,">",200)!=0){return 1;}}return 0;}/*** 功能:主动和服务器断开连接* 参数:None* 返回值:* 连接结果,非0断开成功,0断开失败*/static u8 DisconnectServer(void){u8 cnt;_net.CloseTransmission();//退出透传Delay_ms(500);while(cnt--){memset(_net.rxbuf,0,_net.rxlen); _net.SendString("AT+CIPCLOSE\r\n");//关闭链接if(FindStr((char*)_net.rxbuf,"CLOSED",200)!=0)//操作成功,和服务器成功断开{break;}}if(cnt) return 1;return 0;}/*** 功能:透传模式下的数据发送函数* 参数:*buffer:待发送数据* 返回值:None*/static void SendBuf(u8* buf,u16 len){memset(_net.rxbuf,0,_net.rxlen);#ifdef _DEBUG_NETUsart1_SendBuf(buf,len);#endifNet_SendBuf(buf,len);}/*** 功能:透传模式下的数据发送函数* 参数:*buffer:待发送数据* 返回值:None*/static void SendString(char* str){memset(_net.rxbuf,0,_net.rxlen);#ifdef _DEBUG_NETUsart1_SendString(str);#endifNet_SendString(str);}static u8 OpenTransmission(void){//设置透传模式u8 cnt=2;while(cnt--){memset(_net.rxbuf,0,_net.rxlen); _net.SendString("AT+CIPMODE=1\r\n"); if(FindStr((char*)_net.rxbuf,"OK",200)!=0){return 1;}}return 0;}//退出透传static void CloseTransmission(void){_net.SendString("+++"); Delay_ms(50);_net.SendString("+++"); Delay_ms(50);}/*********************************************END OF FILE********************************************/

net.h部分

#ifndef __FY_NETWORK_H#define __FY_NETWORK_H#include "fy_includes.h"/*连接AP宏定义*/#define SSID "ssid"#define PWD "password"/*连接服务器宏定义*/#define TCP "TCP"#define UDP "UDP"#define IP "122.114.122.174"#define PORT 40915#define Net_SendString(str) Usart2_SendString(str)#define Net_SendBuf(buf,len) Usart2_SendBuf(buf,len)typedef struct{u8 *rxbuf;u16 rxlen;u8 *txbuf;u16 txlen;u8 (*Check)(void);u8 (*Init)(u8 *prx,u16 rxlen,u8 *ptx,u16 txlen);void (*Restore)(void);u8 (*ConnectAP)(char *ssid,char *pswd);u8 (*ConnectServer)(char* mode,char *ip,u16 port);u8 (*DisconnectServer)(void);u8 (*OpenTransmission)(void);void (*CloseTransmission)(void);void (*SendString)(char *str);void (*SendBuf)(u8 *buf,u16 len);}_typdef_net;extern _typdef_net _net;#endif/*********************************************END OF FILE********************************************/

mqtt.c部分

#include "fy_mqtt.h"//#define _DEBUG_MQTTtypedef enum{//名字值 报文流动方向 描述M_RESERVED1=0,//禁止保留M_CONNECT,//客户端到服务端客户端请求连接服务端M_CONNACK,//服务端到客户端连接报文确认M_PUBLISH,//两个方向都允许发布消息M_PUBACK,//两个方向都允许QoS 1消息发布收到确认M_PUBREC,//两个方向都允许发布收到(保证交付第一步)M_PUBREL,//两个方向都允许发布释放(保证交付第二步)M_PUBCOMP,//两个方向都允许QoS 2消息发布完成(保证交互第三步)M_SUBSCRIBE,//客户端到服务端客户端订阅请求M_SUBACK,//服务端到客户端订阅请求报文确认M_UNSUBSCRIBE,//客户端到服务端客户端取消订阅请求M_UNSUBACK,//服务端到客户端取消订阅报文确认M_PINGREQ,//客户端到服务端心跳请求M_PINGRESP,//服务端到客户端心跳响应M_DISCONNECT,//客户端到服务端客户端断开连接M_RESERVED2,//禁止保留}_typdef_mqtt_message;//连接成功服务器回应 20 02 00 00//客户端主动断开连接 e0 00const u8 parket_connetAck[] = {0x20,0x02,0x00,0x00};const u8 parket_disconnet[] = {0xe0,0x00};const u8 parket_heart[] = {0xc0,0x00};const u8 parket_heart_reply[] = {0xc0,0x00};const u8 parket_subAck[] = {0x90,0x03};static void Mqtt_SendBuf(u8 *buf,u16 len);static void Init(u8 *prx,u16 rxlen,u8 *ptx,u16 txlen);static u8 Connect(char *ClientID,char *Username,char *Password);static u8 SubscribeTopic(char *topic,u8 qos,u8 whether);static u8 PublishData(char *topic, char *message, u8 qos);static void SentHeart(void);static void Disconnect(void);_typdef_mqtt _mqtt = {0,0,0,0,Init,Connect,SubscribeTopic,PublishData,SentHeart,Disconnect,};static void Init(u8 *prx,u16 rxlen,u8 *ptx,u16 txlen){_mqtt.rxbuf = prx;_mqtt.rxlen = rxlen;_mqtt.txbuf = ptx;_mqtt.txlen = txlen;memset(_mqtt.rxbuf,0,_mqtt.rxlen);memset(_mqtt.txbuf,0,_mqtt.txlen);//无条件先主动断开_mqtt.Disconnect();Delay_ms(100);_mqtt.Disconnect();Delay_ms(100);}//连接服务器的打包函数static u8 Connect(char *ClientID,char *Username,char *Password){int ClientIDLen = strlen(ClientID);int UsernameLen = strlen(Username);int PasswordLen = strlen(Password);int DataLen;_mqtt.txlen=0;//可变报头+Payload 每个字段包含两个字节的长度标识DataLen = 10 + (ClientIDLen+2) + (UsernameLen+2) + (PasswordLen+2);//固定报头//控制报文类型_mqtt.txbuf[_mqtt.txlen++] = 0x10;//MQTT Message Type CONNECT//剩余长度(不包括固定头部)do{u8 encodedByte = DataLen % 128;DataLen = DataLen / 128;// if there are more data to encode, set the top bit of this byteif ( DataLen > 0 )encodedByte = encodedByte | 128;_mqtt.txbuf[_mqtt.txlen++] = encodedByte;}while ( DataLen > 0 );//可变报头//协议名_mqtt.txbuf[_mqtt.txlen++] = 0; // Protocol Name Length MSB _mqtt.txbuf[_mqtt.txlen++] = 4; // Protocol Name Length LSB _mqtt.txbuf[_mqtt.txlen++] = 'M'; // ASCII Code for M _mqtt.txbuf[_mqtt.txlen++] = 'Q'; // ASCII Code for Q _mqtt.txbuf[_mqtt.txlen++] = 'T'; // ASCII Code for T _mqtt.txbuf[_mqtt.txlen++] = 'T'; // ASCII Code for T //协议级别_mqtt.txbuf[_mqtt.txlen++] = 4; // MQTT Protocol version = 4 //连接标志_mqtt.txbuf[_mqtt.txlen++] = 0xc2; // conn flags _mqtt.txbuf[_mqtt.txlen++] = 0; // Keep-alive Time Length MSB _mqtt.txbuf[_mqtt.txlen++] = 60; // Keep-alive Time Length LSB 60S心跳包 _mqtt.txbuf[_mqtt.txlen++] = BYTE1(ClientIDLen);// Client ID length MSB _mqtt.txbuf[_mqtt.txlen++] = BYTE0(ClientIDLen);// Client ID length LSB memcpy(&_mqtt.txbuf[_mqtt.txlen],ClientID,ClientIDLen);_mqtt.txlen += ClientIDLen;if(UsernameLen > 0){ _mqtt.txbuf[_mqtt.txlen++] = BYTE1(UsernameLen);//username length MSB _mqtt.txbuf[_mqtt.txlen++] = BYTE0(UsernameLen); //username length LSB memcpy(&_mqtt.txbuf[_mqtt.txlen],Username,UsernameLen);_mqtt.txlen += UsernameLen;}if(PasswordLen > 0){ _mqtt.txbuf[_mqtt.txlen++] = BYTE1(PasswordLen);//password length MSB _mqtt.txbuf[_mqtt.txlen++] = BYTE0(PasswordLen); //password length LSB memcpy(&_mqtt.txbuf[_mqtt.txlen],Password,PasswordLen);_mqtt.txlen += PasswordLen; } u8 cnt=2;u8 wait;while(cnt--){memset(_mqtt.rxbuf,0,_mqtt.rxlen);Mqtt_SendBuf(_mqtt.txbuf,_mqtt.txlen);wait=30;//等待3s时间while(wait--){//CONNECTif(_mqtt.rxbuf[0]==parket_connetAck[0] && _mqtt.rxbuf[1]==parket_connetAck[1]) //连接成功 {return 1;//连接成功}Delay_ms(100);}}return 0;}//MQTT订阅/取消订阅数据打包函数//topic 主题 //qos 消息等级 //whether订阅/取消订阅请求包static u8 SubscribeTopic(char *topic,u8 qos,u8 whether){ _mqtt.txlen=0;int topiclen = strlen(topic);int DataLen = 2 + (topiclen+2) + (whether?1:0);//可变报头的长度(2字节)加上有效载荷的长度//固定报头//控制报文类型if(whether) _mqtt.txbuf[_mqtt.txlen++] = 0x82; //消息类型和标志订阅else_mqtt.txbuf[_mqtt.txlen++] = 0xA2; //取消订阅//剩余长度do{u8 encodedByte = DataLen % 128;DataLen = DataLen / 128;// if there are more data to encode, set the top bit of this byteif ( DataLen > 0 )encodedByte = encodedByte | 128;_mqtt.txbuf[_mqtt.txlen++] = encodedByte;}while ( DataLen > 0 );//可变报头_mqtt.txbuf[_mqtt.txlen++] = 0;//消息标识符 MSB_mqtt.txbuf[_mqtt.txlen++] = 0x01; //消息标识符 LSB//有效载荷_mqtt.txbuf[_mqtt.txlen++] = BYTE1(topiclen);//主题长度 MSB_mqtt.txbuf[_mqtt.txlen++] = BYTE0(topiclen);//主题长度 LSB memcpy(&_mqtt.txbuf[_mqtt.txlen],topic,topiclen);_mqtt.txlen += topiclen;if(whether){_mqtt.txbuf[_mqtt.txlen++] = qos;//QoS级别}u8 cnt=2;u8 wait;while(cnt--){memset(_mqtt.rxbuf,0,_mqtt.rxlen);Mqtt_SendBuf(_mqtt.txbuf,_mqtt.txlen);wait=30;//等待3s时间while(wait--){if(_mqtt.rxbuf[0]==parket_subAck[0] && _mqtt.rxbuf[1]==parket_subAck[1]) //订阅成功 {return 1;//订阅成功}Delay_ms(100);}}if(cnt) return 1;//订阅成功return 0;}//MQTT发布数据打包函数//topic 主题 //message 消息//qos消息等级 static u8 PublishData(char *topic, char *message, u8 qos){ int topicLength = strlen(topic); int messageLength = strlen(message);static u16 id=0;int DataLen;_mqtt.txlen=0;//有效载荷的长度这样计算:用固定报头中的剩余长度字段的值减去可变报头的长度//QOS为0时没有标识符//数据长度 主题名 报文标识符 有效载荷if(qos)DataLen = (2+topicLength) + 2 + messageLength; elseDataLen = (2+topicLength) + messageLength; //固定报头//控制报文类型_mqtt.txbuf[_mqtt.txlen++] = 0x30; // MQTT Message Type PUBLISH //剩余长度do{u8 encodedByte = DataLen % 128;DataLen = DataLen / 128;// if there are more data to encode, set the top bit of this byteif ( DataLen > 0 )encodedByte = encodedByte | 128;_mqtt.txbuf[_mqtt.txlen++] = encodedByte;}while ( DataLen > 0 );_mqtt.txbuf[_mqtt.txlen++] = BYTE1(topicLength);//主题长度MSB_mqtt.txbuf[_mqtt.txlen++] = BYTE0(topicLength);//主题长度LSB memcpy(&_mqtt.txbuf[_mqtt.txlen],topic,topicLength);//拷贝主题_mqtt.txlen += topicLength;//报文标识符if(qos){_mqtt.txbuf[_mqtt.txlen++] = BYTE1(id);_mqtt.txbuf[_mqtt.txlen++] = BYTE0(id);id++;}memcpy(&_mqtt.txbuf[_mqtt.txlen],message,messageLength);_mqtt.txlen += messageLength;Mqtt_SendBuf(_mqtt.txbuf,_mqtt.txlen);return _mqtt.txlen;}static void SentHeart(void){Mqtt_SendBuf((u8 *)parket_heart,sizeof(parket_heart));}static void Disconnect(void){Mqtt_SendBuf((u8 *)parket_disconnet,sizeof(parket_disconnet));}static void Mqtt_SendBuf(u8 *buf,u16 len){#ifdef _DEBUG_MQTTUsart1_SendBuf(buf,len);#endifUsart2_SendBuf(buf,len);}/*********************************************END OF FILE********************************************/

mqtt.h部分

#ifndef __FY_MQTT_H_#define __FY_MQTT_H_#include "fy_includes.h"typedef struct{u8 *rxbuf;u16 rxlen;u8 *txbuf;u16 txlen;void (*Init)(u8 *prx,u16 rxlen,u8 *ptx,u16 txlen);u8 (*Connect)(char *ClientID,char *Username,char *Password);u8 (*SubscribeTopic)(char *topic,u8 qos,u8 whether);u8 (*PublishData)(char *topic, char *message, u8 qos);void (*SendHeart)(void);void (*Disconnect)(void);}_typdef_mqtt;extern _typdef_mqtt _mqtt;#endif

完整工程:/download/qq997758497/11239490。

By Urien 6月13日 14:59:29

本内容不代表本网观点和政治立场,如有侵犯你的权益请联系我们处理。
网友评论
网友评论仅供其表达个人看法,并不表明网站立场。