STM32+ESP8266(ESP-12F)物联网温度计-腾讯云物联网

Posted Fog.

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了STM32+ESP8266(ESP-12F)物联网温度计-腾讯云物联网相关的知识,希望对你有一定的参考价值。

STM32+ESP8266(ESP-12F)物联网温度计-腾讯云物联网

一、硬件及软件准备

1、完整工程源码

下载地址:https://download.csdn.net/download/qq_44062900/19747292

2、硬件:STM32单片机、ESP8266(ESP-12F)、DS18B20

注:ESP8266刷的固件是标准的AT指令固件,不同版本AT固件的AT指令略有不同,请注意!

3、软件:Keil5、安信可串口调试助手、wireshark网络抓包工具

安信可串口调试助手下载:https://docs.ai-thinker.com/%E5%BC%80%E5%8F%91%E5%B7%A5%E5%85%B72
wireshark下载地址:https://www.wireshark.org/download.html

二、 实现效果

腾讯连连微信小程序显示实时温度,并且可以远程控制开发板的LED灯

三、 paho MQTT协议库移植

有关 paho MQTT协议库移植请移步:STM32+ESP8266(ESP-12F)物联网温度计-移植paho MQTT协议连接阿里云

四、 腾讯云物联网产品及设备创建

如果是第一次使用腾讯云产品,需要先进行实名认证。下面直接从物联网控制台着手。
物联网控制台地址:https://console.cloud.tencent.com/iotexplorer
点击“公共实例”

点击“新建项目”

输入项目名称,点击“保存”即可

点击“项目ID”进入项目管理页面

点击“新建产品”,输入产品信息,点击“保存”


点击产品ID进入产品管理页面

点击“新建功能”

输入自定义功能,一个是温度上传,一个是LED控制


创建完功能后点击“下一步”

保存以下两个Topic,后面会用到,然后点击“下一步”。

下面开始配置腾讯连连微信小程序,使用腾讯连连可以很方便地设计一个APP管理程序。

点击“保存”,返回后点击“下一步”


点击“新建设备”,输入设备名称后点击保存


点击“设备名称”,复制“设备名称”、“设备秘钥”及“产品ID”并保存在文本文件中,后面激活设备需要用到。



点击“二维码”


在微信小程序中搜索“腾讯连连”,进入后点击“扫一扫”,扫描上方二维码添加设备

五、ESP8266配置

由于MQTT协议是基于TCP传输层协议之上的应用层协议,所以在使用MQTT进行通信之前首先要和服务器建立TCP连接,这样我们才能通过MQTT协议连接到腾讯云物联网平台。

配置总流程:测试ESP8266>>>配置WIFI工作模式为Station(终端)或AP+Station(接入点+终端)>>>重启模块>>>关闭回显>>>连接WIFI>>>设为透传模式>>>建立TCP连接>>>开启透传>>>使用MQTT协议进行通信

注:ESP-12F的固件是标准的AT指令,在给ESP8266发送指令时,要在指令最后加上"\\r\\n"结束符

1、测试ESP8266模块

指令:“AT+\\r\\n”
测试成功则返回"OK"

2、配置WIFI工作模式

指令:“AT+CWMODE=1\\r\\n”
配置成功则返回"OK"

3、重启WIFI模块

指令:“AT+RST\\r\\n”
发送指令后需等待几秒钟,等ESP8266复位完成

4、关闭回显

指令:“ATE0\\r\\n”
配置成功返回"OK"

5、连接WIFI

指令:“AT+CWJAP=“ssid”,“pass”\\r\\n”
其中ssid为WIFI名称,pass为WIFI密码
配置成功返回"OK"

6、设为透传模式

指令:“AT+CIPMODE=1\\r\\n”
配置成功返回"OK"

7、建立TCP连接

指令:“AT+CIPSTART=“TCP”,“ip”,port\\r\\n”
其中ip为服务器ip,这里为"71248IVBSR.iotcloud.tencentdevices.com"
port为固定的1883

格式参考

配置成功返回"CONNECT OK "

6、开启透传
指令:“AT+CIPSEND\\r\\n”
当模块返回">“时,此时进入透传模式,发送的所有数据都被视为是数据,当单独发送一包数据中含有”+++"时,模块会退出透传模式

通过以上步骤后,此时可以通过MQTT协议和服务器进行通信

六、核心代码

1、tencentyun.h

