STM32串口通讯--利用IDLE空闲中断来接收不定长数据

回顾

之前有一篇文章讲过用定时器超时的方式接收不定长数据 定时器超时的方式,串口接收不定长数据 ,但需要占用一个定时器资源,本文采用了另一种方式,即通过IDLE中断的方式来接收,更简单,也更省资源。

原理

IDLE顾名思义,就是空闲的意思,即当监测到串口空闲超过1个数据帧时,会使状态寄存器(SR或ISR)的IDLE位置位,如果此时控制寄存器(CR或CR1)的IDLEIE为1,则会触发IDLE中断。知道原理了,就好操作了。

CubeMX常规操作

1 启动usart1,并开启中断,其他默认

STM32串口通讯--利用IDLE空闲中断来接收不定长数据_第1张图片

2 开启调试接口SWD

STM32串口通讯--利用IDLE空闲中断来接收不定长数据_第2张图片

3 设置好时钟

STM32串口通讯--利用IDLE空闲中断来接收不定长数据_第3张图片

4 代码选项,生成KEIL代码

STM32串口通讯--利用IDLE空闲中断来接收不定长数据_第4张图片

手动修改代码

1 在main函数中增加一行,以启动RXNEIE中断,即串口接收中断

main()
...
  HAL_UART_Receive_IT(&huart2, uart2_receive_buf, 1);
  __HAL_UART_ENABLE_IT(&huart2, UART_IT_RXNE);	//启动RXNE中断
  __HAL_UART_ENABLE_IT(&huart2, UART_IT_IDLE);	//启动IDLE中断
...
  while (1)

2 在stm32h7xx_it.c,这个中断文件中,修改串口中断函数

u8 uart2_receive_point = 0;
u8 uart2_receive_buf[100];
u8 uart2_receive_over = 0;
u8 uart2_temp;

void USART2_IRQHandler(void)
{
  /* USER CODE BEGIN USART2_IRQn 0 */

  /* USER CODE END USART2_IRQn 0 */

  HAL_UART_IRQHandler(&huart2);

  /* USER CODE BEGIN USART2_IRQn 1 */
  //收到1个字节的数据
  if(__HAL_UART_GET_FLAG(&huart2, UART_FLAG_RXNE))
  {
    __HAL_UART_ENABLE_IT(&huart2, UART_IT_RXNE);	//启动RXNE中断
    uart2_receive_buf[uart2_receive_point] = huart2.Instance->RDR;
    uart2_receive_point ++;
  }
  
  //长时间未接收到数据时,会发生IDLE中断,此时意味着数据接收完成
  //不同的内核,清除IDLEIE的方式不同,请查阅手册
  if(__HAL_UART_GET_FLAG(&huart2, UART_FLAG_IDLE))
  {
    huart2.Instance->ICR += USART_ICR_IDLECF;	 //向USART_CR1的IDLECF位写1,以清除IDLEIF标志,否则会一直进IDLEIE中断
    uart2_receive_over = UART_RECEIVE_OK;
  }
  /* USER CODE END USART2_IRQn 1 */
}

兼容性

这个空闲中断,对STM32是OK的,但是对于兼容产品不一定适用,比如航顺HK32F103就亲测不行,需要修改代码。开发人员需要注意这个问题

对于STM32来说,不同的内核,清除IDLEIE标志的方法是不同的,这个需要查阅参考手册。如果不清除该位,会一直进IDLE中断。

你可能感兴趣的:(嵌入式开发,stm32,单片机,arm)