CubeMX 配置

配置串口

配置DMA

配置中断

其他配置默认即可。

 

特别注意

DMA的初始化一定要在串口初始化之前调用,否则会导致dma初始化失败。

MX_DMA_Init();
MX_USART1_UART_Init();

初始化顺序可通过工程设置调整:

 

代码修改

DMA接收

usart.c

定义dma接收数组:

uint8_t uart1RxBuf[USART1_RX_BUFFER_SIZE];
volatile uint8_t UART1_RX_len;
volatile uint8_t UART1_RX_end_flag = 0; 

修改MX_USART1_UART_Init,在初始化之后加入:

/* USER CODE BEGIN USART1_Init 2 */
HAL_UARTEx_ReceiveToIdle_DMA(&huart1, uart1RxBuf, USART1_RX_BUFFER_SIZE);
/* USER CODE END USART1_Init 2 */

usart.h

添加宏及声明:

#define USART1_RX_BUFFER_SIZE 1024
extern uint8_t uart1RxBuf[];
extern volatile uint8_t UART1_RX_len;
extern volatile uint8_t UART1_RX_end_flag; 

stm32f4xx_it.c

/* USER CODE BEGIN EV */位置增加:

/**
  * @brief This function handles UARTx Rx event.
  */
void HAL_UARTEx_RxEventCallback(UART_HandleTypeDef *huart, uint16_t Size)
{
    if(huart->Instance == USART1)
    {
        UART1_RX_len = Size;
        // 这里处理接收到的数据
        UART1_RX_end_flag = 1;
    }
}

以复写 stm32f4xx_hal_uart.c 中如下弱函数(也可以通过注册回调函数的方式实现):

在串口中断中调用:

void USART1_IRQHandler(void)
{
  /* USER CODE BEGIN USART1_IRQn 0 */
  /* USER CODE END USART1_IRQn 0 */
  HAL_UART_IRQHandler(&huart1);
  /* USER CODE BEGIN USART1_IRQn 1 */
  HAL_UARTEx_ReceiveToIdle_DMA(&huart1, uart1RxBuf, USART1_RX_BUFFER_SIZE);
  /* USER CODE END USART1_IRQn 1 */
}

DMA发送

为了便于调用,可封装一下DMA发送函数:

HAL_StatusTypeDef USART1_Transmit_DMA(const uint8_t *pData, uint16_t Size)
{
    return HAL_UART_Transmit_DMA(&huart1, pData, Size);
}