串口空闲中断
ESP8266收发数据
一、在使用ESP8266模块时遇到的一些问题,首先是对模块数据的收发,我们在发送AT指令时会收到模块发送的反馈数据。在我们没有使用实时操作系统的情况下,通过HAL库的串口收发函数是比较难以完成工作的。我在参考了众多博客后总结了两种方法:
1、串口接收+50ms定时器
2、串口空闲中断
本文主要是介绍串口空闲中断
空闲中断的定义
空闲的定义是总线上在一个字节的时间内没有再接收到数据,USART_IT_IDLE空闲中断是检测到数据被接收后,总线上在一个字节的时间内没有再接收到数据的时候发生的。
而空闲中断又分为两种:
1、当接收到1个字节,会产生USART_IT_RXNE中断
2、当接收到一帧数据,就会产生USART_IT_IDLE中断
串口空闲中断(UART_IT_IDLE):STM32的IDLE的中断在串口无数据接收的情况下,是不会一直产生的,当清除IDLE标志位后,必须有接收到第一个数据后,才开始触发,一但接收的数据断流,没有接收到数据,即产生IDLE中断。IDLE位不会再次被置高直到RXNE位被置起(即又检测到一次空闲总线)。
IDLE置1之后它不会自动清0,也不会因为状态位是1而一直产生中断,它只有0跳变到1时才会产生,也可以理解为上升沿触发。所以,为确保下次空闲中断正常进行,需要在中断服务函数发送任意数据来清除标志位。
USART_IT_RXNE也是同理,只是判断空闲的标准不一样
void MX_USART2_UART_Init(void)
{
/* USER CODE BEGIN USART2_Init 0 */
/* USER CODE END USART2_Init 0 */
/* USER CODE BEGIN USART2_Init 1 */
/* USER CODE END USART2_Init 1 */
huart2.Instance = USART2;
huart2.Init.BaudRate = 115200;
huart2.Init.WordLength = UART_WORDLENGTH_8B;
huart2.Init.StopBits = UART_STOPBITS_1;
huart2.Init.Parity = UART_PARITY_NONE;
huart2.Init.Mode = UART_MODE_TX_RX;
huart2.Init.HwFlowCtl = UART_HWCONTROL_NONE;
huart2.Init.OverSampling = UART_OVERSAMPLING_16;
if (HAL_UART_Init(&huart2) != HAL_OK)
{
Error_Handler();
}
/* USER CODE BEGIN USART2_Init 2 */
__HAL_UART_CLEAR_IDLEFLAG(&huart2);//清除空闲中断标志位
__HAL_UART_ENABLE_IT(&huart2,UART_IT_IDLE);//开启串口2的空闲中断
memset(WiFi_RX_BUF,0,WiFi_RXBUFF_SIZE); //清空WiFi接收缓冲区
HAL_UART_DMAStop(&huart2);//停止DMA
HAL_UART_Receive_DMA(&huart2,Usart2_RxBuff,USART2_RXBUFF_SIZE);
/* USER CODE END USART2_Init 2 */
}
在串口初始化函数中开启空闲中断,首先是清楚空闲中断标志位,然后是使能UART_IT_IDLE中断。
void USART2_IRQHandler(void)
{
/* USER CODE BEGIN USART2_IRQn 0 */
if(__HAL_UART_GET_FLAG(&huart2,UART_FLAG_IDLE)!=RESET)
{
Usart2_RxCounter=0;
__HAL_UART_CLEAR_IDLEFLAG(&huart2);//清楚空闲中断标志位
HAL_UART_DMAStop(&huart2);//停止DMA接收以防止新的数据覆盖
/*预计要接受的数据量-剩余待接收的数量=接收的数据数量*/
Usart2_RxCounter+=(USART2_RXBUFF_SIZE-__HAL_DMA_GET_COUNTER(&hdma_usart2_rx));
HAL_UART_Receive_DMA(&huart2,Usart2_RxBuff,USART2_RXBUFF_SIZE);
Usart2_RxCompleted=1;//接收标志位置位1,代表数据已经接收
}
/* USER CODE END USART2_IRQn 0 */
HAL_UART_IRQHandler(&huart2);
/* USER CODE BEGIN USART2_IRQn 1 */
/* USER CODE END USART2_IRQn 1 */
}
在中断函数中我们首先判断空闲中断标志位是否置位,如果if成立则清楚标志位,然后再停止DMA接收,以防止后来的数据覆盖缓存,然后再接收数据。
本人能力有限,若有错误的地方情多多包涵