#ifndef _TENCENT_MQTT_H_
#define	_TENCENT_MQTT_H_

#include "stm32f10x.h"

#define CLIENT_ID "71248IVBSRESP8266"
#define USER_NAME	"71248IVBSRESP8266;12010126;MO8JD;1624767646"
#define PASSWORD	"9f37730219d6e3b9a121b845877cea4694ce7b74;hmacsha1"
#define KEEPALIVE_TIME 1200

#define PUB_TOPIC "$thing/up/property/71248IVBSR/ESP8266"
#define SUB_TOPIC "$thing/down/property/71248IVBSR/ESP8266"


#define MQTT_MAX_BUFF 512

#define MQTT_DISCONNECT 0
#define MQTT_CONNECT		1

extern u8 MQTT_ConnectStatus;

enum REQ_QoS

	REQ_QoS_0=0,
	REQ_QoS_1,
	REQ_QoS_2
;


u8 MQTT_Connect(char *client_id,char *user_name,char *password,u16 keep_alive);
void MQTT_Disconnect(void);
u8 MQTT_Subscribe_Topic(char *topic,int req_qos,int msgid);
u8 MQTT_Unsubscribe_Topic(char *topic,int msgid); 
u8 MQTT_Publish(char *pub_topic, unsigned char* payload);
u8 MQTT_Heart_Send(void);
u8 MQTT_GetConnectStatus(void);
void MQTT_AutoReconnect(void);

#endif


2、tencentyun.c

#include "tencent_mqtt.h"
#include "MQTTPacket.h"
#include "transport.h"
#include "string.h"
#include "usart.h"
#include "delay.h"
#include "led.h"
#include "ESP8266.h"

u8 mqtt_buf[MQTT_MAX_BUFF];
u16 rx_cnt=0;
u8 MQTT_ConnectStatus=MQTT_DISCONNECT;

//连接MQTT服务器
u8 MQTT_Connect(char *client_id,char *user_name,char *password,u16 keep_alive)

	MQTTPacket_connectData data = MQTTPacket_connectData_initializer;
	data.clientID.cstring =client_id;//客户端ID
	data.keepAliveInterval = keep_alive;//保活时间,单位为秒
	data.cleansession = 1;//清除会话
	data.username.cstring = user_name;//用户名
	data.password.cstring = password;//密码
	
	u16 send_len=MQTTSerialize_connect(mqtt_buf,MQTT_MAX_BUFF,&data);//序列化连接数据报
	transport_sendPacketBuffer(mqtt_buf,send_len);//向服务器发送连接数据报
	memset(mqtt_buf,0,MQTT_MAX_BUFF);
	if (MQTTPacket_read(mqtt_buf, MQTT_MAX_BUFF, transport_getdata) == CONNACK)
	
		unsigned char sessionPresent, connack_rc;

		if (MQTTDeserialize_connack(&sessionPresent, &connack_rc, mqtt_buf, MQTT_MAX_BUFF) != 1 || connack_rc != 0)//反序列化CONNACK报文
		
			return 1;//接收报文类型正确,但连接失败
		
	
	else return 1;//接收报文类型错误
	
	return 0;


//断开连接
void MQTT_Disconnect(void)

	u16 send_len=MQTTSerialize_disconnect(mqtt_buf, MQTT_MAX_BUFF);
	transport_sendPacketBuffer(mqtt_buf,send_len);//向服务器发送断开连接数据报
	memset(mqtt_buf,0,MQTT_MAX_BUFF);
	send_len=MQTTSerialize_disconnect(mqtt_buf, MQTT_MAX_BUFF);
	transport_sendPacketBuffer(mqtt_buf,send_len);//向服务器发送断开连接数据报
	memset(mqtt_buf,0,MQTT_MAX_BUFF);

