STM32通过esp8266连接WiFi接入MQTT服务器

简介: STM32通过esp8266连接WiFi接入MQTT服务器

上文我们讲到如何搭建本地MQTT服务器,现在介绍如何通过stm32连接MQTT

一.首先我们初始化esp8266这里我们使用的是USART4与其通信代码如下

1. void UART4_Init(uint32_t bound)
2. {
3.  GPIO_InitTypeDef GPIO_InitStructure;
4.  USART_InitTypeDef USART_InitStructure;
5. 
6. 
7.  RCC_APB1PeriphClockCmd(RCC_APB1Periph_UART4, ENABLE); //使能UART4,GPIOA时钟
8.  RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOC, ENABLE);
9. 
10.   USART_DeInit(UART4);  //复位串口4
11. 
12.   //UART4_TX   PC.10 
13.   GPIO_InitStructure.GPIO_Pin = GPIO_Pin_10; 
14.   GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
15.   GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP; //复用推挽输出
16.   GPIO_Init(GPIOC, &GPIO_InitStructure); //初始化PC10
17. 
18.   //UART4_RX    PC.11
19.   GPIO_InitStructure.GPIO_Pin = GPIO_Pin_11;
20.   GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;//浮空输入
21.   GPIO_Init(GPIOC, &GPIO_InitStructure);  //初始化PC11
22. 
23.   //USART 初始化设置
24.   USART_InitStructure.USART_BaudRate = bound; //设置波特率,一般设置为9600;
25.   USART_InitStructure.USART_WordLength = USART_WordLength_8b; //字长为8位数据格式
26.   USART_InitStructure.USART_StopBits = USART_StopBits_1;  //一个停止位
27.   USART_InitStructure.USART_Parity = USART_Parity_No; //无奇偶校验位
28.   USART_InitStructure.USART_HardwareFlowControl = USART_HardwareFlowControl_None; //无硬件数据流控制
29.   USART_InitStructure.USART_Mode = USART_Mode_Rx | USART_Mode_Tx; //收发模式
30. 
31.   USART_Init(UART4, &USART_InitStructure); //初始化串口
32.   USART_ITConfig(UART4, USART_IT_RXNE, ENABLE);//开启中断
33.   USART_Cmd(UART4, ENABLE);                    //使能串口 
34. 
35. 
36.   TIM7_Int_Init(100-1,7200-1);    //10ms 为了判断是不是一串数据后文有解释
37. 
38.   TIM_Cmd(TIM7,ENABLE);     //
39. }

二.通过数据间隔时间来判断是否是一串数据如果间隔时间大于30ms则判定为不是一串数据,接收缓冲器清零。 代码如下!

1. //定时器7中断服务程序       
2. void TIM7_IRQHandler(void)
3. {  
4.  if (TIM_GetITStatus(TIM7, TIM_IT_Update) != RESET)//是更新中断
5.  {
6. 
7.    TIM_ClearITPendingBit(TIM7, TIM_IT_Update  );  //清除TIM7更新中断标志    
8.      if(F_UART4_RX_RECEIVING)//正在接收串口数据
9.    {
10.       UART4_RX_TIMEOUT_COUNT++;//串口超时计数
11.       if(UART4_RX_TIMEOUT_COUNT>3)//数据接收间隔超过30ms
12.       {//串口接收完成或结束
13.         F_UART4_RX_RECEIVING=0;
14.         UART4_RX_TIMEOUT_COUNT=0;
15.         F_UART4_RX_FINISH=1;
16.       }
17.     }
18.   }     
19. }
20. 
21. 
22. //定时器溢出时间计算方法:Tout=((arr+1)*(psc+1))/Ft us.
23. //Ft=定时器工作频率,单位:Mhz 
24. //通用定时器中断初始化
25. //这里始终选择为APB1的2倍,而APB1为36M
26. //arr:自动重装值。
27. //psc:时钟预分频数     
28. void TIM7_Int_Init(u16 arr,u16 psc)
29. { 
30.   NVIC_InitTypeDef NVIC_InitStructure;
31.   TIM_TimeBaseInitTypeDef  TIM_TimeBaseStructure;
32. 
33.   RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM7, ENABLE);//TIM7时钟使能    
34. 
35.   //定时器TIM7初始化
36.   TIM_TimeBaseStructure.TIM_Period = arr; //设置在下一个更新事件装入活动的自动重装载寄存器周期的值 
37.   TIM_TimeBaseStructure.TIM_Prescaler =psc; //设置用来作为TIMx时钟频率除数的预分频值
38.   TIM_TimeBaseStructure.TIM_ClockDivision = TIM_CKD_DIV1; //设置时钟分割:TDTS = Tck_tim
39.   TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up;  //TIM向上计数模式
40.   TIM_TimeBaseInit(TIM7, &TIM_TimeBaseStructure); //根据指定的参数初始化TIMx的时间基数单位
41. 
42.   TIM_ITConfig(TIM7,TIM_IT_Update,ENABLE ); //使能指定的TIM7中断,允许更新中断
43. 
44.   TIM_Cmd(TIM7,ENABLE);//开启定时器7
45. 
46.   NVIC_InitStructure.NVIC_IRQChannel = TIM7_IRQn;
47.   NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority=0 ;//抢占优先级0
48.   NVIC_InitStructure.NVIC_IRQChannelSubPriority = 2;    //子优先级2
49.   NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;     //IRQ通道使能
50.   NVIC_Init(&NVIC_InitStructure); //根据指定的参数初始化VIC寄存器
51. 
52. }

