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升级(腾讯云物联网)