网站网上商城制作,北京企业模板建站,百度小程序优化排名,深圳苏州企业网站建设服务文章目录 引言一、STM32连接阿里云物联网平台思路二、ESP8266烧录固件三、使用AT指令连接阿里云物联网平台四、STM32环形串口缓冲区驱动程序五、STM32连接阿里云驱动程序 引言
连续写了两篇关于阿里云连接的文章#xff0c;都是使用Arduino ESP8266 Arduino ESP32的方式… 文章目录 引言一、STM32连接阿里云物联网平台思路二、ESP8266烧录固件三、使用AT指令连接阿里云物联网平台四、STM32环形串口缓冲区驱动程序五、STM32连接阿里云驱动程序 引言
连续写了两篇关于阿里云连接的文章都是使用Arduino ESP8266 Arduino ESP32的方式 1、Arduino ESP8266ESP32使用AliyunIoTSDK.h连接阿里云物联网平台 2、使用ArduinoMqttClient库连接阿里云并实现发送接收数据ESP8266
但是使用Arduino的方式处理阿里云的数据在简单的电子小制作、毕业设计完全可以胜任但是Arduino的核心库都是对底层进行二次封装运行效率难免会低一些。ESP8266与ESP32作为主控的MCU功能有限在这种情况下就会想到使用STM32搭载一个可以联网的芯片来做数据物联网的开发了。 我在企业开发项目中接触过新能源汽车充电桩核心是使用STM32F103VET6进行主控它通过搭载一个4G模块来对云端数据进行处理。设备上线时后台有上线的提示管理员可用户都可以查看到充电桩的实时状态如下图所示管理员坐在办公室便可以查看到有两个慢充桩处于空闲状态有一个充电桩已连接车辆但是并没有开始充电我们就可以猜测出用户可能刚刚到达已将插枪连接车辆正在进行扫码的操作。 平台更会报一些简单的故障如急停故障充电桩安装的环境多种多样有时会有小朋友误触到急停故障导致充电桩报故障不能充电这时用户打电话给运维的客服便可以在运维客服的提示下把急停按键复原充电桩便可以正常使用。 通过物联网技术来对新能源汽车充电桩进行控制大大的减轻的运营的成本在其他行业如加油站无人值守的自动洗车机、学校教学楼的自动贩卖机等等都是物联网控制的一个范例如今物联网控制技术更是影响着我们生活的方方面面。
文章使用基础型STM32F1作为主控芯片搭载ESP8266模块使用环形串口缓冲区算法连接阿里云平台实现数据的订阅和发布。文章有一点点的深度我尽量把每一个细节每一个步都骤掰开来嚼碎去详细说明。 有很多例程在数据收发这一块都使用数组进行数据的接收对付一些简单的物联网开发完全是没有问题的而环形串口缓冲区算法是在大规模数据接收时使用的在这么简单的物联网数据收发中使用难免会影响效率。 是的在这么简单的物联网数据的收发我还使用环形串口缓冲区影响一定的运行的效率是一定。但是长期做开发的一定要留有有方便后期升级维护的一个思维一些升级接口需要多预留一些产品都不是一次做出来的是一代一代逐渐完善逐渐更新换代的。
一、STM32连接阿里云物联网平台思路
连接思路其实很简单只要两步就好了 1、烧录MQTT的固件 2、STM32使能串口通过AT指令连接阿里云物联网平台
我使用的是ESP8266作为联网设备连接阿里云物联网平台之前我使用Arduino的方式连接阿里云平台也是同样的原理但是Arduino将一些底层的函数进行了封装我们只需要学会使用Arduino提供的一些库便可以连接阿里云物联网平台进行数据交换。 而STM32则没有相关的库我们需要烧录好MQTT的固件通过电脑串口助手先连接成功阿里云物联网平台测试好订阅和发布的功能后连接我们STM32串口进行简单的串口数据收发。
二、ESP8266烧录固件
连接物联网云平台之前先需要烧录相关固件固件地址如下 安信可固件汇总 我选择第4个固件固件的下载地址附有官方的使用说明。 因为技术更新迭代的速度非常快可能我的这一篇文章发布几个月或半年后固件便开始更新但都是换汤不换药掌握了连接的原理我们也可以自行查看官方的文档来进行连接此篇文章可以作为非常重要的参考使用。 下载完成后便可以烧录固件烧录固件的软件可以通过官网下载我这里也提供一个网盘下载连接 链接https://pan.baidu.com/s/1H96ZbeG_ogslrJUz2Y162w 提取码wslw 软件打开后安装提示很容易就可以将固件烧录进去下图是我烧录成功的截图界面
三、使用AT指令连接阿里云物联网平台
固件烧录成功之后首先需要使用电脑的串口助手软件通过简单的AT指令连接WiFi连接阿里云然后完成订阅和发布数据确认好AT指令代码没有问题后我们才把相关的AT指令封装起来写进程序中连接的AT指令只需要熟悉常用的几个即可。
指令功能AT测试ATRST重启ATCWMODE1设置为无线终端模式可以连接WiFiATCWJAP“wifi”,“passwd”连接热点ATCWSTATE?查询WiFi连接讲解状态ATMQTTUSERCFG0,1,“clientId”,“username”,“password”,0,0,“”设置MQTT连接参数ATMQTTCONN0,“Broker Address”,1883,1连接阿里云ATMQTTCONN?查询MQTT连接状态ATMQTTSUB0,“topic”,0订阅主题ATMQTTPUB0,“topic”,“msg”发布主题
AT指令按照如下通过串口助手发送到ESP8266即可完成阿里云的连接 1判断ESP8266是否存在 使用指令AT\r\n 串口回复OK 备注使用串口助手和STM32发送指令的时候结尾加上\r\n表示指令结束 2设置ESP8266为接入点模式 使用指令ATCWMODE1\r\n 串口回复OK
3查询WiFi是否连接成功 使用指令ATCWSTATE? 串口回复
CWSTATE:2CMCC-H3qz //备注CMCC-H3qz是我的WiFi名OK4如果没有连接WiF则连接WiFi 使用指令ATCWJAP“CMCC-H3qz”,“7xf47uxf”\r\n 备注CMCC-H3qz是我的WiFi名7xf47uxf是我的WiFi密码
串口回复:
ATCWJAPCMCC-H3qz7xf47uxf
WIFI DISCONNECT
WIFI CONNECTED
WIFI GOT IPOK
5设置MQTT参数 使用指令 ATMQTTUSERCFG0,1,“clientId”,“username”,“password”,0,0,“”\r\n 示例 ATMQTTUSERCFG0,1,k0efkfcSwlt.Device_Demo|securemode2\,signmethodhmacsha256\,timestamp1705149361131|,Device_Demok0efkfcSwlt,ea343ac1d6a4eec7b057bcab39a2ffdf88abc8b810ec0dc7ca3de91a56292ff9,0,0,\r\n 备注 1、指令中遇到“,”字符时使用“\”隔开避免报错。 2、clientIdusernamepassword这些数据从阿里云物联网平台获取 串口回复
ATMQTTUSERCFG01k0efkfcSwlt.Device_Demo|securemode2\signmethodhmacsha256\timestamp1705149361131|Device_Demok0efkfcSwltea343ac1d6a4eec7b057bcab39a2ffdf88abc8b810ec0dc7ca3de91a56292ff900OK
6连接阿里云 使用指令ATMQTTCONN0,“Broker Address”,1883,1\r\n 示例 ATMQTTCONN0,k0efkfcSwlt.iot-as-mqtt.cn-shanghai.aliyuncs.com,1883,1\r\n 备注 Broker Address为MQTT域名阿里云物联网平台开发者文档有详细的解释我在以前的文章也对这方面进行了详细的说明大家可以尝试一下使用MQTT.fx连接阿里云平台就能明白MQTT域名的作用了。 附上这部分云文档的地址 使用MQTT.fx接入物联网平台 串口回复
ATMQTTCONN0k0efkfcSwlt.iot-as-mqtt.cn-shanghai.aliyuncs.com18831
MQTTCONNECTED:01k0efkfcSwlt.iot-as-mqtt.cn-shanghai.aliyuncs.com18831OK
这时我们登陆阿里云物联网平台可以看到设备已成功连接阿里云物联网平台。 7发布数据 使用指令ATMQTTPUB0,“topic”,“msg”\r\n 示例 ATMQTTPUB0,/sys/k0efkfcSwlt/Device_Demo/thing/event/property/post,{\params\: {\temperature\: 10.5}\,\version\: \1.0\},0,0\r\n 备注 1、topic从阿里云平台获取 2、msg有一定的格式在阿里云平台的开发者文档里也有详细的说明附上文档连接 阿里云物联网平台设备上报属性 示例中上报的属性为温度10.5。 3、使用这个指令遇到 “ ”的时候学会使用专业字符“\”。
串口回复
ATMQTTPUB0/sys/k0efkfcSwlt/Device_Demo/thing/event/property/post{\params\: {\temperature\: 10.5}\\version\: \1.0\}00OK
我们查看阿里云物联网平台物模型数据可以看到阿里云已成功接收数据。
8订阅数据 使用指令ATMQTTSUB0,“topic”,0\r\n 示例ATMQTTSUB0,/sys/k0efkfcSwlt/Device_Demo/thing/service/property/set,0 备注topic从阿里云物联网平台获取 串口回复
ATMQTTSUB0/sys/k0efkfcSwlt/Device_Demo/thing/service/property/set0OK
这时我们通过在线调试测试订阅数据是否成功。 我们在阿里云平台自定义了一盏LED灯通过在线调试的方式发送开启和关闭的命令如果订阅没有问题的话可以看到如下串口回复
MQTTSUBRECV:0/sys/k0efkfcSwlt/Device_Demo/thing/service/property/set100{method:thing.service.property.setid:2001671834params:{LEDSwitch:0}version:1.0.0}
MQTTSUBRECV:0/sys/k0efkfcSwlt/Device_Demo/thing/service/property/set100{method:thing.service.property.setid:2046606498params:{LEDSwitch:1}version:1.0.0}可以看到json数据里LEDSwitch的变换这时我们就可以在单片机上处理这条指令来实现LED的亮灭实现阿里云物联网平台控制led。
如果顺利到这一步那么恭喜你现在距离成功仅剩一半的距离了接下来只需将AT指令封装到STM32的代码中进行简单的STM32串口操作就可以实现使用STM32连接阿里云的操作了。
四、STM32环形串口缓冲区驱动程序
环形串口缓冲区的原理可以查看这篇文章环形串口缓冲区
明白了环形串口缓冲区的原理在STM32开发中先写好串口的驱动程序然后再编写环形串口缓冲区程序下面是驱动程序我都有注释学过STM32的都能看得懂。
usart.c
/********************************************************************************* file usart.c* author 小途* version V1.0* date 2022-2-21* brief STM32F1的串口初始化设置******************************************************************************* attention* 串口2配置环形串口缓冲区********************************************************************************/#include usart.h#define UART_RX_MAX 255 //数组最大值//环形缓冲区结构体
typedef struct
{uint8_t head_count; //头计数uint8_t tail_count; //尾计数uint8_t buf[UART_RX_MAX]; //缓冲区数组
}UART_S;UART_S uart;//定义串口缓冲区结构体变量//串口环形缓冲区初始化
void uart_Buffer_Init(void)
{int i;uart.head_count 0;uart.tail_count 0;for(i0; iUART_RX_MAX; i){uart.buf[i] 0x00;}
}//往缓冲器里放数据
void uart_buf_put(uint8_t ch)
{uart.buf[uart.head_count] ch;if(uart.head_count UART_RX_MAX){uart.head_count 0;}
}//判断缓冲区是否有数据
int fifo_is_empty(void)
{if(uart.head_count ! uart.tail_count)//判断如果头不等于尾{return 0;//有数据}else return 1;//无数据
}//从缓冲区取数据
int uart_buf_get(uint8_t *ch)
{if(fifo_is_empty() 0)//如果有数据{*ch uart.buf[uart.tail_count];//取数据if(uart.tail_count UART_RX_MAX){uart.tail_count 0;} return 1;//返回成功}else return 0;//返回失败
}//读数据将数据通过串口发送出去
void debug_read(void)
{uint8_t ch;/*如果有数据就一直取直到取完为至*/while(!fifo_is_empty()){if(uart_buf_get(ch)){putchar(ch);}}
}/*** brief 配置嵌套向量中断控制器NVIC* param 无* retval 无*/
void NVIC_Configuration(void)
{NVIC_InitTypeDef NVIC_InitStructure;/* 嵌套向量中断控制器组选择 */NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);/* 配置USART为中断源 */NVIC_InitStructure.NVIC_IRQChannel DEBUG_USART_IRQ;/* 抢断优先级*/NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority 1;/* 子优先级 */NVIC_InitStructure.NVIC_IRQChannelSubPriority 2;/* 使能中断 */NVIC_InitStructure.NVIC_IRQChannelCmd ENABLE;/* 初始化配置NVIC */NVIC_Init(NVIC_InitStructure);
}//对串口2配置嵌套向量中断控制器NVIC
void NVIC_USART2_Configuration(void)
{NVIC_InitTypeDef NVIC_InitStructure;/* 嵌套向量中断控制器组选择 */NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);/* 配置USART为中断源 */NVIC_InitStructure.NVIC_IRQChannel DEBUG_USART2_IRQ;/* 抢断优先级*/NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority 1;/* 子优先级 */NVIC_InitStructure.NVIC_IRQChannelSubPriority 1;/* 使能中断 */NVIC_InitStructure.NVIC_IRQChannelCmd ENABLE;/* 初始化配置NVIC */NVIC_Init(NVIC_InitStructure);
}/*** brief USART GPIO 配置,工作参数配置* param 无* retval 无*/
void USART_Config(void)
{GPIO_InitTypeDef GPIO_InitStructure;USART_InitTypeDef USART_InitStructure;// 打开串口GPIO的时钟DEBUG_USART_GPIO_APBxClkCmd(DEBUG_USART_GPIO_CLK, ENABLE);// 打开串口外设的时钟DEBUG_USART_APBxClkCmd(DEBUG_USART_CLK, ENABLE);// 将USART Tx的GPIO配置为推挽复用模式GPIO_InitStructure.GPIO_Pin DEBUG_USART_TX_GPIO_PIN;GPIO_InitStructure.GPIO_Mode GPIO_Mode_AF_PP;GPIO_InitStructure.GPIO_Speed GPIO_Speed_50MHz;GPIO_Init(DEBUG_USART_TX_GPIO_PORT, GPIO_InitStructure);// 将USART Rx的GPIO配置为浮空输入模式GPIO_InitStructure.GPIO_Pin DEBUG_USART_RX_GPIO_PIN;GPIO_InitStructure.GPIO_Mode GPIO_Mode_IN_FLOATING;GPIO_Init(DEBUG_USART_RX_GPIO_PORT, GPIO_InitStructure);// 配置串口的工作参数// 配置波特率USART_InitStructure.USART_BaudRate DEBUG_USART_BAUDRATE;// 配置 针数据字长USART_InitStructure.USART_WordLength USART_WordLength_8b;// 配置停止位USART_InitStructure.USART_StopBits USART_StopBits_1;// 配置校验位USART_InitStructure.USART_Parity USART_Parity_No ;// 配置硬件流控制USART_InitStructure.USART_HardwareFlowControl USART_HardwareFlowControl_None;// 配置工作模式收发一起USART_InitStructure.USART_Mode USART_Mode_Rx | USART_Mode_Tx;// 完成串口的初始化配置USART_Init(DEBUG_USARTx, USART_InitStructure);// 串口中断优先级配置//NVIC_Configuration();// 使能串口接收中断//USART_ITConfig(DEBUG_USARTx, USART_IT_RXNE, ENABLE); // 使能串口USART_Cmd(DEBUG_USARTx, ENABLE);
}/*** brief USART2 GPIO 配置,工作参数配置配置环形串口缓冲区* param 无* retval 无*/
void USART2_Config(void)
{//在串口2配置环形串口缓冲区//初始化环形串口缓冲区uart_Buffer_Init();GPIO_InitTypeDef GPIO_InitStructure;USART_InitTypeDef USART_InitStructure;// 打开串口GPIO的时钟DEBUG_USART2_GPIO_APBxClkCmd(DEBUG_USART2_GPIO_CLK, ENABLE);// 打开串口外设的时钟DEBUG_USART2_APBxClkCmd(DEBUG_USART2_CLK, ENABLE);// 将USART Tx的GPIO配置为推挽复用模式GPIO_InitStructure.GPIO_Pin DEBUG_USART2_TX_GPIO_PIN;GPIO_InitStructure.GPIO_Mode GPIO_Mode_AF_PP;GPIO_InitStructure.GPIO_Speed GPIO_Speed_50MHz;GPIO_Init(DEBUG_USART2_TX_GPIO_PORT, GPIO_InitStructure);// 将USART Rx的GPIO配置为浮空输入模式GPIO_InitStructure.GPIO_Pin DEBUG_USART2_RX_GPIO_PIN;GPIO_InitStructure.GPIO_Mode GPIO_Mode_IN_FLOATING;GPIO_Init(DEBUG_USART2_RX_GPIO_PORT, GPIO_InitStructure);// 配置串口的工作参数// 配置波特率USART_InitStructure.USART_BaudRate DEBUG_USART2_BAUDRATE;// 配置 针数据字长USART_InitStructure.USART_WordLength USART_WordLength_8b;// 配置停止位USART_InitStructure.USART_StopBits USART_StopBits_1;// 配置校验位USART_InitStructure.USART_Parity USART_Parity_No ;// 配置硬件流控制USART_InitStructure.USART_HardwareFlowControl USART_HardwareFlowControl_None;// 配置工作模式收发一起USART_InitStructure.USART_Mode USART_Mode_Rx | USART_Mode_Tx;// 完成串口的初始化配置USART_Init(DEBUG_USART2, USART_InitStructure); //串口2中断优先级配置NVIC_USART2_Configuration();//使能串口2接收中断USART_ITConfig(DEBUG_USART2, USART_IT_RXNE, ENABLE);// 使能串口//USART_Cmd(DEBUG_USART2, ENABLE);
}/***************** 发送一个字符 **********************/
void Usart_SendByte( USART_TypeDef * pUSARTx, uint8_t ch)
{/* 发送一个字节数据到USART */USART_SendData(pUSARTx,ch);/* 等待发送数据寄存器为空 */while (USART_GetFlagStatus(pUSARTx, USART_FLAG_TXE) RESET);
}/***************** 发送字符串 **********************/
void Usart_SendString( USART_TypeDef * pUSARTx, char *str)
{unsigned int k0;do {Usart_SendByte( pUSARTx, *(str k) );k;} while(*(str k)!\0);/* 等待发送完成 */while(USART_GetFlagStatus(pUSARTx,USART_FLAG_TC)RESET);
}//发送整形数据字符串发送长字符串
void Usart_SendIntString( USART_TypeDef * pUSARTx, int *str)
{int k0;do {Usart_SendByte( pUSARTx, *(str k) );k;} while(*(str k)!\0);/* 等待发送完成 */while(USART_GetFlagStatus(pUSARTx,USART_FLAG_TC)RESET);
}//重定向c库函数printf到串口重定向后可使用printf函数默认使用串口1
int fputc(int ch, FILE *f)
{/* 发送一个字节数据到串口 */USART_SendData(DEBUG_USART1, (uint8_t) ch);/* 等待发送完毕 */while (USART_GetFlagStatus(DEBUG_USART1, USART_FLAG_TXE) RESET); return (ch);
}//重定向c库函数scanf到串口重写向后可使用scanf、getchar等函数默认使用串口1
int fgetc(FILE *f)
{/* 等待串口输入数据 */while (USART_GetFlagStatus(DEBUG_USART1, USART_FLAG_RXNE) RESET);return (int)USART_ReceiveData(DEBUG_USART1);
}
usart.h
#ifndef __USART_H
#define __USART_H#include stm32f10x.h
#include stdio.h/** 串口宏定义不同的串口挂载的总线不一样移植时需要修改这几个宏*/// 串口1-USART1
#define DEBUG_USARTx USART1
#define DEBUG_USART_CLK RCC_APB2Periph_USART1
#define DEBUG_USART_APBxClkCmd RCC_APB2PeriphClockCmd
#define DEBUG_USART_BAUDRATE 115200// USART GPIO 引脚宏定义
#define DEBUG_USART_GPIO_CLK (RCC_APB2Periph_GPIOA)
#define DEBUG_USART_GPIO_APBxClkCmd RCC_APB2PeriphClockCmd#define DEBUG_USART_TX_GPIO_PORT GPIOA
#define DEBUG_USART_TX_GPIO_PIN GPIO_Pin_9
#define DEBUG_USART_RX_GPIO_PORT GPIOA
#define DEBUG_USART_RX_GPIO_PIN GPIO_Pin_10#define DEBUG_USART_IRQ USART1_IRQn
#define DEBUG_USART_IRQHandler USART1_IRQHandler//------------------------------------------------------------------------// 串口1-USART1
#define DEBUG_USART1 USART1
#define DEBUG_USART1_CLK RCC_APB2Periph_USART1
#define DEBUG_USART1_APBxClkCmd RCC_APB2PeriphClockCmd
#define DEBUG_USART1_BAUDRATE 115200// USART GPIO 引脚宏定义
#define DEBUG_USART1_GPIO_CLK (RCC_APB2Periph_GPIOA)
#define DEBUG_USART1_GPIO_APBxClkCmd RCC_APB2PeriphClockCmd#define DEBUG_USART1_TX_GPIO_PORT GPIOA
#define DEBUG_USART1_TX_GPIO_PIN GPIO_Pin_9
#define DEBUG_USART1_RX_GPIO_PORT GPIOA
#define DEBUG_USART1_RX_GPIO_PIN GPIO_Pin_10#define DEBUG_USART1_IRQ USART1_IRQn
#define DEBUG_USART1_IRQHandler USART1_IRQHandler//------------------------------------------------------------------------// 串口2-USART2
#define DEBUG_USART2 USART2
#define DEBUG_USART2_CLK RCC_APB1Periph_USART2
#define DEBUG_USART2_APBxClkCmd RCC_APB1PeriphClockCmd
#define DEBUG_USART2_BAUDRATE 115200// USART GPIO 引脚宏定义
#define DEBUG_USART2_GPIO_CLK (RCC_APB2Periph_GPIOA)
#define DEBUG_USART2_GPIO_APBxClkCmd RCC_APB2PeriphClockCmd#define DEBUG_USART2_TX_GPIO_PORT GPIOA
#define DEBUG_USART2_TX_GPIO_PIN GPIO_Pin_2
#define DEBUG_USART2_RX_GPIO_PORT GPIOA
#define DEBUG_USART2_RX_GPIO_PIN GPIO_Pin_3#define DEBUG_USART2_IRQ USART2_IRQn
#define DEBUG_USART2_IRQHandler USART2_IRQHandler//使能串口2
#define USART2_ON USART_Cmd(DEBUG_USART2, ENABLE);
//失能串口2
#define USART2_OFF USART_Cmd(DEBUG_USART2, DISABLE);//环形串口缓冲区相关功能函数
void uart_buf_put(uint8_t ch);
void debug_read(void);
int fifo_is_empty(void);
int uart_buf_get(uint8_t *ch);//STM32串口相关功能函数
void USART_Config(void);
void USART2_Config(void);
void Usart_SendByte( USART_TypeDef * pUSARTx, uint8_t ch);
void Usart_SendString( USART_TypeDef * pUSARTx, char *str);
void Usart_SendIntString( USART_TypeDef * pUSARTx, int *str);#endif
stm32f10x_it.c
//串口2中断服务函数
//将串口2接收到的数据回传到串口1
void USART2_IRQHandler(void)
{uint8_t ucTemp;if(USART_GetITStatus(DEBUG_USART2,USART_IT_RXNE)!RESET){ ucTemp USART_ReceiveData(DEBUG_USART2);uart_buf_put(ucTemp);//往环形串口缓冲区存数据}
}五、STM32连接阿里云驱动程序
STM32连接阿里云程序逻辑与串口助手的一致之前使用串口助手与我的电脑进行数据交换现在将STM32当成一个小型的“电脑”使用STM32来对ESP8266的数据进行处理达到物联网控制的目的。 我使用的是STM32霸道的开发板做的测试例程 使用杜邦线连接ESP8266模块以下的厂程序供大家参考如有问题望指摘。 esp8266.c
/********************************************************************************* file esp8266.c* author fire* version V1.0* date 2024-1-16* brief esp8266连接阿里云物联网平台******************************************************************************
**/#include ./ESP8266/esp8266.h//测试esp8266是否存在
//向串口2发送“AT”esp8266收到后会回复一个“Ok”
//STM32会将串口2收到的数据转发到串口1用于监视串口2状态
//函数需要提前初始化串口1串口2串口2中断接收
//成功读取到esp8266返回1否则返回0
char esp8266_text(void)
{uint8_t ch;uint8_t str[20], i0;char* pch;//发送测试命令Usart_SendString(DEBUG_USART2, AT\r\n);//延时一段时间等待接收Delay_ms(50);//向串口环形缓冲区取数据while(!fifo_is_empty()){if(uart_buf_get(ch)){str[i] ch;i;}}//STM32将连接在串口2上ESP8266发送过来的数据转发到串口1
// Usart_SendString(DEBUG_USART1, 收到ESP8266传来的数据\r\n);
// Usart_SendString(DEBUG_USART1, (char *)str);
// Usart_SendString(DEBUG_USART1, \r\n);pch strstr((char *)str, OK);if(pch ! NULL){Usart_SendString(DEBUG_USART1, esp8266真实存在\r\n);return 1;}elsereturn 0;
}//esp8266重启
void esp8266_restart(void)
{uint8_t ch;uint8_t str[255], i0;//发送命令Usart_SendString(DEBUG_USART2, ATRST\r\n);//延时一段时间等待接收Delay_ms(50);//向串口环形缓冲区取数据while(!fifo_is_empty()){if(uart_buf_get(ch)){str[i] ch;i;}}//STM32将连接在串口2上ESP8266发送过来的数据转发到串口1Usart_SendString(DEBUG_USART1, 收到ESP8266传来的数据\r\n);Usart_SendString(DEBUG_USART1, (char *)str);Usart_SendString(DEBUG_USART1, \r\n);
}//将esp8266设置为接入点模式
//设置成功返回1失败返回0
char esp8266_setStation(void)
{uint8_t ch;uint8_t str[20], i0; char* pch;//发送命令Usart_SendString(DEBUG_USART2, ATCWMODE1\r\n);//延时一段时间等待接收Delay_ms(50);//向串口环形缓冲区取数据while(!fifo_is_empty()){if(uart_buf_get(ch)){str[i] ch;i;}}//STM32将连接在串口2上ESP8266发送过来的数据转发到串口1
// Usart_SendString(DEBUG_USART1, 收到ESP8266传来的数据\r\n);
// Usart_SendString(DEBUG_USART1, (char *)str);
// Usart_SendString(DEBUG_USART1, \r\n);pch strstr((char *)str, OK);if(pch ! NULL)return 1;elsereturn 0;
}//查询WiFi连接信息
//如果成功连接WiFi返回1否则返回0
char esp8266_inquireWiFi_Data(void)
{uint8_t ch;uint8_t str[255], i0;char* pch;//发送命令Usart_SendString(DEBUG_USART2, ATCWSTATE?\r\n);//延时一段时间等待接收Delay_ms(50);//向串口环形缓冲区取数据while(!fifo_is_empty()){if(uart_buf_get(ch)){str[i] ch;i;}}//STM32将连接在串口2上ESP8266发送过来的数据转发到串口1
// Usart_SendString(DEBUG_USART1, 收到ESP8266传来的数据\r\n);
// Usart_SendString(DEBUG_USART1, (char *)str);
// Usart_SendString(DEBUG_USART1, \r\n);pch strchr((char *)str, 2);if(pch ! NULL)return 1;elsereturn 0;
}//连接WiFi
void esp8266_connectWiFi(void)
{uint8_t ch, i0;char str[255];//将要发送的数据拼接起来char wifi_data[255] ATCWJAP\;strcat(wifi_data, WiFi_Name);strcat(wifi_data, \,\);strcat(wifi_data, WiFi_Password);strcat(wifi_data, \\r\n);//发送命令Usart_SendString(DEBUG_USART2, wifi_data);//延时一段时间等待接收Delay_ms(50);//向串口环形缓冲区取数据while(!fifo_is_empty()){if(uart_buf_get(ch)){str[i] ch;i;}}//STM32将连接在串口2上ESP8266发送过来的数据转发到串口1Usart_SendString(DEBUG_USART1, 收到ESP8266传来的数据\r\n);Usart_SendString(DEBUG_USART1, str);Usart_SendString(DEBUG_USART1, \r\n);
}//设置MQTT连接参数
//设置成功返回1否则返回0
char esp8266_setMQTTData(void)
{uint8_t ch;uint8_t str[255], i0;char* pch;//发送命令Usart_SendString(DEBUG_USART2, ATMQTTUSERCFG0,1,\);Usart_SendString(DEBUG_USART2, Aliyun_ClientId);Usart_SendString(DEBUG_USART2, \,\);Usart_SendString(DEBUG_USART2, Aliyun_Username);Usart_SendString(DEBUG_USART2, \,\);Usart_SendString(DEBUG_USART2, Aliyun_Password);Usart_SendString(DEBUG_USART2, \,0,0,\\\r\n);//延时一段时间等待接收Delay_ms(50);//向串口环形缓冲区取数据while(!fifo_is_empty()){if(uart_buf_get(ch)){str[i] ch;i;}}// Usart_SendString(DEBUG_USART1, 收到ESP8266传来的数据\r\n);
// Usart_SendString(DEBUG_USART1, (char *)str);
// Usart_SendString(DEBUG_USART1, \r\n);pch strstr((char *)str, OK);if(pch ! NULL)return 1;elsereturn 0;
}//连接阿里云
//连接成功回复1失败回复0
char connect_Aliyun(void)
{uint8_t ch;uint8_t str[255], i0;char* pch;//检查esp8266是否存在if(esp8266_text() ! 1){printf(连接错误代码1请检测esp8266与芯片连接线路\r\n);return 0;}//设置esp8266为接入点模式if(esp8266_setStation() ! 1){printf(连接错误代码2esp8266 接入点模式设置失败请检查\r\n);return 0;}else{printf(接入点模式设置成功\r\n);}//连接WiFi网络//连接之前先检查WiFi网络是否连接//如果以连接则跳过此步骤if(esp8266_inquireWiFi_Data() ! 1){//连接WiFiesp8266_connectWiFi();printf(正在连接WiFi);//5(s)*1560(s)1(min)//等待一段时间待WiFi连接成功i15;while(1){Delay_ms(5000);printf(.);//如果WiFi成功退出循环if(esp8266_inquireWiFi_Data() 1){printf(WiFi连接成功\r\n);break;}//超时连接退出程序i--;if(i 0){printf(\r\n错误代码3WiFi连接超时已退出\r\n);return 0;}}}else{printf(WiFi连接成功\r\n);}//设置MQTT连接参数if(esp8266_setMQTTData() ! 1){printf(连接错误代码4esp8266 接入点模式设置失败请检查\r\n);return 0;}else{printf(MQTT连接参数设置成功\r\n);}//-------------------------------------------------------------------------------------------for(i0; i255; i){str[i] \0;}i0;//下面开始连接阿里云//发送命令Usart_SendString(DEBUG_USART2, ATMQTTCONN0,\);Usart_SendString(DEBUG_USART2, BrokerAddress);Usart_SendString(DEBUG_USART2, \,1883,1\r\n);Delay_ms(50);//向串口环形缓冲区取数据while(!fifo_is_empty()){if(uart_buf_get(ch)){str[i] ch;i;}}// Usart_SendString(DEBUG_USART1, 收到ESP8266传来的数据\r\n);
// Usart_SendString(DEBUG_USART1, (char *)str);
// Usart_SendString(DEBUG_USART1, \r\n);// for(i0; i255; i)
// {
// str[i] \0;
// }
//
// i0;//查询阿里云连接状态Usart_SendString(DEBUG_USART2, ATMQTTCONN?);Delay_ms(50);//向串口环形缓冲区取数据while(!fifo_is_empty()){if(uart_buf_get(ch)){str[i] ch;i;}}Usart_SendString(DEBUG_USART1, 阿里云的连接状态为\r\n);Usart_SendString(DEBUG_USART1, (char *)str);Usart_SendString(DEBUG_USART1, \r\n);pch strstr((char *)str, BrokerAddress);if(pch ! NULL){printf(阿里云物联网平台连接成功\r\n);return 1;}else{printf(错误代码6阿里云物联网平台连接失败请检查\r\n);return 0;}
}//向阿里云上传温度数据
void AliyunSetData(float temperature)
{uint8_t ch;uint8_t str[255], i0;//发送数据Usart_SendString(DEBUG_USART2, ATMQTTPUB0,\);Usart_SendString(DEBUG_USART2, IssueTOPIC);Usart_SendString(DEBUG_USART2, \,\{\\\params\\\: {\\\temperature\\\:);//将浮点型数据转换成字符串并发送出去char str2[10];sprintf(str2,%f, temperature);Usart_SendString(DEBUG_USART2, str2);Usart_SendString(DEBUG_USART2, }\\,\\\version\\\: \\\1.0\\\}\,0,0\r\n);Delay_ms(50);//向串口环形缓冲区取数据while(!fifo_is_empty()){if(uart_buf_get(ch)){str[i] ch;i;}}Usart_SendString(DEBUG_USART1, 收到ESP8266传来的数据\r\n);Usart_SendString(DEBUG_USART1, (char *)str);Usart_SendString(DEBUG_USART1, \r\n);
}//阿里云订阅数据
void AliyunSubscriptionData(void)
{ uint8_t ch;uint8_t str3[255], i0;Usart_SendString(DEBUG_USART2, ATMQTTSUB0,\);Usart_SendString(DEBUG_USART2, SubscriptionTOPIC);Usart_SendString(DEBUG_USART2, \,0\r\n);Delay_ms(50);//向串口环形缓冲区取数据while(!fifo_is_empty()){if(uart_buf_get(ch)){str3[i] ch;i;}}Usart_SendString(DEBUG_USART1, \r\n);Usart_SendString(DEBUG_USART1, esp8266设置订阅数据回复\r\n);Usart_SendString(DEBUG_USART1, (char *)str3);Usart_SendString(DEBUG_USART1, \r\n);
}
esp8266.h
#ifndef __ESP8266_H
#define __ESP8266_H#include stm32f10x.h
#include usart.h
#include delay.h
#include string.h#define WiFi_Name CMCC-H3qz
#define WiFi_Password 7xf47uxf
#define Aliyun_ClientId k0efkfcSwlt.Device_Demo|securemode2\\,signmethodhmacsha256\\,timestamp1705149361131|
#define Aliyun_Username Device_Demok0efkfcSwlt
#define Aliyun_Password ea343ac1d6a4eec7b057bcab39a2ffdf88abc8b810ec0dc7ca3de91a56292ff9
#define BrokerAddress k0efkfcSwlt.iot-as-mqtt.cn-shanghai.aliyuncs.com//发布数据topic
#define IssueTOPIC /sys/k0efkfcSwlt/Device_Demo/thing/event/property/post
//订阅数据topic
#define SubscriptionTOPIC /sys/k0efkfcSwlt/Device_Demo/thing/service/property/setchar esp8266_text(void);
void esp8266_restart(void);
char esp8266_setStation(void);
char esp8266_inquireWiFi_Data(void);
void esp8266_connectWiFi(void);
char esp8266_setMQTTData(void);
char connect_Aliyun(void);
void AliyunSetData(float temperature);
void AliyunSubscriptionData(void);#endif
main.c
void RCC_Configuration(void)
{ //Install system time is 72MHZSystemInit();
}int main(void)
{ uint8_t ch, bufferFlag0;char str[255], i0;char *property 0;char led_switch;RCC_Configuration(); //系统时钟初始化Delay_Timer_Init(); //延时函数定时器初始化USART_Config(); //串口1初始化USART2_Config(); //串口2初始化//向串口1 发送一段数据测试串口1初始化成功printf(这是一个STM32挂载ESP8266连接阿里云的例程\r\n);//初始化PB5为输出gpio_OutputConfig(RCC_APB2Periph_GPIOB, GPIO_Pin_5, GPIOB);//并将LED灯熄灭将引脚拉高GPIO_SetBits(GPIOB, GPIO_Pin_5);//如下同理...gpio_OutputConfig(RCC_APB2Periph_GPIOB, GPIO_Pin_0, GPIOB);GPIO_SetBits(GPIOB, GPIO_Pin_0);//初始化PA0为按键功能SW1Key_GPIO_Config(RCC_APB2Periph_GPIOA, GPIO_Pin_0, GPIOA);//初始化PC13为按键功能SW2Key_GPIO_Config(RCC_APB2Periph_GPIOC, GPIO_Pin_13, GPIOC);while(1){//sw1按键按下功能if(Key_Scan(GPIOA, GPIO_Pin_0) 1){//使能串口2USART2_ON;//连接阿里云if(connect_Aliyun() 1){if(GPIO_ReadOutputDataBit(GPIOB,GPIO_Pin_5) 1){GPIO_ResetBits(GPIOB, GPIO_Pin_5); //红灯亮起AliyunSubscriptionData(); //订阅数据} else{GPIO_SetBits(GPIOB, GPIO_Pin_5); //灯熄灭USART2_ON; //使能串口2}}}//sw2按键按下功能//判断esp8266是否存在if(Key_Scan(GPIOC, GPIO_Pin_13) 1){USART2_ON;esp8266_text();}//检测到红灯亮起时发布和订阅数据if(GPIO_ReadOutputDataBit(GPIOB,GPIO_Pin_5) 0){//每隔5秒发布数据Delay_ms(1000);AliyunSetData(1.2);//接收阿里云发送过来的数据for(int j0; j5; j){//每隔1秒查看串口环形缓冲区是否有数据Delay_ms(1000);for(i0; i127; i){str[i] \0;}i0;//向串口环形缓冲区取数据while(!fifo_is_empty()){bufferFlag 1;if(uart_buf_get(ch)){str[i] ch;i;}}if(bufferFlag 1){bufferFlag 0;//STM32将连接在串口2上ESP8266发送过来的数据转发到串口1Usart_SendString(DEBUG_USART1, 收到阿里云服务器发送过来的数据\r\n);Usart_SendString(DEBUG_USART1, str);Usart_SendString(DEBUG_USART1, \r\n);//以下是通过阿里云控制一盏led灯例程property strstr(str, LEDSwitch);if(property ! NULL){led_switch *(property 11);//Usart_SendByte(DEBUG_USART1, led_switch);led_switch led_switch - 48;if(led_switch 0){GPIO_SetBits(GPIOB, GPIO_Pin_0);}else if(led_switch 1){GPIO_ResetBits(GPIOB, GPIO_Pin_0);}}}}}}
}