STM32CubeMX ESP8266 AT指令实现MQTT协议并接入阿里云IOT平台源码解析【附Github源码地址】
课程大纲
【第一章】:物联网简介(什么是物联网)
【第二章】:物联网十大应用场景
【第三章】:什么是MCU?
【第四章】:MCU的应用范围
【第五章】:我们要怎么入门MCU开发?
【第六章】:如何使用STM32Cube MX进行STM32的快速开发
【第七章】:ESP8266+MQTT上阿里云物联网平台实践(附源码)
STM32CubeMX AT指令实现MQTT协议并接入阿里云IOT平台 源码解析
CSDN源代码下载
Github源代码下载
目录
效果展示
关于阿里云IOT平台如何配置请参考这篇博客,本篇只讲ESP8266 驱动和实现MQTT协议的核心代码:
ESP8266+MQTT上阿里云物联网平台实践(附源码)
1.单片机接入阿里云平台步骤解析
1.1 接入阿里云物联网平台步骤
//MQTT初始化函数
void ES8266_MQTT_Init(void)
{
uint8_t status=0;
//1.ESP8266初始化
if(ESP8266_Init())
{
user_main_info("ESP8266初始化成功!\r\n");
status++;
}
else Enter_ErrorMode(0);
//2.连接热点
if(status==1)
{
if(ESP8266_ConnectAP(WIFI_NAME,WIFI_PASSWD))
{
user_main_info("ESP8266连接热点成功!\r\n");
status++;
}
else Enter_ErrorMode(1);
}
//3.连接阿里云IOT服务器
if(status==2)
{
if(ESP8266_ConnectServer("TCP",MQTT_BROKERADDRESS,1883)!=0)
{
user_main_info("ESP8266连接阿里云服务器成功!\r\n");
status++;
}
else Enter_ErrorMode(2);
}
//4.登陆MQTT
if(status==3)
{
if(MQTT_Connect(MQTT_CLIENTID, MQTT_USARNAME, MQTT_PASSWD) != 0)
{
user_main_info("ESP8266阿里云MQTT登陆成功!\r\n");
status++;
}
else Enter_ErrorMode(3);
}
//5.订阅主题
if(status==4)
{
if(MQTT_SubscribeTopic(MQTT_SUBSCRIBE_TOPIC,0,1) != 0)
{
user_main_info("ESP8266阿里云MQTT订阅主题成功!\r\n");
}
else Enter_ErrorMode(4);
}
}
1.2 阿里云IOT平台订阅消息处理
订阅成功后,平台下发消息会通过串口透传出来,对消息进行处即可
//处理MQTT下发的消息
void deal_MQTT_message(uint8_t* buf,uint16_t len)
{
uint8_t data[512];
uint16_t data_len = len;
for(int i=0;i<data_len;i++)
{
data[i] = buf[i];
HAL_UART_Transmit(&huart2,&data[i],1,100);
}
memset(usart1_rxbuf,0,sizeof(usart1_rxbuf)); //清空接收缓冲
usart1_rxcounter=0;
//user_main_info("MQTT收到消息,数据长度=%d \n",data_len);
//查找是否是设置红灯
int i = GetSubStrPos((char*)data,"LEDR");
if( i>0 )
{
uint8_t ledr_status = data[i+6]-'0';
HAL_GPIO_WritePin(LED_R_GPIO_Port,LED_R_Pin,GPIO_PIN_SET);
HAL_GPIO_WritePin(LED_G_GPIO_Port,LED_G_Pin,GPIO_PIN_SET);
HAL_GPIO_WritePin(LED_B_GPIO_Port,LED_B_Pin,GPIO_PIN_SET);
if(ledr_status)
HAL_GPIO_WritePin(LED_R_GPIO_Port,LED_R_Pin,GPIO_PIN_RESET);
else
HAL_GPIO_WritePin(LED_R_GPIO_Port,LED_R_Pin,GPIO_PIN_SET);
}
//查找是否是设置绿灯
i = GetSubStrPos((char*)data,"LEDG");
if( i>0 )
{
uint8_t ledr_status = data[i+6]-'0';
HAL_GPIO_WritePin(LED_R_GPIO_Port,LED_R_Pin,GPIO_PIN_SET);
HAL_GPIO_WritePin(LED_G_GPIO_Port,LED_G_Pin,GPIO_PIN_SET);
HAL_GPIO_WritePin(LED_B_GPIO_Port,LED_B_Pin,GPIO_PIN_SET);
if(ledr_status)
HAL_GPIO_WritePin(LED_G_GPIO_Port,LED_G_Pin,GPIO_PIN_RESET);
else
HAL_GPIO_WritePin(LED_G_GPIO_Port,LED_G_Pin,GPIO_PIN_SET);
}
//查找是否是设置蓝灯
i = GetSubStrPos((char*)data,"LEDB");
if( i>0 )
{
uint8_t ledr_status = data[i+6]-'0';
HAL_GPIO_WritePin(LED_R_GPIO_Port,LED_R_Pin,GPIO_PIN_SET);
HAL_GPIO_WritePin(LED_G_GPIO_Port,LED_G_Pin,GPIO_PIN_SET);
HAL_GPIO_WritePin(LED_B_GPIO_Port,LED_B_Pin,GPIO_PIN_SET);
if(ledr_status)
HAL_GPIO_WritePin(LED_B_GPIO_Port,LED_B_Pin,GPIO_PIN_RESET);
else
HAL_GPIO_WritePin(LED_B_GPIO_Port,LED_B_Pin,GPIO_PIN_SET);
}
}
1.3 本地消息发布
调用MQTT发布消息驱动接口即可
//单片机状态上报
void STM32DHT11_StatusReport(void)
{
//获取温湿度信息
uint8_t temperature;
uint8_t humidity;
uint8_t get_times;
// 获取温湿度信息并用串口打印,获取十次,直到成功跳出
for(get_times=0;get_times<10;get_times++)
{
if(!dht11Read(&temperature, &humidity))//Read DHT11 Value
{
user_main_info("temperature=%d,humidity=%d \n",temperature,humidity);
break;
}
}
//上报一次数据
uint8_t led_r_status = HAL_GPIO_ReadPin(LED_R_GPIO_Port,LED_R_Pin) ? 0:1;
uint8_t led_g_status = HAL_GPIO_ReadPin(LED_G_GPIO_Port,LED_G_Pin) ? 0:1;
uint8_t led_b_status = HAL_GPIO_ReadPin(LED_B_GPIO_Port,LED_B_Pin) ? 0:1;
sprintf(mqtt_message,
"{\"method\":\"thing.service.property.set\",\"id\":\"181454577\",\"params\":{\
\"DHT11_Temperature\":%.1f,\
\"DHT11_Humidity\":%.1f,\
\"Switch_LEDR\":%d,\
\"Switch_LEDG\":%d,\
\"Switch_LEDB\":%d\
},\"version\":\"1.0.0\"}",
(float)temperature,
(float)humidity,
led_r_status,
led_g_status,
led_b_status
);
MQTT_PublishData(MQTT_PUBLISH_TOPIC,mqtt_message,0);
}
2.ESP8266 AT指令驱动
2.1 ESP8266_AT.C
#include "esp8266_at.h"
//usart1发送和接收数组
uint8_t usart1_txbuf[256];
uint8_t usart1_rxbuf[512];
uint8_t usart1_rxone[1];
uint8_t usart1_rxcounter;
//串口1发送一个字节
static void USART1_SendOneByte(uint8_t val)
{
((UART_HandleTypeDef *)&huart1)->Instance->DR = ((uint16_t)val & (uint16_t)0x01FF);
while((((UART_HandleTypeDef *)&huart1)->Instance->SR&0X40)==0);//等待发送完成
}
//向ESP8266发送定长数据
void ESP8266_ATSendBuf(uint8_t* buf,uint16_t len)
{
memset(usart1_rxbuf,0, 256);
//每次发送前将接收串口接收总数置0,为了接收
usart1_rxcounter = 0;
//定长发送
HAL_UART_Transmit(&huart1,(uint8_t *)buf,len,0xFFFF);
}
//向ESP8266发送字符串
void ESP8266_ATSendString(char* str)
{
memset(usart1_rxbuf,0, 256);
//每次发送前将接收串口接收总数置0,为了接收
usart1_rxcounter = 0;
//发送方法1
while(*str) USART1_SendOneByte(*str++);
//发送法法2
// HAL_UART_Transmit(&huart1,(uint8_t *)str,strlen(str),0xFFFF);
}
//退出透传
void ESP8266_ExitUnvarnishedTrans(void)
{
ESP8266_ATSendString("+++");HAL_Delay(50);
ESP8266_ATSendString("+++");HAL_Delay(50);
}
//查找字符串中是否包含另一个字符串
uint8_t FindStr(char* dest,char* src,uint16_t retry_nms)
{
retry_nms/=10; //超时时间
while(strstr(dest,src)==0 && retry_nms--)//等待串口接收完毕或超时退出
{
HAL_Delay(10);
}
if(retry_nms) return 1;
return 0;
}
/**
* 功能:检查ESP8266是否正常
* 参数:None
* 返回值:ESP8266返回状态
* 非0 ESP8266正常
* 0 ESP8266有问题
*/
uint8_t ESP8266_Check(void)
{
uint8_t check_cnt=5;
while(check_cnt--)
{
memset(usart1_rxbuf,0,sizeof(usart1_rxbuf)); //清空接收缓冲
ESP8266_ATSendString("AT\r\n"); //发送AT握手指令
if(FindStr((char*)usart1_rxbuf,"OK",200) != 0)
{
return 1;
}
}
return 0;
}
/**
* 功能:初始化ESP8266
* 参数:None
* 返回值:初始化结果,非0为初始化成功,0为失败
*/
uint8_t ESP8266_Init(void)
{
//清空发送和接收数组
memset(usart1_txbuf,0,sizeof(usart1_txbuf));
memset(usart1_rxbuf,0,sizeof(usart1_rxbuf));
ESP8266_ExitUnvarnishedTrans(); //退出透传
HAL_Delay(500);
ESP8266_ATSendString("AT+RST\r\n");
HAL_Delay(800);
if(ESP8266_Check()==0) //使用AT指令检查ESP8266是否存在
{
return 0;
}
memset(usart1_rxbuf,0,sizeof(usart1_rxbuf)); //清空接收缓冲
ESP8266_ATSendString("ATE0\r\n"); //关闭回显
if(FindStr((char*)usart1_rxbuf,"OK",500)==0) //设置不成功
{
return 0;
}
return 1; //设置成功
}
/**
* 功能:恢复出厂设置
* 参数:None
* 返回值:None
* 说明:此时ESP8266中的用户设置将全部丢失回复成出厂状态
*/
void ESP8266_Restore(void)
{
ESP8266_ExitUnvarnishedTrans(); //退出透传
HAL_Delay(500);
ESP8266_ATSendString("AT+RESTORE\r\n"); //恢复出厂
}
/**
* 功能:连接热点
* 参数:
* ssid:热点名
* pwd:热点密码
* 返回值:
* 连接结果,非0连接成功,0连接失败
* 说明:
* 失败的原因有以下几种(UART通信和ESP8266正常情况下)
* 1. WIFI名和密码不正确
* 2. 路由器连接设备太多,未能给ESP8266分配IP
*/
uint8_t ESP8266_ConnectAP(char* ssid,char* pswd)
{
uint8_t cnt=5;
while(cnt--)
{
memset(usart1_rxbuf,0,sizeof(usart1_rxbuf));
ESP8266_ATSendString("AT+CWMODE_CUR=1\r\n"); //设置为STATION模式
if(FindStr((char*)usart1_rxbuf,"OK",200) != 0)
{
break;
}
}
if(cnt == 0)
return 0;
cnt=2;
while(cnt--)
{
memset(usart1_txbuf,0,sizeof(usart1_txbuf));//清空发送缓冲
memset(usart1_rxbuf,0,sizeof(usart1_rxbuf));//清空接收缓冲
sprintf((char*)usart1_txbuf,"AT+CWJAP_CUR=\"%s\",\"%s\"\r\n",ssid,pswd);//连接目标AP
ESP8266_ATSendString((char*)usart1_txbuf);
if(FindStr((char*)usart1_rxbuf,"OK",8000)!=0) //连接成功且分配到IP
{
return 1;
}
}
return 0;
}
//开启透传模式
static uint8_t ESP8266_OpenTransmission(void)
{
//设置透传模式
uint8_t cnt=2;
while(cnt--)
{
memset(usart1_rxbuf,0,sizeof(usart1_rxbuf));
ESP8266_ATSendString("AT+CIPMODE=1\r\n");
if(FindStr((char*)usart1_rxbuf,"OK",200)!=0)
{
return 1;
}
}
return 0;
}
/**
* 功能:使用指定协议(TCP/UDP)连接到服务器
* 参数:
* mode:协议类型 "TCP","UDP"
* ip:目标服务器IP
* port:目标是服务器端口号
* 返回值:
* 连接结果,非0连接成功,0连接失败
* 说明:
* 失败的原因有以下几种(UART通信和ESP8266正常情况下)
* 1. 远程服务器IP和端口号有误
* 2. 未连接AP
* 3. 服务器端禁止添加(一般不会发生)
*/
uint8_t ESP8266_ConnectServer(char* mode,char* ip,uint16_t port)
{
uint8_t cnt;
ESP8266_ExitUnvarnishedTrans(); //多次连接需退出透传
HAL_Delay(500);
//连接服务器
cnt=2;
while(cnt--)
{
memset(usart1_txbuf,0,sizeof(usart1_txbuf));//清空发送缓冲
memset(usart1_rxbuf,0,sizeof(usart1_rxbuf));//清空接收缓冲
sprintf((char*)usart1_txbuf,"AT+CIPSTART=\"%s\",\"%s\",%d\r\n",mode,ip,port);
ESP8266_ATSendString((char*)usart1_txbuf);
if(FindStr((char*)usart1_rxbuf,"CONNECT",8000) !=0 )
{
break;
}
}
if(cnt == 0)
return 0;
//设置透传模式
if(ESP8266_OpenTransmission()==0) return 0;
//开启发送状态
cnt=2;
while(cnt--)
{
memset(usart1_rxbuf,0,sizeof(usart1_rxbuf)); //清空接收缓冲
ESP8266_ATSendString("AT+CIPSEND\r\n");//开始处于透传发送状态
if(FindStr((char*)usart1_rxbuf,">",200)!=0)
{
return 1;
}
}
return 0;
}
/**
* 功能:主动和服务器断开连接
* 参数:None
* 返回值:
* 连接结果,非0断开成功,0断开失败
*/
uint8_t DisconnectServer(void)
{
uint8_t cnt;
ESP8266_ExitUnvarnishedTrans(); //退出透传
HAL_Delay(500);
while(cnt--)
{
memset(usart1_rxbuf,0,sizeof(usart1_rxbuf)); //清空接收缓冲
ESP8266_ATSendString("AT+CIPCLOSE\r\n");//关闭链接
if(FindStr((char*)usart1_rxbuf,"CLOSED",200)!=0)//操作成功,和服务器成功断开
{
break;
}
}
if(cnt) return 1;
return 0;
}
2.2 ESP8266_AT.H
#ifndef __ESP8266_AT_H
#define __ESP8266_AT_H
#include "stm32f4xx_hal.h"
#include "usart.h"
#include <string.h>
#include <stdio.h>
extern uint8_t usart1_txbuf[256];
extern uint8_t usart1_rxbuf[512];
extern uint8_t usart1_rxone[1];
extern uint8_t usart1_rxcounter;
extern uint8_t ESP8266_Init(void);
extern void ESP8266_Restore(void);
extern void ESP8266_ATSendBuf(uint8_t* buf,uint16_t len); //向ESP8266发送指定长度数据
extern void ESP8266_ATSendString(char* str); //向ESP8266模块发送字符串
extern void ESP8266_ExitUnvarnishedTrans(void); //ESP8266退出透传模式
extern uint8_t ESP8266_ConnectAP(char* ssid,char* pswd); //ESP8266连接热点
extern uint8_t ESP8266_ConnectServer(char* mode,char* ip,uint16_t port); //使用指定协议(TCP/UDP)连接到服务器
#endif
3.MQTT协议实现
3.1 ESP8266_MQTT.C
#include "esp8266_mqtt.h"
#include "esp8266_at.h"
//连接成功服务器回应 20 02 00 00
//客户端主动断开连接 e0 00
const uint8_t parket_connetAck[] = {0x20,0x02,0x00,0x00};
const uint8_t parket_disconnet[] = {0xe0,0x00};
const uint8_t parket_heart[] = {0xc0,0x00};
const uint8_t parket_heart_reply[] = {0xc0,0x00};
const uint8_t parket_subAck[] = {0x90,0x03};
volatile uint16_t MQTT_TxLen;
//MQTT发送数据
void MQTT_SendBuf(uint8_t *buf,uint16_t len)
{
ESP8266_ATSendBuf(buf,len);
}
//发送心跳包
void MQTT_SentHeart(void)
{
MQTT_SendBuf((uint8_t *)parket_heart,sizeof(parket_heart));
}
//MQTT无条件断开
void MQTT_Disconnect()
{
MQTT_SendBuf((uint8_t *)parket_disconnet,sizeof(parket_disconnet));
}
//MQTT初始化
void MQTT_Init(uint8_t *prx,uint16_t rxlen,uint8_t *ptx,uint16_t txlen)
{
memset(usart1_txbuf,0,sizeof(usart1_txbuf)); //清空发送缓冲
memset(usart1_rxbuf,0,sizeof(usart1_rxbuf)); //清空接收缓冲
//无条件先主动断开
MQTT_Disconnect();HAL_Delay(100);
MQTT_Disconnect();HAL_Delay(100);
}
//MQTT连接服务器的打包函数
uint8_t MQTT_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);
//固定报头
//控制报文类型
usart1_txbuf[MQTT_TxLen++] = 0x10; //MQTT Message Type CONNECT
//剩余长度(不包括固定头部)
do
{
uint8_t encodedByte = DataLen % 128;
DataLen = DataLen / 128;
// if there are more data to encode, set the top bit of this byte
if ( DataLen > 0 )
encodedByte = encodedByte | 128;
usart1_txbuf[MQTT_TxLen++] = encodedByte;
}while ( DataLen > 0 );
//可变报头
//协议名
usart1_txbuf[MQTT_TxLen++] = 0; // Protocol Name Length MSB
usart1_txbuf[MQTT_TxLen++] = 4; // Protocol Name Length LSB
usart1_txbuf[MQTT_TxLen++] = 'M'; // ASCII Code for M
usart1_txbuf[MQTT_TxLen++] = 'Q'; // ASCII Code for Q
usart1_txbuf[MQTT_TxLen++] = 'T'; // ASCII Code for T
usart1_txbuf[MQTT_TxLen++] = 'T'; // ASCII Code for T
//协议级别
usart1_txbuf[MQTT_TxLen++] = 4; // MQTT Protocol version = 4
//连接标志
usart1_txbuf[MQTT_TxLen++] = 0xc2; // conn flags
usart1_txbuf[MQTT_TxLen++] = 0; // Keep-alive Time Length MSB
usart1_txbuf[MQTT_TxLen++] = 60; // Keep-alive Time Length LSB 60S心跳包
usart1_txbuf[MQTT_TxLen++] = BYTE1(ClientIDLen);// Client ID length MSB
usart1_txbuf[MQTT_TxLen++] = BYTE0(ClientIDLen);// Client ID length LSB
memcpy(&usart1_txbuf[MQTT_TxLen],ClientID,ClientIDLen);
MQTT_TxLen += ClientIDLen;
if(UsernameLen > 0)
{
usart1_txbuf[MQTT_TxLen++] = BYTE1(UsernameLen); //username length MSB
usart1_txbuf[MQTT_TxLen++] = BYTE0(UsernameLen); //username length LSB
memcpy(&usart1_txbuf[MQTT_TxLen],Username,UsernameLen);
MQTT_TxLen += UsernameLen;
}
if(PasswordLen > 0)
{
usart1_txbuf[MQTT_TxLen++] = BYTE1(PasswordLen); //password length MSB
usart1_txbuf[MQTT_TxLen++] = BYTE0(PasswordLen); //password length LSB
memcpy(&usart1_txbuf[MQTT_TxLen],Password,PasswordLen);
MQTT_TxLen += PasswordLen;
}
uint8_t cnt=2;
uint8_t wait;
while(cnt--)
{
memset(usart1_rxbuf,0,sizeof(usart1_rxbuf));
MQTT_SendBuf(usart1_txbuf,MQTT_TxLen);
wait=30;//等待3s时间
while(wait--)
{
//CONNECT
if(usart1_rxbuf[0]==parket_connetAck[0] && usart1_rxbuf[1]==parket_connetAck[1]) //连接成功
{
return 1;//连接成功
}
HAL_Delay(100);
}
}
return 0;
}
//MQTT订阅/取消订阅数据打包函数
//topic 主题
//qos 消息等级
//whether 订阅/取消订阅请求包
uint8_t MQTT_SubscribeTopic(char *topic,uint8_t qos,uint8_t whether)
{
MQTT_TxLen=0;
int topiclen = strlen(topic);
int DataLen = 2 + (topiclen+2) + (whether?1:0);//可变报头的长度(2字节)加上有效载荷的长度
//固定报头
//控制报文类型
if(whether) usart1_txbuf[MQTT_TxLen++] = 0x82; //消息类型和标志订阅
else usart1_txbuf[MQTT_TxLen++] = 0xA2; //取消订阅
//剩余长度
do
{
uint8_t encodedByte = DataLen % 128;
DataLen = DataLen / 128;
// if there are more data to encode, set the top bit of this byte
if ( DataLen > 0 )
encodedByte = encodedByte | 128;
usart1_txbuf[MQTT_TxLen++] = encodedByte;
}while ( DataLen > 0 );
//可变报头
usart1_txbuf[MQTT_TxLen++] = 0; //消息标识符 MSB
usart1_txbuf[MQTT_TxLen++] = 0x01; //消息标识符 LSB
//有效载荷
usart1_txbuf[MQTT_TxLen++] = BYTE1(topiclen);//主题长度 MSB
usart1_txbuf[MQTT_TxLen++] = BYTE0(topiclen);//主题长度 LSB
memcpy(&usart1_txbuf[MQTT_TxLen],topic,topiclen);
MQTT_TxLen += topiclen;
if(whether)
{
usart1_txbuf[MQTT_TxLen++] = qos;//QoS级别
}
uint8_t cnt=2;
uint8_t wait;
while(cnt--)
{
memset(usart1_rxbuf,0,sizeof(usart1_rxbuf));
MQTT_SendBuf(usart1_txbuf,MQTT_TxLen);
wait=30;//等待3s时间
while(wait--)
{
if(usart1_rxbuf[0]==parket_subAck[0] && usart1_rxbuf[1]==parket_subAck[1]) //订阅成功
{
return 1;//订阅成功
}
HAL_Delay(100);
}
}
if(cnt) return 1; //订阅成功
return 0;
}
//MQTT发布数据打包函数
//topic 主题
//message 消息
//qos 消息等级
uint8_t MQTT_PublishData(char *topic, char *message, uint8_t qos)
{
int topicLength = strlen(topic);
int messageLength = strlen(message);
static uint16_t id=0;
int DataLen;
MQTT_TxLen=0;
//有效载荷的长度这样计算:用固定报头中的剩余长度字段的值减去可变报头的长度
//QOS为0时没有标识符
//数据长度 主题名 报文标识符 有效载荷
if(qos) DataLen = (2+topicLength) + 2 + messageLength;
else DataLen = (2+topicLength) + messageLength;
//固定报头
//控制报文类型
usart1_txbuf[MQTT_TxLen++] = 0x30; // MQTT Message Type PUBLISH
//剩余长度
do
{
uint8_t encodedByte = DataLen % 128;
DataLen = DataLen / 128;
// if there are more data to encode, set the top bit of this byte
if ( DataLen > 0 )
encodedByte = encodedByte | 128;
usart1_txbuf[MQTT_TxLen++] = encodedByte;
}while ( DataLen > 0 );
usart1_txbuf[MQTT_TxLen++] = BYTE1(topicLength);//主题长度MSB
usart1_txbuf[MQTT_TxLen++] = BYTE0(topicLength);//主题长度LSB
memcpy(&usart1_txbuf[MQTT_TxLen],topic,topicLength);//拷贝主题
MQTT_TxLen += topicLength;
//报文标识符
if(qos)
{
usart1_txbuf[MQTT_TxLen++] = BYTE1(id);
usart1_txbuf[MQTT_TxLen++] = BYTE0(id);
id++;
}
memcpy(&usart1_txbuf[MQTT_TxLen],message,messageLength);
MQTT_TxLen += messageLength;
MQTT_SendBuf(usart1_txbuf,MQTT_TxLen);
return MQTT_TxLen;
}
3.2 ESP8266_MQTT.H
#ifndef __ES8266_MQTT_H
#define __ES8266_MQTT_H
#include "stm32f4xx_hal.h"
#define BYTE0(dwTemp) (*( char *)(&dwTemp))
#define BYTE1(dwTemp) (*((char *)(&dwTemp) + 1))
#define BYTE2(dwTemp) (*((char *)(&dwTemp) + 2))
#define BYTE3(dwTemp) (*((char *)(&dwTemp) + 3))
//MQTT连接服务器
extern uint8_t MQTT_Connect(char *ClientID,char *Username,char *Password);
//MQTT消息订阅
extern uint8_t MQTT_SubscribeTopic(char *topic,uint8_t qos,uint8_t whether);
//MQTT消息发布
extern uint8_t MQTT_PublishData(char *topic, char *message, uint8_t qos);
//MQTT发送心跳包
extern void MQTT_SentHeart(void);
#endif
【STM32 ES8266上阿里云IOT MQTT实践课程大纲】
STM32 ES8266上阿里云IOT MQTT实践【第一章】:物联网简介(什么是物联网)
STM32 ES8266上阿里云IOT MQTT实践【第二章】:物联网十大应用场景
STM32 ES8266上阿里云IOT MQTT实践【第三章】:什么是MCU?
STM32 ES8266上阿里云IOT MQTT实践【第四章】:MCU的应用范围
STM32 ES8266上阿里云IOT MQTT实践【第五章】:我们要怎么入门MCU开发?
STM32 ES8266上阿里云IOT MQTT实践【第六章】:如何使用STM32Cube MX进行STM32的快速开发
STM32 ES8266上阿里云IOT MQTT实践【第七章】:ESP8266+MQTT上阿里云物联网平台实践(附源码)
STM32CubeMX通过ESP8266 AT指令MQTT上阿里云物联网平台实践源代码
【Github源码地址】
https://github.com/SuperBigOnion/ESP8266_MQTT_aliyunIOT
更多推荐



所有评论(0)