一、在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);
}