三.初始化esp8266后我们就可以连接WiFi及mqtt了

首先我们将esp8266设置为station模式,如果返回ok则设置成功

代码如下:

1. #define AT_CWMODE  "AT+CWMODE=1" //设置为“station”模式
2. int8_t ESP8266_SetStation(void)
3. {
4.  ClrAtRxBuf();//清空缓存
5.  SendAtCmd((uint8_t *)AT_CWMODE,strlen(AT_CWMODE));
6.  delay_ms(100);
7.  if(strstr((const char *)AT_RX_BUF, (const char *)"OK") == NULL)
8.  {
9.    return -1;
10.   }
11.   return 0;
12. }

四.设置成功之后就可以连接WiFi(可以是路由器也可以是手机或电脑开热点)

代码如下:

1. /*******************************************************************
2. *函数:int8_t ESP8266_SetAP(void)
3. *功能:设置ESP8266要连接的热点名称和密码
4. *输入:char *wifi-热点名称 char *pwd-热点密码
5. *输出:
6.    return = 0 ,sucess
7.    return < 0 ,error
8. *特殊说明:
9. *******************************************************************/
10. #define WIFI_AP   "dmx"//WiFi热点名称       
11. #define WIFI_PWD  "88888888"  //WiFi密码
12. 
13. int8_t ESP8266_SetAP(void)
14. {
15.   uint8_t AtCwjap[MAX_AT_TX_LEN];
16.   memset(AtCwjap, 0x00, MAX_AT_TX_LEN);//清空缓存
17.   ClrAtRxBuf();//清空缓存
18.   sprintf((char *)AtCwjap,"AT+CWJAP=\"%s\",\"%s\"",WIFI_AP, WIFI_PWD  );
19.   SendAtCmd((uint8_t *)AtCwjap,strlen((const char *)AtCwjap));
20.   delay_ms(5500);
21.   if(strstr((const char *)AT_RX_BUF, (const char *)"OK") == NULL)
22.   {
23.     return -1;
24.   }
25.   return 0;
26. }

五.现在就已经成功连接WiFi了下一步连接本地mqtt服务器(上篇博客我教大家如何搭建的)

