stm32 串口DMA配置

一、定义串口DMA缓存

#define UART2_MAX_LENGTH 255

uint8_t aU2DmaRxBuffer[UART2_MAX_LENGTH];
uint8_t aU2DmaTxBuffer[UART2_MAX_LENGTH]; // = "1234";

二、串口基本初始化

	UartHandle[Uart2].Instance = USART2;
	UartHandle[Uart2].Init.BaudRate = bute;
	UartHandle[Uart2].Init.WordLength = mx_get_uart_databit(databit);
	UartHandle[Uart2].Init.StopBits = UART_STOPBITS_1;
	UartHandle[Uart2].Init.Parity = mx_get_uart_paritybit(parity);
	UartHandle[Uart2].Init.Mode = UART_MODE_TX_RX;
	UartHandle[Uart2].Init.HwFlowCtl = UART_HWCONTROL_NONE;
	UartHandle[Uart2].Init.OverSampling = UART_OVERSAMPLING_16;
	UartHandle[Uart2].Init.OneBitSampling = UART_ONE_BIT_SAMPLE_DISABLE;
	UartHandle[Uart2].AdvancedInit.AdvFeatureInit = UART_ADVFEATURE_NO_INIT;
	if (HAL_UART_Init(&UartHandle[Uart2]) != HAL_OK)
	{
		Error_Handler();
	}

三、打开串口空闲中断

__HAL_UART_ENABLE_IT(&UartHandle[Uart2], UART_IT_IDLE);

四、DMA初始化

找到 void HAL_UART_MspInit(UART_HandleTypeDef *uartHandle)函数,里面实现如下所示:

	__HAL_RCC_USART2_CLK_ENABLE();
#if UART2_DMA

		__HAL_RCC_DMA1_CLK_ENABLE();
#endif


		/**USART2 GPIO Configuration
		PA2     ------> USART2_TX
		PA3     ------> USART2_RX
		*/
		GPIO_InitStruct.Pin = GPIO_PIN_2 | GPIO_PIN_3;
		GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
		GPIO_InitStruct.Pull = GPIO_PULLUP;
		GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_VERY_HIGH;
		GPIO_InitStruct.Alternate = GPIO_AF4_USART2;
		HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);

#if UART2_DMA


		/*##-3- Configure the DMA ##################################################*/
		/* Configure the DMA handler for Transmission process */
		hdma_tx.Init.Direction = DMA_MEMORY_TO_PERIPH;
		hdma_tx.Instance = DMA1_Channel4;
		hdma_tx.Init.PeriphInc = DMA_PINC_DISABLE;
		hdma_tx.Init.MemInc = DMA_MINC_ENABLE;
		hdma_tx.Init.PeriphDataAlignment = DMA_PDATAALIGN_BYTE;
		hdma_tx.Init.MemDataAlignment = DMA_MDATAALIGN_BYTE;
		hdma_tx.Init.Mode = DMA_NORMAL;
		hdma_tx.Init.Priority = DMA_PRIORITY_LOW;
		hdma_tx.Init.Request = DMA_REQUEST_4;
		hdma_tx.State = HAL_DMA_STATE_READY;
		if (HAL_DMA_Init(&hdma_tx) != HAL_OK)
		{
			Error_Handler();
		}
		/* Associate the initialized DMA handle to the UART handle */
		__HAL_LINKDMA(uartHandle, hdmatx, hdma_tx);
		hdma_rx.Instance = DMA1_Channel5;
		hdma_rx.Init.Direction = DMA_PERIPH_TO_MEMORY;
		hdma_rx.Init.PeriphInc = DMA_PINC_DISABLE;
		hdma_rx.Init.MemInc = DMA_MINC_ENABLE;
		hdma_rx.Init.PeriphDataAlignment = DMA_PDATAALIGN_BYTE;
		hdma_rx.Init.MemDataAlignment = DMA_MDATAALIGN_BYTE;
		hdma_rx.Init.Mode = DMA_NORMAL;
		hdma_rx.Init.Priority = DMA_PRIORITY_HIGH;
		hdma_rx.Init.Request = DMA_REQUEST_4;
		if (HAL_DMA_Init(&hdma_rx) != HAL_OK)
		{
			Error_Handler();
		}

		/* Associate the initialized DMA handle to the the UART handle */
		__HAL_LINKDMA(uartHandle, hdmarx, hdma_rx);
		/* DMA interrupt init */
		HAL_NVIC_SetPriority(DMA1_Channel4_5_6_7_IRQn, 0, 1);
		HAL_NVIC_EnableIRQ(DMA1_Channel4_5_6_7_IRQn);
#endif


		/* Peripheral interrupt init */
		HAL_NVIC_SetPriority(USART2_IRQn, 0, 0);
		HAL_NVIC_EnableIRQ(USART2_IRQn);

这里注意几个地方

  1. GPIO_InitStruct.Alternate = GPIO_AF4_USART2; 这句代码对应的配置可以在Drivers\STM32L0xx_HAL_Driver\Inc\stm32l0xx_hal_gpio_ex.h文件开头的注释里面查到。
  2. hdma_tx.Init.Request = DMA_REQUEST_4;这句代码对应的request表示通道,不能搞错,错了完全不能通信。

五、中断函数

#if UART2_DMA

	if (USART2->ISR & (1 << UART_IDLE_IRQ)) // 串口空闲中断
	{

		ret = UART2_MAX_LENGTH - __HAL_DMA_GET_COUNTER(UartHandle[Uart2].hdmarx); // 接收到数据的长度
		dbg_printhex("Uart2RecvBuf\r\n",aU2DmaRxBuffer,128);
		if (ret > 0)
		{
			TypeFunc.StrCpy(Uart2RecvBuf, aU2DmaRxBuffer, ret);
			Uart2RecvBufLength = ret;
			uart_recv_timer[Uart2] = 5;
		}
		__HAL_UART_CLEAR_FLAG(&UartHandle[Uart2], UART_CLEAR_IDLEF);
		// 处理DMA 数据
	}
#else

注意:UART_CLEAR_IDLEF 不是UART_IT_IDLE;

如果这篇文章对您很有帮助,不妨
----- 本文结束 ❤ 感谢您的阅读 ----