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协议连接阿里云物联网平台