当前位置:   article > 正文

STM32通过ESP8266连接MQTT服务器_stm32连接mqttx

stm32连接mqttx

        ESP8266有多种连接MQTT方式,本文介绍使用的是AT MQTT版本固件的ESP01s,基于此固件版本进行说明。本文所需硬件:STM32F103RCT6、LED、ESP01s、DHT11,实现功能:温湿度上传和远程开关灯的基本功能。

B站视频教程:STM32+ESP8266+DHT11_哔哩哔哩_bilibili

gitee: STM32_Share: STM32、DHT11、ESP01s 实现温湿度上传和远程开关灯

一、烧录ESP01s所需要的固件

网上购买ESP01s默认固件并不是MQTT版本,因此需要先烧录对应此版本的固件

(1)打开烧录软件

(2)使用固件ESP8266-AT-1M.bin,配置如图所示,然后点击START

 

 烧录完成后如图所示:

(3)验证是否烧录固件成功,使用串口助手发送AT+MQTTUSERCFG=0,1,"sub","","",0,0,""(设置MQTT用户属性)

失败如下图所示:

成功如下图所示:

二、寻找可用的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服务器的访问。

 三、测试ESP01s的AT指令连接

 按照下面顺序依次通过串口助手发送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服务器,所以不需要用户名和密码,所以随便设置就行。

  • 0: 表示配置的索引号。这里设置为0,表示配置 MQTT 客户端的第一个凭据信息。
  • 1: 表示客户端编号。在这里设置为1,用来标识 MQTT 客户端的唯一身份。
  • "MQTTID": 表示 MQTT 客户端的 ID。在这里设置为 "MQTTID",可以是任意字符串,用于标识该 MQTT 客户端。
  • "username": 表示 MQTT 服务器的用户名。在这里设置为 "username",是连接到 MQTT 服务器所需的用户名。
  • "password": 表示 MQTT 服务器的密码。在这里设置为 "password",是连接到 MQTT 服务器所需的密码。
  • 0: 表示是否使用预先配置的 TLS 连接。这里设置为0,表示不使用 TLS 连接。
  • 0: 表示是否清除会话。这里设置为0,表示不清除会话。
  • "": 表示遗愿主题。这里设置为空字符串,表示没有遗愿主题。

(5)发:AT+MQTTCONN=0,"broker-cn.emqx.io",1883,1

回:"OK"

作用:

  • 0: 表示配置的索引号。这里设置为0,表示配置 MQTT 客户端的第一个连接信息。
  • "broker-cn.emqx.io": 表示 MQTT 服务器的地址。在这里设置为 "broker-cn.emqx.io",是要连接的 MQTT 服务器的域名或IP地址。
  • 1883: 表示 MQTT 服务器的端口号。在这里设置为1883,是 MQTT 服务器的默认端口号。
  • 1: 表示QoS等级。这里设置为1,表示消息传递的 QoS 等级为“至少一次”,确保消息被至少传递一次。

(6)发:AT+MQTTSUB=0,"subtest",0

回:"OK"

作用:

  • 0: 表示配置的索引号。这里设置为0,表示配置 MQTT 客户端的第一个订阅信息。
  • "subtest": 表示要订阅的主题。在这里设置为 "subtest",是要订阅的具体主题名。
  • 0: 表示订阅的QoS等级。这里设置为0,表示订阅的消息传递 QoS 等级为“至多一次”,即消息可能会重复发送但不保证到达。

(7)发:AT+MQTTPUB=0,"pubtest","message",0,0

回:"OK"

作用:

  • 0: 表示配置的索引号。这里设置为0,表示配置 MQTT 客户端的第一个发布消息信息。
  • "pubtest": 表示要发布消息的主题。在这里设置为 "pubtest",是要发布消息的具体主题名。
  • "message": 表示要发布的消息内容。在这里设置为 "message",是要发布的具体消息内容。
  • 0: 表示发布消息的QoS等级。这里设置为0,表示发布的消息传递 QoS 等级为“至多一次”,即消息可能会重复发送但不保证到达。
  • 0: 表示是否保留消息。这里设置为0,表示不保留消息。

测试图如下所示:

第一张图倒数第一行:通过MQTTBox对主题subtest,发送LEDON,ESP01s接收到+MQTTSUBRECV:0,"subtest",5,LEDON

第一张图倒数第三行,ESP01s向pubtest发送信息message,在MQTTBox上面的pubtest显示接收到信息message

四、通过程序实现温湿度上传和控制LED灯的亮灭 

        想要详细了解这部分的朋友,可以去B站观看讲解视频。整套工程代码基于正点原子官方例程改写。

