一、驱动依据:
根据我之前的AT指令上云的办法编写这个驱动,使用起来简单粗暴,只需要把串口配置为接收模式,接收中断。
#新版Onenet云平台使用(ESP8266 AT指令上报数据以及公网MQTT服务器连接测试)_esp8266接入onenet,mqtt-CSDN博客https://blog.csdn.net/byhyf83862547/article/details/137613781大家如果要用我这个驱动,注意更改我在注释部分说的东西,不要把数据信息传到我的设备上面来了,这样自己是看不到结果的。
二、硬件:
STM32F103C6T6(只要是STM32系列标准库,改动就不大)
正点原子ESP8266(MQTT固件)
三、驱动程序:
Esp8266_Mqtt.c
#include "Esp8266_Mqtt.h"
#include "usart.h"
#include "string.h"
#include "delay.h"
#include "stdio.h"
/**
* @author GFS
* @time 2024年5月14日
* @mqtt 连接手机热点
* @version 1.0
*/
/**
* @author GFS
* @time 2024年5月19日
* @mqtt 至新版onenet数据传输
* @version 2.0
* @注: 1.只可以传输整形数据
* 2.单个数据传输(每次传输时指定主题(即属性,旧版ONENET称为数据流)和上传的数据)
* 3.修改宏定义的信息和void PublishOnenet(char *topic,int data)中的信息
* 4.
*/
/**************************************************************宏定义及全局变量*************************************************************************/
/**
* @"Redmi K40 Gaming" 手机热点名字
* @"87654321" 热点密码
* @note 注意手机热点设置频段为2.4GHz
*/
#define WifiInfo_AT "AT+CWJAP=\"Redmi K40 Gaming\",\"87654321\"\r\n"
/**
* @inf 各类参数
* @param 1.AT+MQTTUSERCFG=0,1,"设备ID","产品ID","得到的token",0,0,"" //验证信息
* @param 2.AT+MQTTCONN=0,"mqtts.heclouds.com",1883,1 //连接新版onenet
* @param 3.AT+MQTTSUB=0,"$sys/产品ID/设备ID/thing/property/post/reply",1 //订阅主题
* @param 4.AT+MQTTPUB=0,"$sys/产品ID/设备ID/thing/property/post","{\"id\":\"123\"\,\"params\":{\"属性标识符\":{\"value\":上传的数据}}}",0,0 //发布主题
* @JSON 第四条指令是上传数据的关键,它的信息是一个JSON格式数据
本例程中它是如下格式:
{
"id": "123",
"params": {
"shuifei":{
"value": 30
}
}
}
如果我们npc1设备下还有一个dianfei属性,我们既上传水费也上传电费,则JSON格式数据可以是如下:
{
"id": "123",
"params": {
"shuifei":{
"value": 30
},
"dianfei":{
"value": 40
}
}
}
*/
#define AT_MqttUserCfg "AT+MQTTUSERCFG=0,1,\"npc1\",\"45015g8Bam\",\"version=2018-10-31&res=products%2F45015g8Bam%2Fdevices%2Fnpc1&et=4111053161&method=md5&sign=4vpLs%2FP6%2BV6n4VfLCaffkQ%3D%3D\",0,0,\"\"\r\n"
#define AT_MqttConnect "AT+MQTTCONN=0,\"mqtts.heclouds.com\",1883,1\r\n"
#define AT_MqttSubscribe "AT+MQTTSUB=0,\"$sys/45015g8Bam/npc1/thing/property/post/reply\",1\r\n"
//#define AT_MqttPublish "AT+MQTTPUB=0,\"$sys/45015g8Bam/npc1/thing/property/post\",\"{\\\"id\\\":\\\"123\\\"\\,\\\"params\\\":{\\\"shuifei\\\":{\\\"value\\\":13}}}\",0,0\r\n"
//ESP8266连接的串口
#define EspUsart USART1
//延时
#define wait_echo delay_ms(1000)
//At指令标志位
uint8_t AtCmd_Flag=0;
//At指令响应接收字符串
char AtEcoh_Buff[150]={0};
uint8_t AEB_Index=0;
//避免死循环,跳出计时
uint8_t break_time=0;
//发布主题字符组
char data_publish[150]={0};
/************************************************串口*******************************************************************************/
/**
* @brief 指定串口发送单个字符
* @param *usart: 可以是 (&USART1,&USART2...).
* @param data: 要发送的单个字符
* @retval None
*/
void USART_Send_Data(USART_TypeDef *usart,unsigned char data)
{
while(USART_GetFlagStatus(usart,USART_FLAG_TC)!=1); //等待传输完成
USART_SendData(usart,data);
}
/**
* @brief 指定串口发送字符串
* @param *usart: 可以是 (&USART1,&USART2...).
* @param String: 要发送的字符串
* @retval None
*/
void USART_Send_String(USART_TypeDef *usart,unsigned char *String)
{
uint16_t len,j;
len=strlen(String);
for(j=0;j<len;j++)
{
USART_Send_Data(usart,*String++);
}
}
/**
* @brief 串口1中断服务函数
* @param None
* @retval None
*/
void USART1_IRQHandler(void)
{
if(USART_GetITStatus(USART1,USART_IT_RXNE)==SET)//接收中断标志位拉高
{
//处于接收At指令阶段
if(AtCmd_Flag==1)
{
if(AEB_Index<150)
{
AtEcoh_Buff[AEB_Index]=USART1->DR;
AEB_Index+=1;
}
else
AEB_Index=0;
}
//清除标志位
USART_ClearFlag(USART1, USART_FLAG_RXNE);
}
}
/**********************************************MQTT***************************************************/
/**
* @brief AT指令响应字符串清空
* @param NONE
* @retval NONE
*/
void EspAtEcho_Clear(void)
{
memset(AtEcoh_Buff,0,sizeof(AtEcoh_Buff));
AEB_Index=0;
}
/**
* @brief AT指令发送与响应
* @param AtCmd: 要发送AT指令
* @param Ecoh: 想要收到的回应
* @retval 1成功响应,0失败
*/
uint8_t EspAtCmd(unsigned char *AtCmd,unsigned char *Ecoh)
{
//At指令标志位置1
AtCmd_Flag=1;
//通过串口向ESP8266发送AT指令
USART_Send_String(EspUsart,AtCmd);
//查找响应信息
while(break_time<4)
{
wait_echo;
break_time++;
if((strstr((const char *)AtEcoh_Buff,(const char *)Ecoh)!=NULL))
break;
}
//At指令结束
AtCmd_Flag=0;
//清空响应
EspAtEcho_Clear();
//超时跳出,响应失败
if(break_time>3)
{
break_time=0;
return 0;
}
//成功响应
break_time=0;
return 1;
}
/**
* @brief AT指令初始化WIFI模块(连接指定网络)
* @param NONE
* @retval NONE
*/
void Esp8266Init(void)
{
//初始化串口(此处更改为串口初始化函数)
//uart_init(115200);
//开始初始化
while(EspAtCmd("AT\r\n","OK")!=1)
wait_echo;
while(EspAtCmd("AT+CWMODE=1\r\n","OK")!=1)
wait_echo;
while(EspAtCmd("AT+CWDHCP=1,1\r\n","OK")!=1)
wait_echo;
while(EspAtCmd(WifiInfo_AT,"GOT IP")!=1)
wait_echo;
}
/**
* @brief 通过ESP8266订阅主题
* @param NONE
* @retval NONE
* @物联网平台 Onenet
*/
void SubscribeOnenet(void)
{
// while(EspAtCmd(AT_MqttUserCfg,"OK")!=1)
USART_Send_String(EspUsart,AT_MqttUserCfg);
wait_echo;
USART_Send_String(EspUsart,AT_MqttConnect);
// while(EspAtCmd(AT_MqttConnect,"OK")!=1)
wait_echo;
wait_echo;
wait_echo;
wait_echo;
USART_Send_String(EspUsart,AT_MqttSubscribe);
// while(EspAtCmd(AT_MqttSubscribe,"OK")!=1)
wait_echo;
wait_echo;
}
/**
* @brief 通过ESP8266发布主题
* @param topic 主题(属性,旧版称为数据流)
* @param data 上传的数据
* @retval NONE
* @物联网平台 Onenet
*/
void PublishOnenet(char *topic,int data)
{
memset(data_publish,0,sizeof(data_publish));
sprintf(data_publish,"AT+MQTTPUB=0,\"$sys/45015g8Bam/npc1/thing/property/post\",\"{\\\"id\\\":\\\"123\\\"\\,\\\"params\\\":{\\\"%s\\\":{\\\"value\\\":%d}}}\",0,0\r\n",topic,data);
USART_Send_String(EspUsart,(unsigned char*)data_publish);
}
Esp8266_Mqtt.h
#ifndef _ESP8266_MQTT_H
#define _ESP8266_MQTT_H
#include "sys.h"
void USART_Send_Data(USART_TypeDef *usart,unsigned char data);
void USART_Send_String(USART_TypeDef *usart,unsigned char *String);
void EspAtEcho_Clear(void);
uint8_t EspAtCmd(unsigned char *AtCmd,unsigned char *Ecoh);
void Esp8266Init(void);
void SubscribeOnenet(void);
void PublishOnenet(char *topic,int data);
#endif
main.c
#include "sys.h"
#include "usart.h"
#include "usart2.h"
#include "delay.h"
#include "Esp8266_Mqtt.h"
void Led_Init(void)
{
GPIO_InitTypeDef GPIO_InitStruct;
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOC,ENABLE);
GPIO_InitStruct.GPIO_Mode=GPIO_Mode_Out_PP;
GPIO_InitStruct.GPIO_Pin=GPIO_Pin_13;
GPIO_InitStruct.GPIO_Speed=GPIO_Speed_50MHz;
GPIO_Init(GPIOC,&GPIO_InitStruct);
GPIO_ResetBits(GPIOC,GPIO_Pin_13);
}
int sf=12;
int df=25;
int main(void)
{
NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2); //设置NVIC中断分组2:2位抢占优先级,2位响应优先级
uart2_init(115200); //串口初始化 波特率为9600
uart_init(115200);
delay_init(); //延时函数初始化
Led_Init();
Esp8266Init();
SubscribeOnenet();
while(1)
{
PublishOnenet("shuifei",sf);
delay_ms(1000);
delay_ms(1000);
sf++;
PublishOnenet("dianfei",df);
delay_ms(1000);
delay_ms(1000);
df++;
}
}
四、我的实物