STM32 HAL库配置DMA加空闲中断接收串口数据

一、在cubemx生成的初始化代码中加入DMA

复制代码
void MX_USART1_UART_Init(void)
{
	huart1.Instance = USART1;
	huart1.Init.BaudRate = 115200;

	huart1.Init.WordLength = UART_WORDLENGTH_8B;
	huart1.Init.StopBits = UART_STOPBITS_1;
	huart1.Init.Parity = UART_PARITY_NONE;
	huart1.Init.Mode = UART_MODE_TX_RX;
	huart1.Init.HwFlowCtl = UART_HWCONTROL_NONE;
	// huart1.Init.OverSampling = UART_OVERSAMPLING_16;
	if (HAL_UART_Init(&huart1) != HAL_OK)
	{
		Error_Handler();
	}

	// 启动DMA接收
	HAL_UART_Receive_DMA(&huart1, USART1_DMA_Buffer, USART1_DMA_BUFFER_SIZE);

	// 使能IDLE中断
	__HAL_UART_ENABLE_IT(&huart1, UART_IT_IDLE);
}

二、在HAL_UART_MspInit()中修改

复制代码
else if (uartHandle->Instance == USART1)
	{
		/* USER CODE BEGIN USART1_MspInit 0 */

		/* USER CODE END USART1_MspInit 0 */
		/* USART1 clock enable */
		__HAL_RCC_USART1_CLK_ENABLE();

		__HAL_RCC_GPIOA_CLK_ENABLE();
		/**USART1 GPIO Configuration
		PA9     ------> USART1_TX
		PA10     ------> USART1_RX
		*/
		GPIO_InitStruct.Pin = GPIO_PIN_9 | GPIO_PIN_10;
		GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
		GPIO_InitStruct.Pull = GPIO_NOPULL;
		GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_VERY_HIGH;
		GPIO_InitStruct.Alternate = GPIO_AF7_USART1;
		HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);

		__HAL_RCC_DMA2_CLK_ENABLE();

		// 閰嶇疆DMA
		hdma_usart1_rx.Instance = DMA2_Stream2;
		hdma_usart1_rx.Init.Channel = DMA_CHANNEL_4;
		hdma_usart1_rx.Init.Direction = DMA_PERIPH_TO_MEMORY;
		hdma_usart1_rx.Init.PeriphInc = DMA_PINC_DISABLE;
		hdma_usart1_rx.Init.MemInc = DMA_MINC_ENABLE;
		hdma_usart1_rx.Init.PeriphDataAlignment = DMA_PDATAALIGN_BYTE;
		hdma_usart1_rx.Init.MemDataAlignment = DMA_MDATAALIGN_BYTE;
		hdma_usart1_rx.Init.Mode = DMA_NORMAL;
		hdma_usart1_rx.Init.Priority = DMA_PRIORITY_LOW;
		hdma_usart1_rx.Init.FIFOMode = DMA_FIFOMODE_DISABLE;

		if (HAL_DMA_Init(&hdma_usart1_rx) != HAL_OK)
		{
			Error_Handler();
		}

		__HAL_LINKDMA(uartHandle, hdmarx, hdma_usart1_rx);

		/* DMA2_Stream2_IRQn interrupt configuration */
		HAL_NVIC_SetPriority(DMA2_Stream2_IRQn, 0, 0);
		HAL_NVIC_EnableIRQ(DMA2_Stream2_IRQn);

		HAL_NVIC_SetPriority(USART1_IRQn, 0, 0);
		HAL_NVIC_EnableIRQ(USART1_IRQn);
	}

三、增加对应的DMA中断,这里是DMA2_Stream2_IRQHandler()

复制代码
void DMA2_Stream2_IRQHandler(void)
{
  HAL_DMA_IRQHandler(&hdma_usart1_rx);
}

四、完善串口中断USART1_IRQHandler()

复制代码
void USART1_IRQHandler(void)
{
	// 检查是否是IDLE中断标志
	if (__HAL_UART_GET_FLAG(&huart1, UART_FLAG_IDLE))
	{
		// 清除IDLE标志
		__HAL_UART_CLEAR_FLAG(&huart1, UART_FLAG_IDLE);

		// 停止当前DMA传输
		HAL_UART_DMAStop(&huart1);

		// 计算接收到的数据长度
		uint16_t received_len = USART1_DMA_BUFFER_SIZE - __HAL_DMA_GET_COUNTER(&hdma_usart1_rx);

		// 将接收到的数据保存到UART1BUF缓冲区
		if (received_len > 0 && received_len <= UARTLEN)
		{
			// 将数据从DMA缓冲区复制到UART1BUF
			memcpy(UART1BUF, USART1_DMA_Buffer, received_len);
			UART1_byte_count = received_len;
			UART1RcvFg = 1; // 设置接收完成标志
		}

		// 重新启动DMA接收
		HAL_UART_Receive_DMA(&huart1, USART1_DMA_Buffer, USART1_DMA_BUFFER_SIZE);
	}

	// 处理HAL库相关中断
	HAL_UART_IRQHandler(&huart1);
}
相关推荐
bubiyoushang8882 小时前
STM32F103C8T6+DM9051以太网功能实现方案
stm32·单片机·嵌入式硬件
IT_阿水2 小时前
基于STM32河流水质检测
stm32·单片机·嵌入式硬件
黑白园2 小时前
STM32定时器中断
stm32·单片机·嵌入式硬件
weixin_456808383 小时前
【沁恒蓝牙开发】ADC DMA定时采样、转化
单片机·嵌入式硬件
华普微HOPERF4 小时前
MCU+BLE射频+丰富外设,BLE SoC如何高效传输数据?
单片机·嵌入式硬件
振南的单片机世界4 小时前
时钟开关:不用的外设,把它的时钟关掉,省电!
stm32·单片机·嵌入式硬件
金色光环4 小时前
SCPI添加错误码
stm32·scpi
iCxhust5 小时前
将8088 BootLoader分拆烧写到8086 ROM中
stm32·单片机·嵌入式硬件·51单片机·微机原理
国科安芯5 小时前
商业航天电机控制领域抗辐射 MCU 芯片应用研究
网络·单片机·嵌入式硬件·安全性测试
charlie1145141916 小时前
嵌入式C++工程实践第20篇:GPIO 输入模式内部电路 —— 芯片是如何“听“到外部信号的
开发语言·c++·stm32·单片机