(1)ESP8266配置代码

  1. #include "stm32f10x.h" // Device header
  2. #include "wifi.h"
  3. #include "delay.h"
  4. #include "usart.h"
  5. #include "usart2.h"
  6. #include "string.h"
  7. /*
  8. ESP01s STM32
  9. 3V3----------3.3V
  10. GND----------GND
  11. RX-----------PA2
  12. TX-----------PA3
  13. RST----------PA4
  14. */
  15. //第一步、wifi模块上电先重启一下
  16. void wifi_GPIO_Init(void)
  17. {
  18. GPIO_InitTypeDef GPIO_InitStructure;
  19. RCC_APB2PeriphClockCmd( RCC_APB2Periph_GPIOA , ENABLE);
  20. GPIO_InitStructure.GPIO_Pin = GPIO_Pin_4;
  21. GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
  22. GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;
  23. GPIO_Init(GPIOA, &GPIO_InitStructure);
  24. GPIO_SetBits(GPIOA,GPIO_Pin_4);
  25. }
  26. void rst_wifi(void)
  27. {
  28. GPIO_ResetBits(GPIOA,GPIO_Pin_4);
  29. delay_ms(1000);
  30. GPIO_SetBits(GPIOA,GPIO_Pin_4);
  31. }
  32. //第二步、开始进行AT指令配置
  33. //判断串口二收到的数据是不是前面定义的ack(期待的应答结果)
  34. u8* wifi_check_cmd(u8 *str)
  35. {
  36. char *strx = 0;
  37. if(USART2_RX_STA&0X8000)
  38. {
  39. USART2_RX_BUF[USART2_RX_STA&0X7FFF] = 0;
  40. strx = strstr((const char*)USART2_RX_BUF,(const char*)str);
  41. }
  42. return (u8*)strx;
  43. }
  44. //放一个命令函数在这
  45. //cmd:发送的AT指令
  46. //ack:期待的回答
  47. //time:等待时间(单位10ms)
  48. //返回值:0、发送成功。 1、发送失败
  49. u8 wifi_send_cmd(u8 *cmd,u8 *ack,u16 time)
  50. {
  51. u8 res = 0;
  52. USART2_RX_STA = 0;
  53. u2_printf("%s\r\n",cmd);
  54. if(time)
  55. {
  56. while(--time)
  57. {
  58. delay_ms(10);
  59. if(USART2_RX_STA&0X8000) //串口二接收到数据
  60. {
  61. //判断接受的数据是不是想要的
  62. if(wifi_check_cmd(ack))
  63. {
  64. break;
  65. }
  66. USART2_RX_STA = 0;
  67. }
  68. }
  69. if(time == 0) res = 1;
  70. }
  71. return res;
  72. }
  73. //第三步、按顺序发送AT指令
  74. void init_wifi(void)
  75. {
  76. //1 AT
  77. while(wifi_send_cmd("AT","OK",50))
  78. {
  79. printf("AT响应失败\r\n");
  80. }
  81. //2 将Wi-Fi模块设置为Station(STA)模式
  82. while(wifi_send_cmd("AT+CWMODE=1","OK",50))
  83. {
  84. printf("STA模式设置失败\r\n");
  85. }
  86. //3 连接WIFI的用户名和密码
  87. while(wifi_send_cmd("AT+CWJAP=\"xiaomi\",\"123456789\"","OK",500))
  88. {
  89. printf("连接WIFI失败\r\n");
  90. }
  91. //4 设置MQTT相关属性
  92. while(wifi_send_cmd("AT+MQTTUSERCFG=0,1,\"MQTTID\",\"username\",\"password\",0,0,\"\"","OK",500))
  93. {
  94. printf("连接WIFI失败\r\n");
  95. }
  96. //5 连接MQTT的ip
  97. while(wifi_send_cmd("AT+MQTTCONN=0,\"broker-cn.emqx.io\",1883,1","OK",500))
  98. {
  99. printf("连接MQTT服务器失败\r\n");
  100. }
  101. //6 订阅主题
  102. while(wifi_send_cmd("AT+MQTTSUB=0,\"subtest\",0","OK",50))
  103. {
  104. printf("订阅主题失败\r\n");
  105. }
  106. }