1. #define SERVER_PC_IP "172.16.40.36"  //服务器IP地址
2. #define SERVER_PC_PORT 1883      //服务器端口号   
3. int8_t ESP8266_IpStart(void)
4. {
5.  uint8_t IpStart[MAX_AT_TX_LEN];
6.  memset(IpStart, 0x00, MAX_AT_TX_LEN);//清空缓存
7.  ClrAtRxBuf();//清空缓存
8. 
9.  /**************配置MQTT_USER信息***************/
10.   //AT+MQTTUSERCFG=0,1,"用户ID","账号","密码",0,0,""
11.                          //AT+MQTTUSERCFG=0,1,\"M3\",\"\",\"\",0,0,\"\"
12.   sprintf((char *)IpStart,"AT+MQTTUSERCFG=0,1,\"M3\",\"\",\"\",0,0,\"\"");
13.   SendAtCmd((uint8_t *)IpStart,strlen((const char *)IpStart));
14.   delay_ms(1500);
15.   printf("IpStart-USER_Config: %s\r\n", (char *)AT_RX_BUF);
16.   if(strstr((const char *)AT_RX_BUF, (const char *)"OK") == NULL)
17.   {
18.     /******断开连接*****/
19.     memset(IpStart, 0x00, MAX_AT_TX_LEN);//清空缓存
20.     ClrAtRxBuf();//清空缓存
21. 
22.     //AT+MQTTCLEAN=0
23.     sprintf((char *)IpStart,"AT+MQTTCLEAN=0");
24. 
25.     SendAtCmd((uint8_t *)IpStart,strlen((const char *)IpStart));
26. 
27.     return -1;
28.   }
29. 
30.   /**************建立MQTT连接***************/
31.   memset(IpStart, 0x00, MAX_AT_TX_LEN);//清空缓存
32.   ClrAtRxBuf();//清空缓存
33. 
34.   //AT+MQTTCONN=0,"服务器IP",1883,0
35.   //AT+MQTTCONN=0,"172.16.40.36",1883,0
36.   sprintf((char *)IpStart,"AT+MQTTCONN=0,\"%s\",%d,0",SERVER_PC_IP, SERVER_PC_PORT  );
37. 
38.   SendAtCmd((uint8_t *)IpStart,strlen((const char *)IpStart));
39.   delay_ms(1500);
40.   printf("IpStart-MQTT_Connect: %s\r\n", (char *)AT_RX_BUF);
41.   if(strstr((const char *)AT_RX_BUF, (const char *)"OK") == NULL)
42.   {
43.     return -2;
44.   }
45. 
46.   return 0;
47. }

六.经过以上五步就已经成功连接mqtt服务器了。现在通过命令设置自己为订阅者

1. int8_t ESP8266_MQTT_Sub(char *topic) //主题自己设置
2. {
3.  int8_t error = 0;
4.  uint8_t IpSend[MAX_AT_TX_LEN];
5.  memset(IpSend, 0x00, MAX_AT_TX_LEN);//清空缓存
6.  ClrAtRxBuf();//清空缓存
7. 
8. 
9.  //AT+MQTTSUB=0,M3",0
10.   sprintf((char *)IpSend,"AT+MQTTSUB=0,\"%s\",1", topic);
11.   SendAtCmd((uint8_t *)IpSend,strlen((const char *)IpSend));
12.   delay_ms(1500);
13.   printf("MQTT_Sub_Ack: %s\r\n",AT_RX_BUF);
14.   if(strstr((const char *)AT_RX_BUF, (const char *)"OK") == NULL)
15.   {
16.     return -4;
17.   }
18. 
19.   return error;
20. }

在这里我们通过mqtt.fx同样连接本地搭建的服务器,作为一个发布者发送消息stm32就能收到了。不过此处还没写收到信息的代码

七.stm32作为发布者者代码,这边你可以开一个mqtt.fx订阅相同的主题就能收到消息了

1. int8_t ESP8266_MQTT_Pub(char *IpBuf, uint8_t len, uint8_t qos)//信息 消息长度 以及qos(百度)
2. {
3.  uint8_t TryGo = 0;
4.  int8_t error = 0;
5.  uint8_t IpSend[MAX_AT_TX_LEN];
6.  memset(IpSend, 0x00, MAX_AT_TX_LEN);//清空缓存
7.  ClrAtRxBuf();//清空缓存
8.  /************设置为MQTT_Binary发送模式************/
9. /*   注意----------dmx为发布的主题-----------*/
10.   sprintf((char *)IpSend,"AT+MQTTPUBRAW=0,\"dmx\",%d,%d,0", len, qos);
11.   //printf("%s\r\n",IpSend);
12.   SendAtCmd((uint8_t *)IpSend,strlen((const char *)IpSend));
13.   delay_ms(100);
14.   //注意--如果断开连接或者怎么样,这一步ESP8266就会返回ERROR
15.   if(strstr((const char *)AT_RX_BUF, (const char *)"OK") == NULL)
16.   {
17.     printf("MQTT_Pub Fail:%s\r\n", AT_RX_BUF);
18.     MQTTSendErrorTimes++;
19.     return -1;
20.   }
21. 
22.   ClrAtRxBuf();//清空缓存
23. 
24.   //以二进制数据形式发送字符串
25.   SendAtCmd((uint8_t *)IpBuf, len);
26.   printf("MQTT_Pub: %s\r\n", IpBuf);
27.   if(qos == 0){
28.     return 0;
29.   }
30. 
31.   //等待qos回执处理
32.   delay_ms(100);
33.   if(strstr((const char *)AT_RX_BUF, (const char *)"OK") == NULL)
34.   {
35.     MQTTSendErrorTimes++;
36.     return -2;
37.   }
38.   return error;
39. }