//订阅主题
u8 MQTT_Subscribe_Topic(char *sub_topic,int req_qos,int msgid)

	MQTTString topicString = MQTTString_initializer;
	topicString.cstring = sub_topic;
	u16 send_len = MQTTSerialize_subscribe(mqtt_buf, MQTT_MAX_BUFF, 0, msgid, 1, &topicString, &req_qos);//序列化订阅数据报
	transport_sendPacketBuffer(mqtt_buf,send_len);//向服务器发送订阅数据报
	memset(mqtt_buf,0,MQTT_MAX_BUFF);
	if(MQTTPacket_read(mqtt_buf,MQTT_MAX_BUFF, transport_getdata) == SUBACK)//判断是否是SUBACK报文
	
		unsigned short submsgid;
		int subcount;
		int granted_qos;
		u8 rc=MQTTDeserialize_suback(&submsgid, 1, &subcount, &granted_qos, mqtt_buf, MQTT_MAX_BUFF);//反序列化SUBACK报文
		if(!rc || submsgid!=msgid || granted_qos==0x80)	return 1;接收报文类型正确,但订阅失败
	
	else return 1;//接收报文类型错误
	
	return 0;

//取消订阅主题
u8 MQTT_Unsubscribe_Topic(char *unsub_topic,int msgid)

	MQTTString topicString = MQTTString_initializer;
	topicString.cstring = unsub_topic;
	u16 send_len = MQTTSerialize_unsubscribe(mqtt_buf,MQTT_MAX_BUFF, 0, msgid,1, &topicString);//序列化取消订阅数据报
	transport_sendPacketBuffer(mqtt_buf,send_len);//向服务器发送取消订阅数据报
	memset(mqtt_buf,0,MQTT_MAX_BUFF);
	if(MQTTPacket_read(mqtt_buf,MQTT_MAX_BUFF, transport_getdata) == UNSUBACK)//判断是否是UNSUBACK报文
	
		unsigned short unsubmsgid;
		u8 rc=MQTTDeserialize_unsuback(&unsubmsgid,mqtt_buf,MQTT_MAX_BUFF);//反序列化UNSUBACK报文
		if(!rc || unsubmsgid!=msgid )	return 1;接收报文类型正确,但取消订阅失败
	
	else return 1;//接收报文类型错误
	return 0;


//发布主题
u8 MQTT_Publish(char *pub_topic, unsigned char* payload)

	MQTTString topicString = MQTTString_initializer;
	topicString.cstring = pub_topic;
	u16 send_len = MQTTSerialize_publish(mqtt_buf,MQTT_MAX_BUFF,0,0,0,0,topicString, payload, strlen((const char*)payload));//序列化发布数据报
	transport_sendPacketBuffer(mqtt_buf,send_len);//向服务器发送发布数据报
	memset(mqtt_buf,0,MQTT_MAX_BUFF);
	return 0;

//发送心跳包
u8 MQTT_Heart_Send(void)

	u16 send_len=MQTTSerialize_pingreq(mqtt_buf,MQTT_MAX_BUFF);
	transport_sendPacketBuffer(mqtt_buf,send_len);//向服务器发送PING数据报
	memset(mqtt_buf,0,MQTT_MAX_BUFF);
	if(MQTTPacket_read(mqtt_buf,MQTT_MAX_BUFF, transport_getdata) != PINGRESP)//判断是否是PINGRESP报文
	
		return 1;//接收报文类型错误
	

	return 0;

//获取MQTT服务器连接状态
u8 MQTT_GetConnectStatus(void)

	if(MQTT_Heart_Send()) return MQTT_DISCONNECT;
	return MQTT_CONNECT;

//自动重连
void MQTT_AutoReconnect(void)

	u8 con_cnt=0;
	ESP_Exit_Unvarnished();
	while(ESP_AutoReConnect_Server(WIFI_SSID,WIFI_PWD,SERVER_IP,SERVER_PORT) && con_cnt<=30)
	
		Delay_Ms(1000);
		printf("wifi or TCP disconnect,auto connectting...\\n");
		con_cnt++;
	
	if(con_cnt>30)	printf("wifi or TCP auto reconnect failure\\n");
	else printf("TCP server connect\\n");
	con_cnt=0;
	if(ESP_SendCmd("AT+CIPSEND\\r\\n",">",10,10)) printf("透传模式开启失败\\n");//开启透传
	while(MQTT_Connect(CLIENT_ID,USER_NAME,PASSWORD,KEEPALIVE_TIME) && con_cnt<=30)//重新连接
	
		Delay_Ms(1000);
		printf("MQTT server disconnect,auto connectting...\\n");
		con_cnt++;
	
	if(con_cnt>30)	printf("MQTT auto reconnect failure\\n");
	else printf("MQTT connect\\n");
	con_cnt=0;



3、main.c