(2)使用定时器,定时上传温湿度数据。

  1. #include "timer.h"
  2. #include "led.h"
  3. #include "usart.h"
  4. #include "dht11.h"
  5. #include "wifi.h"
  6. #include <string.h>
  7. //通用定时器中断初始化
  8. //这里时钟选择为APB12倍,而APB136M
  9. //arr:自动重装值。
  10. //psc:时钟预分频数
  11. //这里使用的是定时器3!
  12. void TIM3_Int_Init(u16 arr,u16 psc)
  13. {
  14. TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure;
  15. NVIC_InitTypeDef NVIC_InitStructure;
  16. RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM3, ENABLE); //时钟使能
  17. TIM_TimeBaseStructure.TIM_Period = arr; //设置在下一个更新事件装入活动的自动重装载寄存器周期的值 计数到5000500ms
  18. TIM_TimeBaseStructure.TIM_Prescaler =psc; //设置用来作为TIMx时钟频率除数的预分频值 10Khz的计数频率
  19. TIM_TimeBaseStructure.TIM_ClockDivision = 0; //设置时钟分割:TDTS = Tck_tim
  20. TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up; //TIM向上计数模式
  21. TIM_TimeBaseInit(TIM3, &TIM_TimeBaseStructure); //根据TIM_TimeBaseInitStruct中指定的参数初始化TIMx的时间基数单位
  22. //TimeOut = ((PSC+ 1* (ARR+ 1) ) / TIMxCLK 单位秒
  23. TIM_ITConfig( //使能或者失能指定的TIM中断
  24. TIM3, //TIM2
  25. TIM_IT_Update ,
  26. ENABLE //使能
  27. );
  28. NVIC_InitStructure.NVIC_IRQChannel = TIM3_IRQn; //TIM3中断
  29. NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0; //先占优先级0
  30. NVIC_InitStructure.NVIC_IRQChannelSubPriority = 3; //从优先级3
  31. NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; //IRQ通道被使能
  32. NVIC_Init(&NVIC_InitStructure); //根据NVIC_InitStruct中指定的参数初始化外设NVIC寄存器
  33. TIM_Cmd(TIM3, ENABLE); //使能TIMx外设
  34. }
  35. char humi,temp,buf2[50];
  36. void TIM3_IRQHandler(void) //TIM3中断
  37. {
  38. if (TIM_GetITStatus(TIM3, TIM_IT_Update) != RESET) //检查指定的TIM中断发生与否:TIM 中断源
  39. {
  40. LED0=!LED0;
  41. DHT11_Read_Data(&temp,&humi);
  42. sprintf(buf2,"AT+MQTTPUB=0,\"pubtest\",\"temp:%d%d\\\,humi:%d%d\",0,0",temp/10,temp%10,humi/10,humi%10);
  43. printf("buf2:%s\r\n",buf2);
  44. wifi_send_cmd(buf2,"OK",100);
  45. TIM_ClearITPendingBit(TIM3, TIM_IT_Update ); //清除TIMx的中断待处理位:TIM 中断源
  46. }
  47. }

(3)main函数代码

  1. #include "led.h"
  2. #include "delay.h"
  3. #include "sys.h"
  4. #include "usart.h"
  5. #include "usart2.h"
  6. #include "dht11.h"
  7. #include "wifi.h"
  8. #include "timer.h"
  9. #include <string.h>
  10. char *cmdLEDON = "+MQTTSUBRECV:0,\"subtest\",5,LEDON";
  11. char *cmdLEDOFF = "+MQTTSUBRECV:0,\"subtest\",6,LEDOFF";
  12. int main(void)
  13. {
  14. delay_init(); //延时函数初始化
  15. LED_Init(); //初始化与LED连接的硬件接口
  16. wifi_GPIO_Init();
  17. uart_init(9600);
  18. USART2_Init(115200); //连接ESP8266
  19. DHT11_Init(); //dht11
  20. rst_wifi();
  21. init_wifi();
  22. TIM3_Int_Init(9999,35999); //5s
  23. while(1)
  24. {
  25. if(USART2_RX_STA&0X8000)
  26. {
  27. if(!memcmp(USART2_RX_BUF,cmdLEDON,strlen(cmdLEDON)))
  28. {
  29. //开灯
  30. LED1 = 0;
  31. printf("开灯\r\n");
  32. }
  33. if(!memcmp(USART2_RX_BUF,cmdLEDOFF,strlen(cmdLEDOFF)))
  34. {
  35. //关灯
  36. LED1 = 1;
  37. printf("关灯\r\n");
  38. }
  39. memset(USART2_RX_BUF,0,1024);
  40. USART2_RX_STA = 0;
  41. }
  42. }
  43. }

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/菜鸟追梦旅行/article/detail/296722
推荐阅读
相关标签
  

闽ICP备14008679号