才发现CSDN把文章变成VIP可查看了,坑人!!!现已重新发布
------------------------------------------------------------------------------------------------------------------------------------
本文为本人学习esp8266过程的学习笔记,源码在最后,接收不定长数据的方法也可以应用在其它地方
由于项目需求,购买了ESP8266作为STM32数据发送到云服务器的桥梁。调试esp8266过程中也遇到了问题。后面采用了串口空闲中断+DMA接收的方法解决了接收不定长数据的问题
esp8266的工作原理我就不赘述了,我看的下面大佬的博客:
(29条消息) 基于STM32的ESP8266使用教程(一)_量化这个世界!-CSDN博客
(29条消息) 【常用模块】ESP8266 WIFI串口通信模块使用详解(实例:附STM32详细代码)_Yngz_Miao的博客-CSDN博客_esp8266wifi模块教程
问题:如何在PC端发送AT指令到stm32,stm32再传输给esp8266,最后将esp8266传回的数据通过串口打印出来。由于ESP8266返回的数据是不定长数据,并且没有规定好的结束符,因此无法用串口接收中断来处理数据。
解决方案:
对于接收不定长数据,如何知道完成了数据的接收呢?
最常用的办法是使用空闲中断,在串口空闲的时候,触发一次中断,通知内核,本次运输完成了。串口空闲中断的判定是:当串口开始接收数据后,检测到1字节数据的时间内没有数据发送,则认为串口空闲了。由于我们的内核在串口接收数据到空闲这段时间,是不受理串口数据的,所以我们还需要使用DMA来协助我们把数据传送到指定的地方,当数据传输完成后,通知内核去处理。
实现流程
(1)开启串口空闲中断: 在程序初始化时候,使能串口中断
(2)定义串口空闲中断处理函数: 在串口中断中添加串口空闲中断处理函数 ,用以标记数据接收完成,计算接收到数据的长度我采用了stm32上的双串口通信,串口1(Lpuart1)用来PC端发送数据以及接受数据,串口4(uart4)用来与esp8266通信。通信流程如下图:
PC发送指令到Lpuart1,在Lpuart1开启接收中断,在中断回调函数里,将接收到的数据发送给uart4,uart4采用DMA串口空闲中断接收(uart4的RX、TX与esp8266的TX,RX相连),uart4接收到的数据会直接发送给esp8266,esp8266返回来的数据通过printf函数(已重定向到串口1)打印到PC。
经过调试,功能有一点瑕疵:如果在进入串口4空闲中断服务函数时不加延时,那么8266返回的一些比较长的数据会接收不到(例如PC发送:AT+GMR),若有大佬知道是什么原因,还望指导小弟以下
实现流程:
在cubemx里使能两个串口,并在串口4开启DMA接收,模式设置为循环。
下面为代码(用到的代码都有注释解释):
usart.h里添加的代码
#include “stdio.h”
/*重定向printf函数*/
#ifdef __GNUC__
#define PUTCHAR_PROTOTYPE int __io_putchar(int ch)
#else
#define PUTCHAR_PROTOTYPE int fputc(int ch, FILE *f)
#endif /* __GNUC__ */
/*串口2的接收缓冲变量*/
#define Rxbuffer4_Size 1024
extern uint8_t c;
extern uint8_t RxBuffer_4[];
extern uint16_t RxNum_4;
/*串口L1的接收缓冲变量*/
extern uint8_t aRxBuffer; //接收中断缓冲
extern uint8_t Uart1_RxBuff[256]; //接收缓冲
extern uint8_t Uart1_Rx_Cnt ; //接收缓冲计数
extern uint8_t cAlmStr[] ;
usart.c里添加的代码
/* USER CODE BEGIN 0 */
uint8_t RxBuffer_4[Rxbuffer4_Size];//数据缓冲数组
uint16_t RxNum_4 = 0;//接收的数据长度
/* USER CODE END 0 */
void MX_LPUART1_UART_Init(void)
{
/* USER CODE BEGIN LPUART1_Init 2 */
/*使能串口1的接收中断*/
HAL_UART_Receive_IT(&hlpuart1, (uint8_t *)&aRxBuffer, 1);
/* USER CODE END LPUART1_Init 2 */
}
void MX_UART4_Init(void)
{
/* USER CODE BEGIN UART4_Init 2 */
//开启串口4的空闲中断
__HAL_UART_ENABLE_IT(&huart4, UART_IT_IDLE);
/* USER CODE END UART4_Init 2 */
}
/*添加重定向的代码*/
PUTCHAR_PROTOTYPE
{
/* e.g. write a character to the LPUART1 and Loop until the end of transmission */
HAL_UART_Transmit( &hlpuart1, (uint8_t *)&ch, 1, 0xFFFF);
return ch;
}
stm32g4xx_it.c里添加的代码
/*在串口4的中断服务函数里添加下面的内容*/
void UART4_IRQHandler(void)
{
//判断是否是空闲中断
if(__HAL_UART_GET_FLAG(&huart4, UART_FLAG_IDLE) == SET)
{
HAL_Delay(100);//如果没有这个延时,接收8266回来的数据有时会无法显示,例如发送AT+GMR
//例如发送AT+GMR,返回的数据就无法正常显示,具体原因我也还没搞懂
printf("\r\n我是串口2,我收到数据了\r\n");
//清除空闲中断标志(否则会一直不断进入中断)
__HAL_UART_CLEAR_IDLEFLAG(&huart4);
//暂停DMA接收
HAL_UART_DMAStop(&huart4);
RxNum_4 = Rxbuffer4_Size - __HAL_DMA_GET_COUNTER(&hdma_uart4_rx);
printf("\r\n我是串口4,我收到的数据长度为:\r\n%s\r\n",RxBuffer_4);
//将数据缓冲数组清零
memset(RxBuffer_4 ,0,Rxbuffer4_Size);
//使能下一次的DMA接收
HAL_UART_Receive_DMA(&huart4,RxBuffer_4,Rxbuffer4_Size);
}
}
/*中断回调函数*/
void HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart)
{
/* Prevent unused argument(s) compilation warning */
UNUSED(huart);
/* NOTE: This function Should not be modified, when the callback is needed,
the HAL_UART_TxCpltCallback could be implemented in the user file
*/
if(huart->Instance == LPUART1)
{
if(Uart1_Rx_Cnt >= 255) //溢出判断
{
Uart1_Rx_Cnt = 0;
memset(Uart1_RxBuff,0x00,sizeof(Uart1_RxBuff));//用来清空数组,memset是一个清空数组函数
HAL_UART_Transmit(&hlpuart1, (uint8_t *)&cAlmStr, sizeof(cAlmStr),0xFFFF);
}
else
{
Uart1_RxBuff[Uart1_Rx_Cnt++] = aRxBuffer; //接收数据转存
if((Uart1_RxBuff[Uart1_Rx_Cnt-1] == 0x0A)&&(Uart1_RxBuff[Uart1_Rx_Cnt-2] == 0x0D)) //判断结束位
{
printf("\r\n我是串口1,我现在发送指令过去了,现在是第%d次发送\r\n",c);
c++;
HAL_UART_Transmit(&huart4, (uint8_t *)&Uart1_RxBuff, Uart1_Rx_Cnt,0xFFFF); //将收到的信息发送出去
while(HAL_UART_GetState(&hlpuart1) == HAL_UART_STATE_BUSY_TX)//检测UART发送结束
Uart1_Rx_Cnt = 0;
printf("\r\n我是串口1,我现在要清空数组了\r\n");
memset(Uart1_RxBuff,0x00,sizeof(Uart1_RxBuff)); //用来清空数组,memset是一个清空数组函数
}
}
HAL_UART_Receive_IT(&hlpuart1, (uint8_t *)&aRxBuffer, 1); //再开启接收中断
}
}
工程文件:
链接:https://pan.baidu.com/s/1JiPnx1QgEbOCdMDVv1Up_A
提取码:at89