当串口需要接收到大量的数据,我们可以采用usart+dma+idel中断的方式来处理数据
因为要使用串口中断需要先在串口初始化中使能中断
/* USER CODE BEGIN USART1_Init 2 */
__HAL_UART_ENABLE_IT(&huart1,UART_IT_IDLE);
/* USER CODE END USART1_Init 2 */
定义接收缓冲区
/* USER CODE BEGIN 0 */
uint8_t Rxbuff[Rbuffsize]={0};
uint16_t Rxnum ;
/* USER CODE END 0 */
/* USER CODE BEGIN Private defines */
#define Rbuffsize 256
extern uint8_t Rxbuff[Rbuffsize];
extern uint16_t Rxnum;
/* USER CODE END Private defines */
操作中断服务函数
void USART1_IRQHandler(void)
{
/* USER CODE BEGIN USART1_IRQn 0 */
if(__HAL_UART_GET_FLAG(&huart1,UART_FLAG_IDLE)==SET)
{
__HAL_UART_CLEAR_IDLEFLAG(&huart1);
HAL_UART_DMAStop(&huart1);
Rxnum=Rbuffsize-__HAL_DMA_GET_COUNTER(&hdma_usart1_rx);
HAL_UART_Transmit_DMA(&huart1,Rxbuff,Rxnum);
}
/* USER CODE END USART1_IRQn 0 */
HAL_UART_IRQHandler(&huart1);
/* USER CODE BEGIN USART1_IRQn 1 */
/* USER CODE END USART1_IRQn 1 */
}
判断是否是空闲中断
清楚标志位
停止dma
计算传输字节数
传输剩余字节
因为没有设置临时缓冲区,所以要在中断完成回调函数中重新使能Dma
void HAL_UART_TxCpltCallback(UART_HandleTypeDef *huart){
if(huart->Instance==USART1)
{
Rxnum=0;
memset(Rxbuff,0,Rbuffsize);
HAL_UART_Receive_DMA(&huart1,Rxbuff,Rbuffsize);
}
}
另外要清空数组和传输字节数。
编译完成。
传输正常。刚开始调试的时候有错误,一直不停的收到数据,查bug发现是DMA模式都设成循环了,在这里usart_tx应该是normal模式,不然就会一直收到消息。
思考:如何设置临时缓冲区处理
能否用循环队列处理
能否在dma传输完成callback函数重新使能dma传输
只是在中断服务函数中设置标志位, 在callback函数中操作数据是否可以。
学习笔记,有歧义的地方,感谢指出
标签:idel,dma,CODE,HAL,usart,UART,huart1,USER,USART1 From: https://blog.csdn.net/qq_61556106/article/details/144634031