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一站式入门使用
从源码编译、部署broker、部署namesrv,使用java客户端首发消息等一站式入门RocketMQ。
消息队列 MNS 入门课程
1、消息队列MNS简介 本节课介绍消息队列的MNS的基础概念 2、消息队列MNS特性 本节课介绍消息队列的MNS的主要特性 3、MNS的最佳实践及场景应用 本节课介绍消息队列的MNS的最佳实践及场景应用案例 4、手把手系列:消息队列MNS实操讲 本节课介绍消息队列的MNS的实际操作演示 5、动手实验:基于MNS,0基础轻松构建 Web Client 本节课带您一起基于MNS,0基础轻松构建 Web Client
目录
相关文章
|
30天前
|
消息中间件 物联网 网络性能优化
MQTT常见问题之mqtt 连接一直显示 Not authorized to connect如何解决
MQTT(Message Queuing Telemetry Transport)是一个轻量级的、基于发布/订阅模式的消息协议,广泛用于物联网(IoT)中设备间的通信。以下是MQTT使用过程中可能遇到的一些常见问题及其答案的汇总:
|
1月前
|
SQL 分布式计算 DataWorks
DataWorks常见问题之dataworks连接FTP服务器失败如何解决
DataWorks是阿里云提供的一站式大数据开发与管理平台,支持数据集成、数据开发、数据治理等功能;在本汇总中,我们梳理了DataWorks产品在使用过程中经常遇到的问题及解答,以助用户在数据处理和分析工作中提高效率,降低难度。
|
1月前
|
运维 Linux Nacos
nacos常见问题之远程访问不报错放到服务器上nacos连接超时如何解决
Nacos是阿里云开源的服务发现和配置管理平台,用于构建动态微服务应用架构;本汇总针对Nacos在实际应用中用户常遇到的问题进行了归纳和解答,旨在帮助开发者和运维人员高效解决使用Nacos时的各类疑难杂症。
59 1
|
21天前
|
网络协议 Python
pythonTCP客户端编程连接服务器
【4月更文挑战第6天】本教程介绍了TCP客户端如何连接服务器,包括指定服务器IP和端口、发送连接请求、处理异常、进行数据传输及关闭连接。在Python中,使用`socket`模块创建Socket对象,然后通过`connect()`方法尝试连接服务器 `(server_ip, server_port)`。成功连接后,利用`send()`和`recv()`进行数据交互,记得在通信完成后调用`close()`关闭连接,确保资源释放和程序稳定性。
|
1天前
|
监控 Linux 网络安全
Linux服务器如何查询连接服务器的IP
【4月更文挑战第17天】Linux服务器如何查询连接服务器的IP
7 1
|
8天前
|
网络协议 安全 Linux
IDEA通过内网穿透实现固定公网地址远程SSH连接本地Linux服务器
IDEA通过内网穿透实现固定公网地址远程SSH连接本地Linux服务器
|
20天前
|
弹性计算 前端开发 Java
使用阿里云 mqtt serverless 版本超低成本快速实现 webscoket 长链接服务器
使用阿里云 MQTT Serverless 可轻松实现弹性伸缩的 WebSocket 服务,每日成本低至几元。适用于小程序消息推送的 MQTT P2P 模式。前端需注意安全,避免 AK 泄露,采用一机一密方案。后端通过调用 `RegisterDeviceCredential` API 发送消息。示例代码包括 JavaScript 前端连接和 Java 后端发送。
190 0
|
25天前
|
弹性计算 关系型数据库 MySQL
阿里云数据库服务器价格表,数据库创建、连接和使用教程
阿里云数据库使用流程包括购买和管理。选择所需数据库类型如MySQL,完成实名认证后购买,配置CPU、内存和存储。确保数据库地域与ECS相同以允许内网连接。创建数据库和账号,设置权限。通过DMS登录数据库,使用账号密码连接。同一VPC内的ECS需添加至白名单以进行内网通信。参考官方文档进行详细操作。
126 3
|
1月前
|
前端开发 安全 数据安全/隐私保护
WPA_CLI 的介绍:介绍如何使用wpa_cli连接WiFi的方法
WPA_CLI 的介绍:介绍如何使用wpa_cli连接WiFi的方法
50 2
|
1月前
|
Java Maven Android开发
java如何连接mqtt
java如何连接mqtt
45 0