【STM32】使用STM32CubeMX配置串口DMA实现高效不定长数据接收与IDLE检测

        本文主要讲解如何配置串口使能IDLE空闲帧中断使用DMA来搬运接收到的数据。

一、大致原理

当接收器连续接收到一个完整的数据帧后(例如在8N1模式下,即1个起始位、8个数据位、1个停止位),如果接收线上没有立即出现下一个起始位,且信号保持空闲状态(逻辑高电平)超过至少一个字符的传输时间(即“帧时间”),则会触发IDLE中断。

DMA的Normal模式和circular模式的区别:

Normal模式(普通模式):

在Normal模式下,DMA会按照预先设定的数据传输长度(NDTR寄存器设置的值)进行传输,传输完毕后停止工作,不再自动重启。也就是说,完成一次完整的数据搬运后,DMA停止传输,需要软件重新启动DMA才能进行下一次传输。

Circular模式(循环模式):

在Circular模式下,DMA在完成一次数据传输后,会自动重新加载NDTR寄存器的初始值,从而重新开始传输。这意味着DMA会以循环的方式不断地搬运数据,适合用于连续数据流的应用场景(如音频采集、连续串口接收、ADC连续采样等)。

二、操作步骤

1.stm32cubemx操作

1.1使能串口

创建项目、时钟配置和项目管理配置步骤我就跳过了,大家根据自己的型号来进行配置。

首先先使能串口为异步模式。选择步骤2的对应串口,配置步骤3的串口模式为异步模式,第4个框的内容不用修改。

第四个框的配置内容解释如下:

Basic Parameters(基本参数)
    Baud Rate(波特率):115200 Bits/s
    Word Length(数据位长度): 8 Bits (including Parity)
    Parity(奇偶校验位):无
    Stop Bits(停止位) : 1位

Advanced Parameters(高级参数)
    Data Direction(数据方向)
        Receive and Transmit(接收和发送)
        说明该串口既可以进行数据接收,也可以进行数据发送。
        适用于全双工或半双工通信场景。
    Over Sampling(过采样率)
        16 Samples
        说明 UART 采用 16 倍过采样率(通常有 8 或 16 可选)。
        16 倍过采样能提供更好的抗噪能力,使数据采样更加稳定。
        但在某些低功耗应用中,可能会选择 8 倍过采样,以降低功耗和提高吞吐率。
        

1.2使能串口接收DMA

1.3选择循环模式

     

使能串口中断, 然后生成代码

2.keil代码编写

1.1在main.h文件中添加缓存大小#define

/* Exported constants --------------------------------------------------------*/
/* USER CODE BEGIN EC */
#define RX_BUFFER_SIZE  256
/* USER CODE END EC */

1.2在main.c文件的代码块块中分别添加

{    
/* USER CODE BEGIN PV */
uint8_t uart_rx_buffer[RX_BUFFER_SIZE];	// DMA搬运目标缓存
/* USER CODE END PV */
}



{
  /* USER CODE BEGIN 2 */

	__HAL_UART_ENABLE_IT(&huart1, UART_IT_IDLE);  // 使能串口IDLE中断
  HAL_UART_Receive_DMA(&huart1, uart_rx_buffer, RX_BUFFER_SIZE); // 开启串口接收DMA

  /* USER CODE END 2 */

  /* Infinite loop */
  /* USER CODE BEGIN WHILE */
  while (1)
  {
    /* USER CODE END WHILE */

    /* USER CODE BEGIN 3 */
  }
  /* USER CODE END 3 */

}

1.3在stm32f4xx_it.c添加代码

/**
  * @brief This function handles USART1 global interrupt.
  */
void USART1_IRQHandler(void)
{
  /* USER CODE BEGIN USART1_IRQn 0 */
	if(__HAL_UART_GET_FLAG(&huart1, UART_FLAG_IDLE) != RESET){	// 判断是否产生IDLE中断
		
		__HAL_UART_CLEAR_IDLEFLAG(&huart1);  	// 清除IDLE中断标志位
		HAL_UART_DMAStop(&huart1);	// 停止DMA接收
        uint16_t received_length = RX_BUFFER_SIZE - __HAL_DMA_GET_COUNTER(huart1.hdmarx);	// 计算实际接收到的数据长度
		
		// 业务代码
		HAL_UART_Transmit(&huart1, uart_rx_buffer, received_length, 100);	// 发送接收到的数据
		
		HAL_UART_Receive_DMA(&huart1, uart_rx_buffer, RX_BUFFER_SIZE);	// 开启DMA接收
	}
  /* USER CODE END USART1_IRQn 0 */
  HAL_UART_IRQHandler(&huart1);
  /* USER CODE BEGIN USART1_IRQn 1 */

  /* USER CODE END USART1_IRQn 1 */
}

以下是实验结果:

作者:来块小鱼饼干(≧^.^≦)

物联沃分享整理
物联沃-IOTWORD物联网 » 【STM32】使用STM32CubeMX配置串口DMA实现高效不定长数据接收与IDLE检测

发表回复