• STM32 HAL库串口空闲中断 + DMA 收发不定长数据


    串口接收缓冲区定义

    usart.h

    #define BUFFER_SIZE 64
    
    typedef struct
    {
    	uint8_t  buff[BUFFER_SIZE];
    	uint32_t length;
    	uint32_t rx_flag;
    }uart_rx_msg;
    
    /* 串口接收消息缓冲 */
    extern uart_rx_msg rs422_rx_msg;
    extern uart_rx_msg rs485_rx_msg;
    extern uart_rx_msg rs232_rx_msg;
    

    usart.c

    /* 串口接收消息缓冲 */
    uart_rx_msg rs422_rx_msg;
    uart_rx_msg rs485_rx_msg;
    uart_rx_msg rs232_rx_msg;
    
    //在每个串口初始化函数里初始化缓冲BUF
    /* 初始化缓冲区  */
    memset(rs485_rx_msg.buff,0,BUFFER_SIZE);
    rs485_rx_msg.rx_flag = 0;
    rs485_rx_msg.length = 0;	
    
    memset(rs232_rx_msg.buff,0,BUFFER_SIZE); 
    rs232_rx_msg.length = 0;
    rs232_rx_msg.rx_flag = 0;
    
    memset(rs422_rx_msg.buff,0,BUFFER_SIZE);
    rs422_rx_msg.length = 0;
    rs422_rx_msg.rx_flag = 0;
    
    

    使能IDLE中断和DMA接收

    	//使能IDLE中断
    	__HAL_UART_ENABLE_IT(&huart1, UART_IT_IDLE); 
    	//DMA接收函数
    	HAL_UART_Receive_DMA(&huart1,rs232_rx_msg.buff,BUFFER_SIZE);
    

    空闲中断回调函数

    HAL库没有实现空闲中断回调,需自己实现,然后放到USART_IRQHandler中断函数中

    void uart_dma_isr_process(UART_HandleTypeDef *huart)
    {
    	if(huart->Instance == huart1.Instance)
    	{
    			uint32_t temp;
    			//获取IDLE标志位
    			if(__HAL_UART_GET_FLAG(&huart1,UART_FLAG_IDLE) != RESET)//idle标志被置位
    			{ 
    				__HAL_UART_CLEAR_IDLEFLAG(&huart1);//清除标志位
    				//停止DMA搬运
    				HAL_UART_DMAStop(&huart1); 
    				// 获取DMA中未传输的数据个数   
    				temp  =  __HAL_DMA_GET_COUNTER(&hdma_usart1_rx);
    				//总计数减去未传输的数据个数,得到已经接收的数据个数
    				rs232_rx_msg.length =  BUFFER_SIZE - temp; 
    				// 接受完成标志位置1	
    				rs232_rx_msg.rx_flag = 1;	
    			}
    	}
    	if(huart->Instance == huart4.Instance)
    	{
    			uint32_t temp;
    			//获取IDLE标志位
    			if(__HAL_UART_GET_FLAG(&huart4,UART_FLAG_IDLE) != RESET)//idle标志被置位
    			{ 
    				__HAL_UART_CLEAR_IDLEFLAG(&huart4);//清除标志位
    				//停止DMA搬运
    				HAL_UART_DMAStop(&huart4); 
    				// 获取DMA中未传输的数据个数   
    				temp  =  __HAL_DMA_GET_COUNTER(&hdma_uart4_rx);
    				//总计数减去未传输的数据个数,得到已经接收的数据个数
    				rs485_rx_msg.length =  BUFFER_SIZE - temp; 
    				// 接受完成标志位置1	
    				rs485_rx_msg.rx_flag = 1;	
    			}
    	}
    	if(huart->Instance == huart6.Instance)
    	{
    			uint32_t temp;
    			//获取IDLE标志位
    			if(__HAL_UART_GET_FLAG(&huart6,UART_FLAG_IDLE) != RESET)//idle标志被置位
    			{ 
    				__HAL_UART_CLEAR_IDLEFLAG(&huart6);//清除标志位
    				//停止DMA搬运
    				HAL_UART_DMAStop(&huart6); 
    				// 获取DMA中未传输的数据个数   
    				temp  =  __HAL_DMA_GET_COUNTER(&hdma_usart6_rx);
    				//总计数减去未传输的数据个数,得到已经接收的数据个数
    				rs422_rx_msg.length =  BUFFER_SIZE - temp; 
    				// 接受完成标志位置1	
    				rs422_rx_msg.rx_flag = 1;	
    			}
    	}
     }
    

    DMA收,根据标志位进行数据回显

    		if(rs422_rx_msg.rx_flag == 1)  //接收完成标志
    		{	
    //			can_send_msg(0x01,rs422_rx_msg.buff,rs422_rx_msg.length);
    //			can_send_msg(0x02,rs422_rx_msg.buff,rs422_rx_msg.length);
    			//将接收到的数据回发
    			HAL_UART_Transmit_DMA(&huart6,rs422_rx_msg.buff, rs422_rx_msg.length);
    			rs422_rx_msg.length = 0;//清除计数
    			rs422_rx_msg.rx_flag = 0;//清除接收结束标志位
    			memset(rs422_rx_msg.buff,0,rs422_rx_msg.length);
    		}
    		HAL_UART_Receive_DMA(&huart6,rs422_rx_msg.buff,BUFFER_SIZE);//重新打开DMA接收
    

    USART_IRQHandler调用回调函数

    void USART1_IRQHandler(void)
    {
      /* USER CODE BEGIN USART1_IRQn 0 */
    	uart_dma_isr_process(&huart1);
      /* USER CODE END USART1_IRQn 0 */
      HAL_UART_IRQHandler(&huart1);
      /* USER CODE BEGIN USART1_IRQn 1 */
    
      /* USER CODE END USART1_IRQn 1 */
    }
    
  • 相关阅读:
    蓝桥杯 奇偶覆盖 模拟
    基于RuoYi-Flowable-Plus的若依ruoyi-nbcio支持部门经理的审批
    Docker下安装oracle环境(以oracle_11g环境为例)
    ceph 分布式存储与部署
    关于DAG的一些零散记录
    Webpack的Tree Shaking是如何工作的以及它的作用
    终于解决VScode中python/C++打印中文全是乱码的问题了
    Bean 作用域与生命周期
    陈志泊主编《数据库原理及应用教程第4版微课版》的实验题目参考答案实验4
    【intent-filter】AndroidManifest中<intent-filter>标签的 部分作用
  • 原文地址:https://blog.csdn.net/lanzh_syf/article/details/139244857