STM32 串口UART DMA Idol 接收调试记录
背景
在使用STM32CubeMX配置串口DMA+IDLE中断接收不定长度数据时,发现只有在main函数调用HAL_UARTEx_ReceiveToIdle_DMA()时执行一次,在中断回调函数中再次开启DMA时,发现huart- rxstate = 0x22 (HAL_UART_STATE_BUSY_RX),RX一直处于Busy状态,无法再次开启DMA接收。
最开始代码如下:
- 在main函数中启动DMA接收
c
int main(void)
{
/* USER CODE BEGIN 1 */
/* USER CODE END 1 */
/* MCU Configuration--------------------------------------------------------*/
/* Reset of all peripherals, Initializes the Flash interface and the Systick. */
HAL_Init();
/* USER CODE BEGIN Init */
/* USER CODE END Init */
/* Configure the system clock */
SystemClock_Config();
/* USER CODE BEGIN SysInit */
/* USER CODE END SysInit */
/* Initialize all configured peripherals */
MX_GPIO_Init();
MX_DMA_Init();
MX_USART2_UART_Init();
/* USER CODE BEGIN 2 */
printf("Motor ready.\r\n");
HAL_UARTEx_ReceiveToIdle_DMA(&huart2, (uint8_t *)rcv_buff, sizeof(rcv_buff));
delay_ms(500);
/* USER CODE END 2 */
/* Infinite loop */
/* USER CODE BEGIN WHILE */
while (1)
{
HAL_GPIO_TogglePin(LED_GPIO_Port, LED_Pin);
// HAL_UART_Transmit_DMA(&huart2, s_buff, sizeof (s_buff));
// HAL_Delay(500);
delay_ms(500);
commander_run();
/* USER CODE END WHILE */
/* USER CODE BEGIN 3 */
}
/* USER CODE END 3 */
}
- 接收到IDEL信号后,在中断回调函数中重新启动DMA接收
c
void HAL_UARTEx_RxEventCallback(UART_HandleTypeDef *huart, uint16_t Size)
{
if(DEBUG_UART == 2)
{
HAL_UARTEx_ReceiveToIdle_DMA(huart, (uint8_t *)rcv_buff, sizeof(rcv_buff));
rcv_flag = 1;
}
}
解决
代码单步调试发现,中断回调函数中调用HAL_UARTEx_ReceiveToIdle_DMA()再次启动DMA时,
串口接收寄存器状态huart- rxstate = 0x22 (HAL_UART_STATE_BUSY_RX) ,一直处于busy状态。
必须先调用HAL_UART_DMAStop()关闭DMA后,huart- rxstate = 0x20(HAL_UART_STATE_READY),才能调用HAL_UARTEx_ReceiveToIdle_DMA()再次启动DMA
代码如下:
c
void HAL_UARTEx_RxEventCallback(UART_HandleTypeDef *huart, uint16_t Size)
{
// 必须关闭DMA,否则huart- rxstate = 0x22 (HAL_UART_STATE_BUSY_RX),
// 调用HAL_UARTEx_ReceiveToIdle_DMA()时,无法正常开启,还是继续上次开启的Idle DMA
HAL_UART_DMAStop(huart);
HAL_UARTEx_ReceiveToIdle_DMA(huart, (uint8_t *)rcv_buff, sizeof(rcv_buff));
}
参考: