? ? ? ? ESP8266有多種連接MQTT方式,本文介紹使用的是AT MQTT版本固件的ESP01s,基于此固件版本進(jìn)行說明。本文所需硬件:STM32F103RCT6、LED、ESP01s、DHT11,實(shí)現(xiàn)功能:溫濕度上傳和遠(yuǎn)程開關(guān)燈的基本功能。
B站視頻教程:STM32+ESP8266+DHT11_嗶哩嗶哩_bilibili
gitee:?STM32_Share: STM32、DHT11、ESP01s 實(shí)現(xiàn)溫濕度上傳和遠(yuǎn)程開關(guān)燈
一、燒錄ESP01s所需要的固件
網(wǎng)上購(gòu)買ESP01s默認(rèn)固件并不是MQTT版本,因此需要先燒錄對(duì)應(yīng)此版本的固件
(1)打開燒錄軟件
(2)使用固件ESP8266-AT-1M.bin,配置如圖所示,然后點(diǎn)擊START
?
?燒錄完成后如圖所示:
(3)驗(yàn)證是否燒錄固件成功,使用串口助手發(fā)送AT+MQTTUSERCFG=0,1,"sub","","",0,0,""(設(shè)置MQTT用戶屬性)
失敗如下圖所示:
成功如下圖所示:
二、尋找可用的MQTT服務(wù)器
(1) 使用一個(gè)公共MQTT服務(wù)器,這里測(cè)試使用https://www.emqx.com/zh/mqtt/public-mqtt5-broker
?
?(2)電腦下載并安裝MQTTBox,配置如圖所示:
(3)保存,然后針對(duì)同一主題進(jìn)行訂閱和發(fā)布(注意:因?yàn)槭褂玫氖枪舶娴腗QTT服務(wù)器,所以如果使用簡(jiǎn)單的主題名稱,可能會(huì)跟別人重復(fù)了,所以建議使用較為復(fù)雜的主題)。左側(cè)點(diǎn)擊publish后,右側(cè)出現(xiàn)相應(yīng)內(nèi)容,證明服務(wù)器可以使用,可以進(jìn)行后續(xù)操作。
(4) 如果在阿里云等平臺(tái)開通云服務(wù)器,也可以安裝相應(yīng)版本的EMQXhttps://www.emqx.com/zh/try?product=broker
?安裝完成后,即可通過訪問自己阿里云的ip地址,實(shí)現(xiàn)MQTT服務(wù)器的訪問。
?三、測(cè)試ESP01s的AT指令連接
?按照下面順序依次通過串口助手發(fā)送AT指令(注意波特率為115200,勾選發(fā)送新行)
(1)發(fā):AT
回:"OK"
作用:測(cè)試ESP01s連接成功,有反應(yīng)
(2)發(fā):AT+CWMODE=1
回:"OK"
作用:將Wi-Fi模塊設(shè)置為Station(STA)模式
(3)發(fā):AT+CWJAP="xiaomi","123456789"
回:"OK"
作用:連接WIFI的用戶名和密碼
(4)發(fā):AT+MQTTUSERCFG=0,1,"MQTTID","username","password",0,0,""
回:"OK"
作用:這里因?yàn)橛玫墓驳腗QTT服務(wù)器,所以不需要用戶名和密碼,所以隨便設(shè)置就行。
- 0: 表示配置的索引號(hào)。這里設(shè)置為0,表示配置 MQTT 客戶端的第一個(gè)憑據(jù)信息。
- 1: 表示客戶端編號(hào)。在這里設(shè)置為1,用來標(biāo)識(shí) MQTT 客戶端的唯一身份。
- "MQTTID": 表示 MQTT 客戶端的 ID。在這里設(shè)置為 "MQTTID",可以是任意字符串,用于標(biāo)識(shí)該 MQTT 客戶端。
- "username": 表示 MQTT 服務(wù)器的用戶名。在這里設(shè)置為 "username",是連接到 MQTT 服務(wù)器所需的用戶名。
- "password": 表示 MQTT 服務(wù)器的密碼。在這里設(shè)置為 "password",是連接到 MQTT 服務(wù)器所需的密碼。
- 0: 表示是否使用預(yù)先配置的 TLS 連接。這里設(shè)置為0,表示不使用 TLS 連接。
- 0: 表示是否清除會(huì)話。這里設(shè)置為0,表示不清除會(huì)話。
- "": 表示遺愿主題。這里設(shè)置為空字符串,表示沒有遺愿主題。
(5)發(fā):AT+MQTTCONN=0,"broker-cn.emqx.io",1883,1
回:"OK"
作用:
- 0: 表示配置的索引號(hào)。這里設(shè)置為0,表示配置 MQTT 客戶端的第一個(gè)連接信息。
- "broker-cn.emqx.io": 表示 MQTT 服務(wù)器的地址。在這里設(shè)置為 "broker-cn.emqx.io",是要連接的 MQTT 服務(wù)器的域名或IP地址。
- 1883: 表示 MQTT 服務(wù)器的端口號(hào)。在這里設(shè)置為1883,是 MQTT 服務(wù)器的默認(rèn)端口號(hào)。
- 1: 表示QoS等級(jí)。這里設(shè)置為1,表示消息傳遞的 QoS 等級(jí)為“至少一次”,確保消息被至少傳遞一次。
(6)發(fā):AT+MQTTSUB=0,"subtest",0
回:"OK"
作用:
- 0: 表示配置的索引號(hào)。這里設(shè)置為0,表示配置 MQTT 客戶端的第一個(gè)訂閱信息。
- "subtest": 表示要訂閱的主題。在這里設(shè)置為 "subtest",是要訂閱的具體主題名。
- 0: 表示訂閱的QoS等級(jí)。這里設(shè)置為0,表示訂閱的消息傳遞 QoS 等級(jí)為“至多一次”,即消息可能會(huì)重復(fù)發(fā)送但不保證到達(dá)。
(7)發(fā):AT+MQTTPUB=0,"pubtest","message",0,0
回:"OK"
作用:
- 0: 表示配置的索引號(hào)。這里設(shè)置為0,表示配置 MQTT 客戶端的第一個(gè)發(fā)布消息信息。
- "pubtest": 表示要發(fā)布消息的主題。在這里設(shè)置為 "pubtest",是要發(fā)布消息的具體主題名。
- "message": 表示要發(fā)布的消息內(nèi)容。在這里設(shè)置為 "message",是要發(fā)布的具體消息內(nèi)容。
- 0: 表示發(fā)布消息的QoS等級(jí)。這里設(shè)置為0,表示發(fā)布的消息傳遞 QoS 等級(jí)為“至多一次”,即消息可能會(huì)重復(fù)發(fā)送但不保證到達(dá)。
- 0: 表示是否保留消息。這里設(shè)置為0,表示不保留消息。
測(cè)試圖如下所示:
第一張圖倒數(shù)第一行:通過MQTTBox對(duì)主題subtest,發(fā)送LEDON,ESP01s接收到+MQTTSUBRECV:0,"subtest",5,LEDON。
第一張圖倒數(shù)第三行,ESP01s向pubtest發(fā)送信息message,在MQTTBox上面的pubtest顯示接收到信息message
四、通過程序?qū)崿F(xiàn)溫濕度上傳和控制LED燈的亮滅?
? ? ? ? 想要詳細(xì)了解這部分的朋友,可以去B站觀看講解視頻。整套工程代碼基于正點(diǎn)原子官方例程改寫。
(1)ESP8266配置代碼
#include "stm32f10x.h" // Device header
#include "wifi.h"
#include "delay.h"
#include "usart.h"
#include "usart2.h"
#include "string.h"
/*
ESP01s STM32
3V3----------3.3V
GND----------GND
RX-----------PA2
TX-----------PA3
RST----------PA4
*/
//第一步、wifi模塊上電先重啟一下
void wifi_GPIO_Init(void)
{
GPIO_InitTypeDef GPIO_InitStructure;
RCC_APB2PeriphClockCmd( RCC_APB2Periph_GPIOA , ENABLE);
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_4;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;
GPIO_Init(GPIOA, &GPIO_InitStructure);
GPIO_SetBits(GPIOA,GPIO_Pin_4);
}
void rst_wifi(void)
{
GPIO_ResetBits(GPIOA,GPIO_Pin_4);
delay_ms(1000);
GPIO_SetBits(GPIOA,GPIO_Pin_4);
}
//第二步、開始進(jìn)行AT指令配置
//判斷串口二收到的數(shù)據(jù)是不是前面定義的ack(期待的應(yīng)答結(jié)果)
u8* wifi_check_cmd(u8 *str)
{
char *strx = 0;
if(USART2_RX_STA&0X8000)
{
USART2_RX_BUF[USART2_RX_STA&0X7FFF] = 0;
strx = strstr((const char*)USART2_RX_BUF,(const char*)str);
}
return (u8*)strx;
}
//放一個(gè)命令函數(shù)在這
//cmd:發(fā)送的AT指令
//ack:期待的回答
//time:等待時(shí)間(單位10ms)
//返回值:0、發(fā)送成功。 1、發(fā)送失敗
u8 wifi_send_cmd(u8 *cmd,u8 *ack,u16 time)
{
u8 res = 0;
USART2_RX_STA = 0;
u2_printf("%s\r\n",cmd);
if(time)
{
while(--time)
{
delay_ms(10);
if(USART2_RX_STA&0X8000) //串口二接收到數(shù)據(jù)
{
//判斷接受的數(shù)據(jù)是不是想要的
if(wifi_check_cmd(ack))
{
break;
}
USART2_RX_STA = 0;
}
}
if(time == 0) res = 1;
}
return res;
}
//第三步、按順序發(fā)送AT指令
void init_wifi(void)
{
//1 AT
while(wifi_send_cmd("AT","OK",50))
{
printf("AT響應(yīng)失敗\r\n");
}
//2 將Wi-Fi模塊設(shè)置為Station(STA)模式
while(wifi_send_cmd("AT+CWMODE=1","OK",50))
{
printf("STA模式設(shè)置失敗\r\n");
}
//3 連接WIFI的用戶名和密碼
while(wifi_send_cmd("AT+CWJAP=\"xiaomi\",\"123456789\"","OK",500))
{
printf("連接WIFI失敗\r\n");
}
//4 設(shè)置MQTT相關(guān)屬性
while(wifi_send_cmd("AT+MQTTUSERCFG=0,1,\"MQTTID\",\"username\",\"password\",0,0,\"\"","OK",500))
{
printf("連接WIFI失敗\r\n");
}
//5 連接MQTT的ip
while(wifi_send_cmd("AT+MQTTCONN=0,\"broker-cn.emqx.io\",1883,1","OK",500))
{
printf("連接MQTT服務(wù)器失敗\r\n");
}
//6 訂閱主題
while(wifi_send_cmd("AT+MQTTSUB=0,\"subtest\",0","OK",50))
{
printf("訂閱主題失敗\r\n");
}
}
(2)使用定時(shí)器,定時(shí)上傳溫濕度數(shù)據(jù)。文章來源:http://www.zghlxwxcb.cn/news/detail-699190.html
#include "timer.h"
#include "led.h"
#include "usart.h"
#include "dht11.h"
#include "wifi.h"
#include <string.h>
//通用定時(shí)器中斷初始化
//這里時(shí)鐘選擇為APB1的2倍,而APB1為36M
//arr:自動(dòng)重裝值。
//psc:時(shí)鐘預(yù)分頻數(shù)
//這里使用的是定時(shí)器3!
void TIM3_Int_Init(u16 arr,u16 psc)
{
TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure;
NVIC_InitTypeDef NVIC_InitStructure;
RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM3, ENABLE); //時(shí)鐘使能
TIM_TimeBaseStructure.TIM_Period = arr; //設(shè)置在下一個(gè)更新事件裝入活動(dòng)的自動(dòng)重裝載寄存器周期的值 計(jì)數(shù)到5000為500ms
TIM_TimeBaseStructure.TIM_Prescaler =psc; //設(shè)置用來作為TIMx時(shí)鐘頻率除數(shù)的預(yù)分頻值 10Khz的計(jì)數(shù)頻率
TIM_TimeBaseStructure.TIM_ClockDivision = 0; //設(shè)置時(shí)鐘分割:TDTS = Tck_tim
TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up; //TIM向上計(jì)數(shù)模式
TIM_TimeBaseInit(TIM3, &TIM_TimeBaseStructure); //根據(jù)TIM_TimeBaseInitStruct中指定的參數(shù)初始化TIMx的時(shí)間基數(shù)單位
//TimeOut = ((PSC+ 1) * (ARR+ 1) ) / TIMxCLK 單位秒
TIM_ITConfig( //使能或者失能指定的TIM中斷
TIM3, //TIM2
TIM_IT_Update ,
ENABLE //使能
);
NVIC_InitStructure.NVIC_IRQChannel = TIM3_IRQn; //TIM3中斷
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0; //先占優(yōu)先級(jí)0級(jí)
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 3; //從優(yōu)先級(jí)3級(jí)
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; //IRQ通道被使能
NVIC_Init(&NVIC_InitStructure); //根據(jù)NVIC_InitStruct中指定的參數(shù)初始化外設(shè)NVIC寄存器
TIM_Cmd(TIM3, ENABLE); //使能TIMx外設(shè)
}
char humi,temp,buf2[50];
void TIM3_IRQHandler(void) //TIM3中斷
{
if (TIM_GetITStatus(TIM3, TIM_IT_Update) != RESET) //檢查指定的TIM中斷發(fā)生與否:TIM 中斷源
{
LED0=!LED0;
DHT11_Read_Data(&temp,&humi);
sprintf(buf2,"AT+MQTTPUB=0,\"pubtest\",\"temp:%d%d\\\,humi:%d%d\",0,0",temp/10,temp%10,humi/10,humi%10);
printf("buf2:%s\r\n",buf2);
wifi_send_cmd(buf2,"OK",100);
TIM_ClearITPendingBit(TIM3, TIM_IT_Update ); //清除TIMx的中斷待處理位:TIM 中斷源
}
}
(3)main函數(shù)代碼文章來源地址http://www.zghlxwxcb.cn/news/detail-699190.html
#include "led.h"
#include "delay.h"
#include "sys.h"
#include "usart.h"
#include "usart2.h"
#include "dht11.h"
#include "wifi.h"
#include "timer.h"
#include <string.h>
char *cmdLEDON = "+MQTTSUBRECV:0,\"subtest\",5,LEDON";
char *cmdLEDOFF = "+MQTTSUBRECV:0,\"subtest\",6,LEDOFF";
int main(void)
{
delay_init(); //延時(shí)函數(shù)初始化
LED_Init(); //初始化與LED連接的硬件接口
wifi_GPIO_Init();
uart_init(9600);
USART2_Init(115200); //連接ESP8266
DHT11_Init(); //dht11
rst_wifi();
init_wifi();
TIM3_Int_Init(9999,35999); //5s
while(1)
{
if(USART2_RX_STA&0X8000)
{
if(!memcmp(USART2_RX_BUF,cmdLEDON,strlen(cmdLEDON)))
{
//開燈
LED1 = 0;
printf("開燈\r\n");
}
if(!memcmp(USART2_RX_BUF,cmdLEDOFF,strlen(cmdLEDOFF)))
{
//關(guān)燈
LED1 = 1;
printf("關(guān)燈\r\n");
}
memset(USART2_RX_BUF,0,1024);
USART2_RX_STA = 0;
}
}
}
到了這里,關(guān)于STM32通過ESP8266連接MQTT服務(wù)器的文章就介紹完了。如果您還想了解更多內(nèi)容,請(qǐng)?jiān)谟疑辖撬阉鱐OY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!