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);
}
相关推荐
崇山峻岭之间3 小时前
HC32F460PETB的PB2的Vout123
单片机
恶魔泡泡糖3 小时前
stm32F103C8T6标准库串口接收之中断方式2
stm32·单片机·嵌入式硬件
充哥单片机设计3 小时前
【STM32开源项目】智能小区充电桩
stm32·单片机·嵌入式硬件·毕业设计·小区充电桩·智能小区充电桩
嵌入式-老费4 小时前
esp32开发与应用(如何解决SoC冷启动的问题)
单片机·嵌入式硬件
充哥单片机设计5 小时前
【STM32开源项目】智能语音台灯
stm32·单片机·嵌入式硬件·毕业设计·单片机设计·智能语音台灯
EatFan5 小时前
全栈自造 Status Deck(四):硬件终于到了,从点亮屏幕到跑通第一个 Demo
单片机·物联网·esp32
sunoo-2296 小时前
【嵌入式裸机开发Day04】i.MX6ULL 蜂鸣器驱动详解:从引脚地址查找到代码实现全流程
arm开发·单片机·嵌入式硬件·学习·串口·裸机
Brilliantwxx7 小时前
【STM32】 SPI阻塞式通信与HAL源码 (源码分析)
stm32·单片机·嵌入式硬件
Doraemomo7 小时前
IMX6ULL裸机开发——PWM
arm开发·嵌入式硬件·imx6ull
老当益壮梁奶奶8 小时前
ARM汇编学习笔记(五):从按键轮询到 GIC 中断控制器(ARM Cortex-A7 )
arm开发·笔记·单片机·嵌入式硬件