ESP826601S+STM32通过AT指令连接阿里云
文章目录
- ESP826601S+STM32通过AT指令连接阿里云
- 1、烧录ESP8266AT固件
- 2、获取设备MQTT连接参数
- 3、进行STM32代码编写
- 3.1、流程!
- 3.2、话不多说,上代码,先将一些准备参数进行一个宏定义!
- 3.3、坑!!!!!
- 3.3.1--回车换行
- 3.3.2---MQTT连接参数
- 3.3.3--逗号
- 3.3.4--双引号
- 3.3.5 这些就是我在准备参数中遇到的问题,如果大家有更好的方法去解决或者有新问题也欢迎评论区留言。下面来看我的具体连接代码
- 3.3.6在这个具体的连接代码中,我也遇到几个问题,在此说明,希望给大家一个参考!
- 3.3.11接下来是主函数实现。
- 3.3.12这里我不方便放全代码,大家看一下我的连接阿里云就行,经过上面的编写,这边主函数只是进行一个函数调用,然后发布数据就行,但是我的发布写的很糟糕,可以说又臭又长,现在一时没有想到好的解决办法,大家有建议欢迎指出。
1、烧录ESP8266AT固件
1.1、这里选择安信可的MQTT透传固件(固件号1471)
直接点击次链接进行一个下载,我使用的是01S,flash只有1M,所以选择这个,你们按照需要进行一个下载,烧录工具安信可也进行提供了的,点击此链接进行一个下载,下载之后烧录ESP826601s。
2、获取设备MQTT连接参数
2.1、登录阿里云物联网平台
去阿里云物联网平台中进行一个产品的创建,然后创建设备,获取设备的MQTT连接参数,这里我就不再描述了,现在有很多教你怎么去配置阿里云的。博主这里默认你们会了。
3、进行STM32代码编写
3.1、流程!
先说一下我的一个流程,我这边使用的是STM32F103C8T6最小系统板,有三个串口,串口1作为调试串口,串口2用来与01s进行一个通讯,串口3用来获取传感器数据。
3.2、话不多说,上代码,先将一些准备参数进行一个宏定义!
#ifndef __ALY_H
#define __ALY_H
#include "stm32f10x.h"
//注意,clientId中有逗号需要在逗号前加入“\\”
//阿里云MQTT--clientId
#define ALY_clientId "a1j1PgnBJjr.test1|securemode=2\\,signmethod=hmacsha256\\,timestamp=1674444301740|"
//阿里云MQTT-用户名
#define ALY_username "test1&a1j1PgnBJjr"
//阿里云MQTT--密码
#define ALY_passwd "36d12b53812c7f6c731027649de9fd04084ab42016bfd826acd73716056a5046"
//阿里云MQTT--端口地址
#define ALY_mqttHostUrl "a1j1PgnBJjr.iot-as-mqtt.cn-shanghai.aliyuncs.com"
//阿里云MQTT--端口号
#define ALY_port 1883
//在配置MQTT用户属性时的一个自定义ID
#define ALY_client_id "ESP8266"
//阿里云MQTT环境资源--这里不需要
#define ALY_path ""
//阿里云订阅Topic
#define ALY_SUB "/sys/a1j1PgnBJjr/test1/thing/service/property/set"
//阿里云发布Topic
#define ALY_PUB "/sys/a1j1PgnBJjr/test1/thing/event/property/post"
//阿里云发布数据
#define ALY_buffer "{\\\"method\\\":\\\"thing.service.property.post\\\"\\,\\\"id\\\":\\\"2012934115\\\"\\,\\\"params\\\":{\\\"co\\\":15\\,\\\"RoomHumidity\\\":12.1}\\,\\\"version\\\":\\\"1.0.0\\\"}"
//阿里云自定义topic
#define ALY_ZDY "/a1j1PgnBJjr/test1/user/update"
//阿里云自定义发布内容
#define ZDY_buffer "hello"
//WiFi名称和密码
#define Wifi_Name "Xiaomi_F617"
#define Wifi_Password "chenlong"
//在进行连接阿里云之前的一些配置参数
//AT--用来检查AT固件是否烧入成功
#define ESP8266_AT "AT\r\n"
//复位
#define ESP8266_Reset "AT+RST\r\n"
//恢复出厂设置
#define ESP8266_RESTORE "AT+RESTORE\r\n"
//设置连接WiFi模式
#define ESP8266_CWMODE "AT+CWMODE=3\r\n"
//设置SNTP服务器
#define ESP8266_CIPSNTPCFG "AT+CIPSNTPCFG=1,8,\"ntp1.aliyun.com\"\r\n"
//连接阿里云
uint8_t Connect_ALY(void);
//判断AT指令是否发送成功
uint8_t ESP8266_AT_Handle(void);
//判断阿里云是否连接成功
uint8_t ALY_Connect_Handle(void);
#endif
3.3、坑!!!!!
这些准备参数中,有很多坑博主是踩过一遍了,想了好多天才发现问题所在,在此列出希望给大家一点帮助!
3.3.1–回车换行
所有的AT指令发送都必须加回车换行,否则视为发送失败,当时以为自己固件出问题了,但其实不然,这里面的回车换行是\r\n,不是单独的\n。
3.3.2—MQTT连接参数
那个连接阿里云的参数,直接去设备里面找,
不用在去用第三方工具进行加密了,直接赋值就行,安全性够了的。
3.3.3–逗号
在MQTT连接参数中,你如果直接复制他的Clientid参数,你发现报错的,当时我人傻了很久,后来发现,连接阿里云,用的是JSON格式,我们现在没去加JSON库,但是要按照他的格式去写,需要在每个逗号前面加\,去转义。具体去看我的代码中的操作。
3.3.4–双引号
这个问题折磨了好几天,在你都能订阅连接成功之后,发布自定义Topic数据能成功,但是发布物模型数据确始终不能成功,找了好久,当时都想放弃了,最后发现是双引号问题,归根到底还是json格式问题,我们在发布物模型数据的时候,是按照JSON格式来的,双引号前同样需要加入\进行转义,同时还需要一个\来进行一个表示它不代表字符串的意思,具体去看我的代码,还有逗号,一定不要搞错了,这里特别容易出问题。
3.3.5 这些就是我在准备参数中遇到的问题,如果大家有更好的方法去解决或者有新问题也欢迎评论区留言。下面来看我的具体连接代码
#include "aly.h"
#include "delay.h"
#include "usart2.h"
#include "usart1.h"
/*
函数内容:通过ESP826601S--AT指令连接阿里云
*/
uint8_t Connect_ALY(void)
{
//循环发送次数
int i=0;
//失败编号
uint8_t err=0;
//临时内容数组
char temp_buffer[128]={0};
//复位
for(i=0;i<5;i++)
{
UsartOutStr(USART2,(uint8_t *)ESP8266_Reset,strlen(ESP8266_Reset));
err=ESP8266_AT_Handle();
if(err!=0)
{
break;
}
delay_ms(100);
}
if(i>=5)
{
return 1;
}
//恢复出厂设置
for(i=0;i<5;i++)
{
UsartOutStr(USART2,(uint8_t *)ESP8266_RESTORE,strlen(ESP8266_RESTORE));
err=ESP8266_AT_Handle();
if(err!=0)
{
break;
}
delay_ms(100);
}
if(i>=5)
{
return 2;
}
//配置WiFi模式
for(i=0;i<5;i++)
{
UsartOutStr(USART2,(uint8_t *)ESP8266_CWMODE,strlen(ESP8266_CWMODE));
err=ESP8266_AT_Handle();
if(err!=0)
{
break;
}
delay_ms(100);
}
if(i>=5)
{
return 3;
}
//开启SNTP服务器,8时域,SNTP服务器为阿里云域名
for(i=0;i<5;i++)
{
UsartOutStr(USART2,(uint8_t *)ESP8266_CIPSNTPCFG,strlen(ESP8266_CIPSNTPCFG));
err=ESP8266_AT_Handle();
if(err!=0)
{
break;
}
delay_ms(100);
}
if(i>=5)
{
return 4;
}
//连接wifi
for(i=0;i<5;i++)
{
memset(temp_buffer,0,128);
sprintf(temp_buffer,"AT+CWJAP=\"%s\",\"%s\"\r\n",Wifi_Name,Wifi_Password);
UsartOutStr(USART2,(uint8_t *)temp_buffer,strlen(temp_buffer));
err=ESP8266_AT_Handle();
if(err!=0)
{
break;
}
delay_ms(500);
err=ESP8266_AT_Handle();
if(err!=0)
{
break;
}
delay_ms(500);
err=ESP8266_AT_Handle();
if(err!=0)
{
break;
}
}
if(i>=5)
{
return 5;
}
//配置 MQTT 用户属性
for(i=0;i<5;i++)
{
memset(temp_buffer,0,128);
sprintf(temp_buffer,"AT+MQTTUSERCFG=%d,%d,\"%s\",\"%s\",\"%s\",%d,%d,\"%s\"\r\n",
0,1,ALY_client_id,ALY_username,ALY_passwd,0,0,ALY_path);
UsartOutStr(USART2,(uint8_t *)temp_buffer,strlen(temp_buffer));
err=ESP8266_AT_Handle();
if(err!=0)
{
break;
}
delay_ms(100);
}
if(i>=5)
{
return 6;
}
//配置 MQTT 客户端 ID
for(i=0;i<5;i++)
{
memset(temp_buffer,0,128);
sprintf(temp_buffer,"AT+MQTTCLIENTID=%d,\"%s\"\r\n",0,ALY_clientId);
UsartOutStr(USART2,(uint8_t *)temp_buffer,strlen(temp_buffer));
err=ESP8266_AT_Handle();
if(err!=0)
{
break;
}
delay_ms(100);
}
if(i>=5)
{
return 7;
}
//查询连接状态
memset(temp_buffer,0,128);
sprintf(temp_buffer,"AT+MQTTCONN?\r\n");
UsartOutStr(USART2,(uint8_t *)temp_buffer,strlen(temp_buffer));
err=ALY_Connect_Handle();
if(err==0)
{
//连接 MQTT Broker
memset(temp_buffer,0,128);
sprintf(temp_buffer,"AT+MQTTCONN=%d,\"%s\",%d,%d\r\n",0,ALY_mqttHostUrl,ALY_port,0);
UsartOutStr(USART2,(uint8_t *)temp_buffer,strlen(temp_buffer));
while(1)
{
if(Usart2ReadCnt>0)
{
UsartOutStr(USART1,(uint8_t *)Usart2ReadBuff,strlen((char *)Usart2ReadBuff));
if(strstr((char *)Usart2ReadBuff,"+MQTTCONNECTED")!=NULL)
{
Recover_Usart2();
break;
}
Recover_Usart2();
}
}
}
//订阅指令
for(i=0;i<5;i++)
{
memset(temp_buffer,0,128);
sprintf(temp_buffer,"AT+MQTTSUB=%d,\"%s\",%d\r\n",0,ALY_SUB,0);
UsartOutStr(USART2,(uint8_t *)temp_buffer,strlen(temp_buffer));
err=ESP8266_AT_Handle();
if(err!=0)
{
break;
}
delay_ms(100);
}
if(i>=5)
{
return 9;
}
return 0;
}
/*
函数内容:ESP8266发送AT指令之后的处理函数
函数参数:无
返回值: 发送成功--1
失败--0
*/
uint8_t ESP8266_AT_Handle(void)
{
uint8_t i=0;
char *err=NULL;
for(i=0;i<10;i++)
{
if(Usart2ReadCnt>0)
{
err=strstr((char *)Usart2ReadBuff,"OK");
if(err==NULL)
{
UsartOutStr(USART1,(uint8_t *)Usart2ReadBuff,strlen((char *)Usart2ReadBuff));
Recover_Usart2();
return 0;
}
else
{
UsartOutStr(USART1,(uint8_t *)Usart2ReadBuff,strlen((char *)Usart2ReadBuff));
Recover_Usart2();
return 1;
}
}
delay_ms(100);
}
return 0;
}
/*
函数内容:ESP8266发送连接阿里云AT指令之后的处理函数
函数参数:无
返回值: 已经连接--1
没有连接--0
*/
uint8_t ALY_Connect_Handle(void)
{
uint8_t i=0;
char *err=NULL;
for(i=0;i<10;i++)
{
if(Usart2ReadCnt>0)
{
UsartOutStr(USART1,(uint8_t *)Usart2ReadBuff,strlen((char *)Usart2ReadBuff));
err=strstr((char *)Usart2ReadBuff,"+MQTTCONN:0,4");
if(err!=NULL)
{
Recover_Usart2();
return 1;
}
err=strstr((char *)Usart2ReadBuff,"+MQTTCONN:0,5");
if(err!=NULL)
{
Recover_Usart2();
return 1;
}
err=strstr((char *)Usart2ReadBuff,"+MQTTCONN:0,6");
if(err!=NULL)
{
Recover_Usart2();
return 1;
}
Recover_Usart2();
}
delay_ms(100);
}
return 0;
}
3.3.6在这个具体的连接代码中,我也遇到几个问题,在此说明,希望给大家一个参考!
3.3.7、发送太少
在一开始,我是发送一次数据然后直接判断他的回复是否是OK,因为我使用的是串口+DMA接收的方式,但是实测发现会有很多问题,它有可能还没来得及回复,并且它的回复是片段,我有可能接收不完全,而且他的回复有时候第一次是ERROR,第二次就变成OK了,所以,我这边用了一个for循环去多发几次,尽可能降低误判。
3.3.8、等待太短
在连接WiFi的时候,需要注意,你发送连接指令,它是需要时间去进行一个连接的,所以,我这边发送一次连接指令,就间隔0.5秒去判断,多判断几次,等待它的一个连接相应。
3.3.9、重复连接
在连接阿里云的时候,我做了一个判断,有可能你上次没有断开连接,然后你这边进行一个查询,如果连接还在,就不要重复发送连接指令了。同时,连接阿里云也是需要时间的,我这里写的不是很好,我想的是WiFi也连接成功了,参数也配置成功了,这边我发送连接指令,我就一直等它连接,这里是一个死循环,后续大家可以加一个跳出变量,死循环在代码中最好别用。
3.3.10、错误定位
一定要加返回错误值,这样你可以很清楚知道在哪里出问题了,这种写法特别适合我这种不习惯用单步调试的人,可以帮我们很快定位问题。
3.3.11接下来是主函数实现。
//连接阿里云
err=Connect_ALY();
switch(err)
{
case 0:
OLED_ShowString(1,2,"Cnnect OK");
break;
case 1:
OLED_ShowString(1,2,"Reset Fail");
break;
case 2:
OLED_ShowString(1,2,"RESTORE Fail");
break;
case 3:
OLED_ShowString(1,2,"CWMODE Fail");
break;
case 4:
OLED_ShowString(1,2,"SNTP Fail");
break;
case 5:
OLED_ShowString(1,2,"Wifi Fail");
break;
case 6:
OLED_ShowString(1,2,"SERCFG Fail");
break;
case 7:
OLED_ShowString(1,2,"CLIENTID Fail");
break;
case 8:
OLED_ShowString(1,2,"CONN Fail");
break;
case 9:
OLED_ShowString(1,2,"SUB Fail");
break;
default:
OLED_ShowString(1,2,"Other Fail");
break;
}
while(1)
{
//获取温湿度值
DHT11_REC_Data();
//获取一氧化碳值
Usart3_Handle();
//更新温度值
Updata_T(rec_data[2],rec_data[3]);
//更新湿度值
Updata_R(rec_data[0],rec_data[1]);
//更新一氧化碳值
Updata_CO(Co_Value);
memset(Send_Buffer,0,128);
sprintf(Send_Buffer,"AT+MQTTPUB=0,\"%s\",\"{\\\"method\\\":\\\"thing.service.property.post\\\"\\,\\\"id\\\":\\\"2012934115\\\"\\,\\\"params\\\":{\\\"co\\\":%d\\,\\\"RoomHumidity\\\":%f\\,\\\"RoomTemp\\\":%f}\\,\\\"version\\\":\\\"1.0.0\\\"}\",%d,%d\r\n",
ALY_PUB,Co_Value,(rec_data[0]*100+rec_data[1])/100.0f,(rec_data[2]*100+rec_data[3])/100.0f,1,0);
UsartOutStr(USART2,(uint8_t *)Send_Buffer,strlen(Send_Buffer));
ESP8266_AT_Handle();
delay_ms(500);
}
}