赞
踩
准备工作见下文第三节:ESP8266+OneNet使用物模型实现数据的收发(仅为连接单片机前的调试工作,本章不涉及单片机)-CSDN博客
在使用单片机发送相关AT指令时需要用到单片机的串口功能,下面使用库函数对串口进行配置。小编对USART1和USART3进行了配置,使用串口1连接ESP8266,使用串口3连接USB-TTL(便于将串口1接收到的缓冲通过串口3发送至串口助手观察)。单片机、ESP8266、ST-LINK、USB-TTL引脚连接如下(下图均为引脚名称):
STM32F103 | ST-LINK |
SWCLK | SWCLK |
SWDIO(或SWIO) | SWDIO |
GND | GND |
3V3(或3.3) | 3V3 |
STM32F103 | ESP8266 |
PA9 | RX |
PA10 | TX |
GND | G |
3V3(或3.3) | 3V |
STM32F103 | USB-TTL |
PB10 | RXD |
由于小编仅使用串口3的TXD,因此不将串口3的RXD与下载器的TXD相连,在下面进行串口配置时小编也不会对串口3的RXD功能进行配置。
小编使用库函数进行串口的配置,具体见下述代码:
- //Serial.c
- #include "stm32f10x.h"
-
- uint8_t Serial_RxBuff[300]; //定义接收数据的存放区域
- uint16_t RxCount; //定义接收到数据的个数
-
- /**
- * @brief 串口1配置
- * @param 无
- * @retval 无
- */
- void Serial_Init(void)
- {
- GPIO_InitTypeDef GPIO_InitStructure;
- USART_InitTypeDef USART_InitStructure;
- NVIC_InitTypeDef NVIC_InitStructure; //定义结构体变量
-
- RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1,ENABLE); //打开USART1的时钟
- RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA,ENABLE); //打开GPIOA的时钟
-
- GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;
- GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
- GPIO_InitStructure.GPIO_Pin = GPIO_Pin_9;
- GPIO_Init(GPIOA, &GPIO_InitStructure); //初始化PA9引脚为服用推完输出,即TXD
- GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU;
- GPIO_InitStructure.GPIO_Pin = GPIO_Pin_10;
- GPIO_Init(GPIOA, &GPIO_InitStructure); //初始化PA10引脚为上拉输入,即RXD
-
- USART_InitStructure.USART_BaudRate = 115200; //波特率,可调
- USART_InitStructure.USART_HardwareFlowControl = USART_HardwareFlowControl_None; //无硬件流控
- USART_InitStructure.USART_Mode = USART_Mode_Tx | USART_Mode_Rx; //发送和接收模式
- USART_InitStructure.USART_Parity = USART_Parity_No; //无校验
- USART_InitStructure.USART_StopBits = USART_StopBits_1; //1位停止位
- USART_InitStructure.USART_WordLength = USART_WordLength_8b; //字长8位
- USART_Init(USART1,&USART_InitStructure); //将结构体参数赋值,配置串口1
-
- USART_ITConfig(USART1,USART_IT_RXNE,ENABLE); //开启串口1接收数据的中断
-
- NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2); //配置NVIC分组2,2位抢占优先级,2位响应优先级
-
- NVIC_InitStructure.NVIC_IRQChannel = USART1_IRQn; //选择配置NVIC的串口线
- NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; //指定NVIC线路使能
- NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 1; //配置抢占优先级为1
- NVIC_InitStructure.NVIC_IRQChannelSubPriority = 1; //配置响应优先级为1
- NVIC_Init(&NVIC_InitStructure); //将结构体参数赋值,配置中断
-
- USART_Cmd(USART1,ENABLE); //使能串口1,串口开始运行
- }
-
- /**
- * @brief 串口3配置
- * @param 无
- * @retval 无
- */
- void Serial3_Init(void)
- {
- GPIO_InitTypeDef GPIO_InitStructure;
- USART_InitTypeDef USART_InitStructure; //定义结构体变量
-
- RCC_APB1PeriphClockCmd(RCC_APB1Periph_USART3,ENABLE); //打开USART3的时钟
- RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB,ENABLE); //打开GPIOB的时钟
-
- GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;
- GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
- GPIO_InitStructure.GPIO_Pin = GPIO_Pin_10;
- GPIO_Init(GPIOB, &GPIO_InitStructure); //初始化PB10引脚为服用推完输出,即TXD
-
-
- USART_InitStructure.USART_BaudRate = 115200; //波特率,可调
- USART_InitStructure.USART_HardwareFlowControl = USART_HardwareFlowControl_None; //无硬件流控
- USART_InitStructure.USART_Mode = USART_Mode_Tx; //发送模式
- USART_InitStructure.USART_Parity = USART_Parity_No; //无校验
- USART_InitStructure.USART_StopBits = USART_StopBits_1; //1位停止位
- USART_InitStructure.USART_WordLength = USART_WordLength_8b; //字长8位
- USART_Init(USART3,&USART_InitStructure); //将结构体参数赋值,配置串口3
-
-
- USART_Cmd(USART3,ENABLE); //使能串口3,串口开始运行
- }
-
- /**
- * @brief 串口1发送一个字节
- * @param Byte,串口发送的一个字节
- * @retval 无
- */
- void Serial_SendByte(uint8_t Byte)
- {
- USART_SendData(USART1,Byte); //将字节写入数据寄存器,写入后自动发送
- while(USART_GetFlagStatus(USART1,USART_FLAG_TXE) == RESET); //等待发送完成,发送完成自动清除标志位
- }
-
- /**
- * @brief 串口1发送一个字符串
- * @param String,发送字符串的首地址
- * @retval
- */
- void Serial_SendString(char *String)
- {
- uint8_t i;
- for(i = 0;String[i] != '\0';i++) //遍历字符数组,遇到结束标志停止
- {
- Serial_SendByte(String[i]); //调用发送一个字节发送数据
- }
- }
-
- /**
- * @brief 串口3发送一个字节
- * @param Byte,串口发送的一个字节
- * @retval 无
- */
- void Serial3_SendByte(uint8_t Byte)
- {
- USART_SendData(USART3,Byte); //将字节写入数据寄存器,写入后自动发送
- while(USART_GetFlagStatus(USART3,USART_FLAG_TXE) == RESET); //等待发送完成,发送完成自动清除标志位
- }
-
- /**
- * @brief 串口1发送一个字符串
- * @param String,发送字符串的首地址
- * @retval
- */
- void Serial3_SendString(char *String)
- {
- uint8_t i;
- for(i = 0;String[i] != '\0';i++) //遍历字符数组,遇到结束标志停止
- {
- Serial3_SendByte(String[i]); //调用发送一个字节发送数据
- }
- }
- /**
- * @brief 清除数据缓冲区
- * @param 无
- * @retval 无
- */
- void Clear_Buffer(void)
- {
- uint16_t i;
- for(i=0;i<RxCount;i++) //将0写入缓冲区,直到大于缓冲区接收到的字符数量
- {
- Serial_RxBuff[i]=0;//缓存
- }
- RxCount=0; //重新计数,等待下一次接收
- }
-
- /**
- * @brief 串口1中断函数
- * @param 无
- * @retval 无
- */
- void USART1_IRQHandler(void)
- {
- uint8_t data; //定义临时变量存放串口接收的一个字节
- if(USART_GetITStatus(USART1,USART_IT_RXNE) == SET) //判断是否是串口1的接收事件触发中断
- {
-
- data = USART_ReceiveData(USART1); //读取数据寄存器,存放在临时变量
- if(data != '\r' || data != '\n' ) //判断接收数据不是结束标志
- {
- Serial_RxBuff[RxCount++] = data; //不是结束标志,将数据存放在缓存区
- }
- if(data == '\n') //判断接收数据是结束标志
- {
- Serial_RxBuff[RxCount] = '\0'; //是结束标志,给缓存区的最后一位添加结束标志
- }
-
- USART_ClearITPendingBit(USART1,USART_IT_RXNE); //清除标志位
- }
- }
-
-
-
- //Serial.h
- #ifndef __SERIAL__H_
- #define __SERIAL__H_
-
- extern char Serial_RxBuff[];
-
- void Serial_Init(void);
- void Serial_SendByte(uint8_t Byte);
- void Serial_SendString(char *String);
- void Clear_Buffer(void);
- void Serial3_Init(void);
- void Serial3_SendByte(uint8_t Byte);
- void Serial3_SendString(char *String);
-
- #endif
- //main.c
- #include "stm32f10x.h" // Device header
- #include "serial.h"
- #include "delay.h"
-
- char CWJAP[] = "AT+CWJAP=\"@PHICOMM_60\",\"lzj123456lzj\"\r\n";
- char MQTTUSERCFG[] = "AT+MQTTUSERCFG=0,1,\"esp8266\",\"OWA8D1n1ES\",\"version=2018-10-31&res=products%2FOWA8D1n1ES%2Fdevices%2Fesp8266&et=1745287964&method=md5&sign=VBufe7exEABGp0ub0ezEUQ%3D%3D\",0,0,\"\"\r\n";
- char MQTTCONN[] = "AT+MQTTCONN=0,\"mqtts.heclouds.com\",1883,0\r\n";
-
- int main()
- {
- Serial_Init();
- Serial3_Init();
-
- Serial_SendString("AT+RST\r\n");
- Delay_ms(500);
- Serial3_SendString(Serial_RxBuff);
- Clear_Buffer();
- Serial_SendString("AT+CWMODE=1\r\n");
- Delay_ms(500);
- Serial3_SendString(Serial_RxBuff);
- Clear_Buffer();
- Serial_SendString(CWJAP);
- Delay_ms(3000);
- Serial3_SendString(Serial_RxBuff);
- Clear_Buffer();
- Serial_SendString(MQTTUSERCFG);
- Delay_ms(500);
- Serial3_SendString(Serial_RxBuff);
- Clear_Buffer();
- Serial_SendString(MQTTCONN);
- Delay_ms(500);
- Serial3_SendString(Serial_RxBuff);
- Clear_Buffer();
- while(1)
- {
-
-
- }
- }
在main.c中这里发送的参数就不进行介绍,可以参考本文第一节的准备工作。在这里需要特别注意在发送AT+RST时,正确情况下我们应该接收到ready才判断其复位成功,但在实际操作中小编发现无法完整的将串口1接收到的缓冲通过串口3发送出来。小编猜测在ESP8266的回传数据中有的存在因此无法将其保存在缓冲区(有知道的小伙伴可以分享一下),但所幸并影响后续的操作。其次,还要注意Serial_SendString(CWJAP);需要的时间间隔较长,小编尝试了500ms、1000ms、2000ms在执行后续过程时会返回busy从而导致后续执行出错,知道小编尝试3000ms才成功,因此大家在操作中需要密切注意这一步。
失败:
成功:
同时设备上线
同时再补充一点,如果通过esp8266连接上云平台后,如果再次发送AT+MQTTUSERCFG和AT+MQTTCONN的指令时是会返回ERROE的,必须复位后执行才能正常连接。
代码如下:
【免费】STM32+ESP8266+OneNet(仅连接,不涉及数据的上下行)资源-CSDN文库
补充:将Serial.c的
- uint8_t Serial_RxBuff[300]; //定义接收数据的存放区域
- uint16_t RxCount; //定义接收到数据的个数
改为
- uint8_t Serial_RxBuff[250]; //定义接收数据的存放区域
- uint8_t RxCount; //定义接收到数据的个数
可以接收到正常发送AT+RST的回传内容,但会接收到多次
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。