赞
踩
ESP8266有多种连接MQTT方式,本文介绍使用的是AT MQTT版本固件的ESP01s,基于此固件版本进行说明。本文所需硬件:STM32F103RCT6、LED、ESP01s、DHT11,实现功能:温湿度上传和远程开关灯的基本功能。
B站视频教程:STM32+ESP8266+DHT11_哔哩哔哩_bilibili
gitee: STM32_Share: STM32、DHT11、ESP01s 实现温湿度上传和远程开关灯
网上购买ESP01s默认固件并不是MQTT版本,因此需要先烧录对应此版本的固件
(1)打开烧录软件
(2)使用固件ESP8266-AT-1M.bin,配置如图所示,然后点击START
烧录完成后如图所示:
(3)验证是否烧录固件成功,使用串口助手发送AT+MQTTUSERCFG=0,1,"sub","","",0,0,""(设置MQTT用户属性)
失败如下图所示:
成功如下图所示:
(1) 使用一个公共MQTT服务器,这里测试使用https://www.emqx.com/zh/mqtt/public-mqtt5-broker
(2)电脑下载并安装MQTTBox,配置如图所示:
(3)保存,然后针对同一主题进行订阅和发布(注意:因为使用的是公共版的MQTT服务器,所以如果使用简单的主题名称,可能会跟别人重复了,所以建议使用较为复杂的主题)。左侧点击publish后,右侧出现相应内容,证明服务器可以使用,可以进行后续操作。
(4) 如果在阿里云等平台开通云服务器,也可以安装相应版本的EMQXhttps://www.emqx.com/zh/try?product=broker
安装完成后,即可通过访问自己阿里云的ip地址,实现MQTT服务器的访问。
按照下面顺序依次通过串口助手发送AT指令(注意波特率为115200,勾选发送新行)
(1)发:AT
回:"OK"
作用:测试ESP01s连接成功,有反应
(2)发:AT+CWMODE=1
回:"OK"
作用:将Wi-Fi模块设置为Station(STA)模式
(3)发:AT+CWJAP="xiaomi","123456789"
回:"OK"
作用:连接WIFI的用户名和密码
(4)发:AT+MQTTUSERCFG=0,1,"MQTTID","username","password",0,0,""
回:"OK"
作用:这里因为用的公共的MQTT服务器,所以不需要用户名和密码,所以随便设置就行。
(5)发:AT+MQTTCONN=0,"broker-cn.emqx.io",1883,1
回:"OK"
作用:
(6)发:AT+MQTTSUB=0,"subtest",0
回:"OK"
作用:
(7)发:AT+MQTTPUB=0,"pubtest","message",0,0
回:"OK"
作用:
测试图如下所示:
第一张图倒数第一行:通过MQTTBox对主题subtest,发送LEDON,ESP01s接收到+MQTTSUBRECV:0,"subtest",5,LEDON。
第一张图倒数第三行,ESP01s向pubtest发送信息message,在MQTTBox上面的pubtest显示接收到信息message
想要详细了解这部分的朋友,可以去B站观看讲解视频。整套工程代码基于正点原子官方例程改写。
(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);
- }
-
-
- //第二步、开始进行AT指令配置
-
-
- //判断串口二收到的数据是不是前面定义的ack(期待的应答结果)
- 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;
- }
-
-
- //放一个命令函数在这
- //cmd:发送的AT指令
- //ack:期待的回答
- //time:等待时间(单位10ms)
- //返回值:0、发送成功。 1、发送失败
- 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) //串口二接收到数据
- {
- //判断接受的数据是不是想要的
- if(wifi_check_cmd(ack))
- {
- break;
- }
- USART2_RX_STA = 0;
- }
- }
- if(time == 0) res = 1;
- }
- return res;
-
- }
-
- //第三步、按顺序发送AT指令
- void init_wifi(void)
- {
- //1 AT
- while(wifi_send_cmd("AT","OK",50))
- {
- printf("AT响应失败\r\n");
- }
-
- //2 将Wi-Fi模块设置为Station(STA)模式
- while(wifi_send_cmd("AT+CWMODE=1","OK",50))
- {
- printf("STA模式设置失败\r\n");
- }
-
- //3 连接WIFI的用户名和密码
- while(wifi_send_cmd("AT+CWJAP=\"xiaomi\",\"123456789\"","OK",500))
- {
- printf("连接WIFI失败\r\n");
- }
-
- //4 设置MQTT相关属性
- 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服务器失败\r\n");
- }
- //6 订阅主题
- while(wifi_send_cmd("AT+MQTTSUB=0,\"subtest\",0","OK",50))
- {
- printf("订阅主题失败\r\n");
- }
- }
-
-
-
(2)使用定时器,定时上传温湿度数据。
- #include "timer.h"
- #include "led.h"
- #include "usart.h"
- #include "dht11.h"
- #include "wifi.h"
- #include <string.h>
-
-
- //通用定时器中断初始化
- //这里时钟选择为APB1的2倍,而APB1为36M
- //arr:自动重装值。
- //psc:时钟预分频数
- //这里使用的是定时器3!
- void TIM3_Int_Init(u16 arr,u16 psc)
- {
- TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure;
- NVIC_InitTypeDef NVIC_InitStructure;
-
- RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM3, ENABLE); //时钟使能
-
- TIM_TimeBaseStructure.TIM_Period = arr; //设置在下一个更新事件装入活动的自动重装载寄存器周期的值 计数到5000为500ms
- TIM_TimeBaseStructure.TIM_Prescaler =psc; //设置用来作为TIMx时钟频率除数的预分频值 10Khz的计数频率
- TIM_TimeBaseStructure.TIM_ClockDivision = 0; //设置时钟分割:TDTS = Tck_tim
- TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up; //TIM向上计数模式
- TIM_TimeBaseInit(TIM3, &TIM_TimeBaseStructure); //根据TIM_TimeBaseInitStruct中指定的参数初始化TIMx的时间基数单位
- //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; //先占优先级0级
- NVIC_InitStructure.NVIC_IRQChannelSubPriority = 3; //从优先级3级
- NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; //IRQ通道被使能
- NVIC_Init(&NVIC_InitStructure); //根据NVIC_InitStruct中指定的参数初始化外设NVIC寄存器
-
- TIM_Cmd(TIM3, ENABLE); //使能TIMx外设
-
- }
-
- char humi,temp,buf2[50];
-
- void TIM3_IRQHandler(void) //TIM3中断
- {
- if (TIM_GetITStatus(TIM3, TIM_IT_Update) != RESET) //检查指定的TIM中断发生与否: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函数代码
- #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(); //延时函数初始化
- 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)))
- {
- //关灯
- LED1 = 1;
- printf("关灯\r\n");
- }
- memset(USART2_RX_BUF,0,1024);
- USART2_RX_STA = 0;
- }
- }
- }
-
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。