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);
}
相关推荐
隔壁大炮4 分钟前
PID控制结构&角度环实现直立
stm32·嵌入式·硬件·pid·平衡车·江协科技
羽获飞7 分钟前
从零开始学嵌入式之STM32——29.通用定时器-输入捕获模式测量信号的周期和频率
stm32·单片机·嵌入式硬件
421!20 分钟前
ESP32学习笔记之GPIO
开发语言·笔记·单片机·嵌入式硬件·学习·算法·fpga开发
惶了个恐26 分钟前
嵌入式硬件第二弹——51单片机(2)
单片机·嵌入式硬件·51单片机
易水寒陈37 分钟前
使用vscode开发stm32
ide·vscode·stm32
BUG_yechiyu39 分钟前
RT-Thread Nano版本使用RTC,同时解决复位日期丢失,时间并正确问题
stm32
LCG元44 分钟前
STM32实战:基于STM32CubeMX的串口通信与DMA传输优化
stm32·单片机·嵌入式硬件
heanyu1 小时前
STM32学习 1 ----串口通讯--阻塞式收发+支持printf
stm32·嵌入式硬件·学习
莎士比亚的文学花园1 小时前
硬件入门——51单片机
单片机·嵌入式硬件·51单片机
2501_918126911 小时前
学习所有6502写游戏动作的语句
汇编·嵌入式硬件·学习·游戏·个人开发