八.到这里,完成的步骤已经完成,由于篇幅有限,很多细节也讲不完,如果有什么问题可以评论区留言,最后我附一个搭建好的mqtt的一个简易智能家居!可以读取各种传感器器数据,如温湿度,光照,烟雾溶度等上传给服务器,风扇 PWM灯也可以被服务器传来的数据控制。

相关实践学习
消息队列RocketMQ版:基础消息收发功能体验
本实验场景介绍消息队列RocketMQ版的基础消息收发功能,涵盖实例创建、Topic、Group资源创建以及消息收发体验等基础功能模块。
消息队列 MNS 入门课程
1、消息队列MNS简介 本节课介绍消息队列的MNS的基础概念 2、消息队列MNS特性 本节课介绍消息队列的MNS的主要特性 3、MNS的最佳实践及场景应用 本节课介绍消息队列的MNS的最佳实践及场景应用案例 4、手把手系列:消息队列MNS实操讲 本节课介绍消息队列的MNS的实际操作演示 5、动手实验:基于MNS,0基础轻松构建 Web Client 本节课带您一起基于MNS,0基础轻松构建 Web Client
目录
相关文章
|
1月前
|
传感器 数据采集 移动开发
基于STM32的智能手环wifi连接手机APP(下)
基于STM32的智能手环wifi连接手机APP(下)
72 0
|
3月前
|
传感器 网络协议 物联网
手把手教你在 Windows 环境中搭建 MQTT 服务器
手把手教你在 Windows 环境中搭建 MQTT 服务器
281 0
|
1月前
|
传感器 存储 编解码
基于STM32的智能手环wifi连接手机APP(上)
基于STM32的智能手环wifi连接手机APP(上)
57 0
|
3月前
|
Ubuntu 网络安全 数据安全/隐私保护
ubuntu server连接wifi教程
本文提供了一个简化Ubuntu Server在Raspberry Pi系统上配置过程的脚本"config_ubuntu_server",包括自动和手动两种方法来设置root权限、SSH配置,并连接WiFi,同时支持无密码SSH访问,适合初学者和高级用户。
84 3
|
5月前
|
IDE 物联网 网络性能优化
什么是MQTT?如何使用ESP12F芯片连接到MQTT服务器
通过上述步骤,你可以成功地使用ESP12F模块连接到MQTT服务器,发布和订阅消息。MQTT的轻量级和高效性使其非常适合各种物联网应用,而ESP12F模块的强大功能和低成本使其成为实现这些应用的理想选择。
199 0
|
5月前
|
消息中间件 Serverless 网络性能优化
消息队列 MQ产品使用合集之客户端和服务器之间的保活心跳检测间隔是怎么设置的
消息队列(MQ)是一种用于异步通信和解耦的应用程序间消息传递的服务,广泛应用于分布式系统中。针对不同的MQ产品,如阿里云的RocketMQ、RabbitMQ等,它们在实现上述场景时可能会有不同的特性和优势,比如RocketMQ强调高吞吐量、低延迟和高可用性,适合大规模分布式系统;而RabbitMQ则以其灵活的路由规则和丰富的协议支持受到青睐。下面是一些常见的消息队列MQ产品的使用场景合集,这些场景涵盖了多种行业和业务需求。
|
5月前
使用STM32F103标准库实现定时器控制LED点亮和关闭
通过这篇博客,我们学习了如何使用STM32F103标准库,通过定时器来控制LED的点亮和关闭。我们配置了定时器中断,并在中断处理函数中实现了LED状态的切换。这是一个基础且实用的例子,适合初学者了解STM32定时器和中断的使用。 希望这篇博客对你有所帮助。如果有任何问题或建议,欢迎在评论区留言。
431 2
|
4月前
stm32f407探索者开发板(十七)——串口寄存器库函数配置方法
stm32f407探索者开发板(十七)——串口寄存器库函数配置方法
699 0
|
5月前
|
IDE 开发工具
使用STM32F103标准库实现自定义键盘
通过本文,我们学习了如何使用STM32F103标准库实现一个简单的自定义键盘。我们首先初始化了GPIO引脚,然后实现了一个扫描函数来检测按键状态。这个项目不仅能够帮助我们理解STM32的GPIO配置和按键扫描原理,还可以作为进一步学习中断处理和低功耗设计的基础。希望本文对你有所帮助,祝你在嵌入式开发的道路上不断进步!
503 4