ESP826601S+STM32通过AT指令连接阿里云

ESP826601S+STM32通过AT指令连接阿里云

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);
	}
}

3.3.12这里我不方便放全代码,大家看一下我的连接阿里云就行,经过上面的编写,这边主函数只是进行一个函数调用,然后发布数据就行,但是我的发布写的很糟糕,可以说又臭又长,现在一时没有想到好的解决办法,大家有建议欢迎指出。

  • 2
    点赞
  • 44
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值