#include "stm32f10x.h"
#include "delay.h"
#include "led.h"
#include "key.h"
#include "usart.h"
#include <string.h>
#include "timer.h"
#include "esp8266.h"
#include <stdlib.h>
#include "ds18b20.h"
#include "tencent_mqtt.h"
#include <stdio.h>
#include "usart.h"
#include "beep.h"

int main(void)

	u8 key=0;
	char Pub_buff[512];
	u16 cnt=0;
	Delay_Ms(1000);
	BEEP_Init();//蜂鸣器初始化
	LED_Init();//LED初始化
	KEY_Init();//按键初始化
	USARTx_Init(USART1,72,115200);//串口1初始化
	USARTx_Init(USART3,36,115200);//串口3初始化
	TIMERx_Init(TIM2,72,2000*10);//设置分频系数为72,定时10ms.分频系数7200-->100us,72-->1us
	TIMERx_Init(TIM4,72,2000*10);//设置分频系数为72,定时10ms.分频系数7200-->100us,72-->1us
	DS18B20_Init();//DS18B20初始化
	ESP_UnvarnishedMode_Init(WIFI_SSID,WIFI_PWD,SERVER_IP,SERVER_PORT);//连接TCP服务器并进入透传模式
	if(MQTT_Connect(CLIENT_ID,USER_NAME,PASSWORD,KEEPALIVE_TIME))//登录MQTT服务器
		printf("connect failure\\n");
	else 
	
		printf("connect success\\n");	
		if(MQTT_Subscribe_Topic(SUB_TOPIC,REQ_QoS_0,1))//订阅
		
			printf("subscribe failure\\n");
		
		else printf("subscribe success\\n");
	
	
	while(1)
	
		if(USART3_RX_FLAG)
		
			for(u16 i=0;i<USART3_RX_CNT;i++)
			
				if(USART3_RX_BUFF[i]=='\\0')	USART3_RX_BUFF[i]='0';
			
			USART3_RX_BUFF[USART3_RX_CNT]='\\0';
			printf("USART3_RX=%s\\n",USART3_RX_BUFF);
			if(strstr(USART3_RX_BUFF,"\\"LED_swi\\":1"))	LED1=0;
			if(strstr(USART3_RX_BUFF,"\\"LED_swi\\":0"))	LED1=1;
			USART3_RX_FLAG=0;
			USART3_RX_CNT=0;
		
		if(USART1_RX_FLAG)
		
			USART1_RX_FLAG=0;
			USART1_RX_BUFF[USART1_RX_CNT]='\\0';
			USARTx_SendString(USART3,USART1_RX_BUFF);
			USART1_RX_CNT=0;
		
		Delay_Ms(10);
        cnt++;
        if(cnt%300==0)//上传温度数据
        
			snprintf(Pub_buff,sizeof(Pub_buff),"\\"clientToken\\":\\"1234\\",\\"method\\":\\"report\\",\\"params\\":\\"Temperature\\": %0.2f",DS18B20_Read_Temp()*0.0625);
			MQTT_Publish(PUB_TOPIC,(unsigned char*)Pub_buff);

        
		if(cnt==3000)
		
			cnt=0;
			if(MQTT_GetConnectStatus()==MQTT_DISCONNECT)//未连接MQTT服务器
			
				printf("MQTT Disconnect\\n");
				MQTT_AutoReconnect();//自动重连
				if(MQTT_Subscribe_Topic(SUB_TOPIC,REQ_QoS_0,1))//重新订阅
				
					printf("subscribe failure\\n");
				
				else printf("subscribe success\\n");
				
			
			else printf("MQTT Connect\\n");
		

		key=KEY_GetVal();
		if(key==2)//订阅
		
			if(MQTT_Subscribe_Topic(SUB_TOPIC,REQ_QoS_0,1))
			
				以上是关于STM32+ESP8266(ESP-12F)物联网温度计-腾讯云物联网的主要内容,如果未能解决你的问题,请参考以下文章

STM32+ESP8266(ESP-12F)物联网温度计-腾讯云物联网

STM32+ESP8266(ESP-12F)物联网温度计-腾讯云物联网

STM32+ESP8266(ESP-12F)实现在线OTA升级(腾讯云物联网)

STM32+ESP8266(ESP-12F)实现在线OTA升级(腾讯云物联网)

STM32+ESP8266(ESP-12F)实现在线OTA升级(腾讯云物联网)

STM32+ESP8266移植paho MQTT协议连接阿里云物联网平台