STM32 串口DMA不定长接收全流程

思路:首先cubemax生成工程后,在用户代码中,使用空闲中断+手动调用HAL_UART_RxCpltCallback的方式来实现调用,然后处理完数据后清除空闲中断。

代码:

实现手动调用完成函数,因为DMA只会在接收完整后才能自动调用,比如期望400个字节,只收到100个是不会调用完成的,一个数据包长度不够就不会调用。

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_UART_RxCpltCallback(&huart1);

  /* USER CODE END USART1_IRQn 1 */
}

 开启空闲中断和DMA接收,开启空闲中断后,可以用来实现数据包接收完成就产生中断,而不是DMA全部接收完成才产生中断,也不是每个字节都产生中断

__HAL_UART_ENABLE_IT(&LOAD_UART, UART_IT_IDLE);
	while(__HAL_UART_GET_FLAG(&LOAD_UART,UART_FLAG_IDLE)==RESET)
	{}
	HAL_UART_Receive_DMA(&LOAD_UART, aucLoad_DMABuf, LOAD_DMA_SIZE);

 在这个函数里清除空闲中断标志,否则会导致中断无法退出而死机,然后通过RxXferSize -CNDTR计算出实际收到的字节数量。

void HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart)
{
    uint32_t temp;

    if (&LOAD_UART == huart)
	{
		HAL_UART_DMAStop(&LOAD_UART);

		__HAL_UART_CLEAR_IDLEFLAG(&LOAD_UART);								//清除标志位
		temp = LOAD_UART.Instance->ISR;  									//清除状态寄存器SR,读取SR寄存器可以实现清除SR寄存器的功能
		temp = LOAD_UART.Instance->RDR; 									//读取数据寄存器中的数据
		temp  = LOAD_UART.hdmarx->Instance->CNDTR;							//获取DMA中未传输的数据个数,NDTR寄存器分析见下面

		usLoad_Length = LOAD_UART.RxXferSize - temp;
		bLoad_Prase = TRUE;
	}
}

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值