STM32
直播中

费加罗

8年用户 814经验值
私信 关注
[问答]

求分享STM32_H750串口接收不定长数据及初始化进入idle中断的解决方法

求分享STM32_H750串口接收不定长数据及初始化进入idle中断的解决方法

回帖(1)

王明钊

2021-12-16 09:40:27
首先定义一些变量


uint8_t rx_len=0;  
uint8_t recv_end_flag=0;
uint8_t rx_buffer[200];


然后在串口初始化之后添加IDLE中断相关函数


__HAL_UART_ENABLE_IT(&huart1, UART_IT_IDLE);//开启IDLE中断
while(__HAL_UART_GET_FLAG(&huart1,UART_FLAG_IDLE)==RESET)
{}
HAL_UART_Receive_DMA(&huart1,rx_buffer,200);//开启DMA接收
recv_end_flag=0;


串口中断函数


void USART1_IRQHandler(void)
{
  /* USER CODE BEGIN USART1_IRQn 0 */
           uint32_t tmp_flag = 0;
    uint32_t temp;
    tmp_flag =__HAL_UART_GET_FLAG(&huart1,UART_FLAG_IDLE);
    if((tmp_flag != RESET))
    {
      __HAL_UART_CLEAR_IDLEFLAG(&huart1);             
        temp  = __HAL_DMA_GET_COUNTER(&hdma_usart1_rx);
        HAL_UART_DMAStop(&huart1);
        rx_len =  200 - temp;
        recv_end_flag = 1;               
    }
  /* USER CODE END USART1_IRQn 0 */
  HAL_UART_IRQHandler(&huart1);
  /* USER CODE BEGIN USART1_IRQn 1 */


  /* USER CODE END USART1_IRQn 1 */
}


串口中断函数中,清除中断,获取接收到的长度,置接收完成标志recv_end_flag=1
while函数中判断recv_end_flag进行处理


  while (1)
  {
    /* USER CODE END WHILE */


    /* USER CODE BEGIN 3 */
               
                                if(recv_end_flag ==1)                       
                {       
                        printf("接收到的数据长度为%drn",rx_len);
                        HAL_UART_Transmit(&huart1,rx_buffer, rx_len,200);//将接收到的数据发送出去
                        for(uint8_t i=0;i                         {
                                rx_buffer=0;//清空
                        }
                        rx_len=0;//清0
                        recv_end_flag=0;//清0
                HAL_UART_Receive_DMA(&huart1,rx_buffer,200);
                }
  }


以上完成了串口IDLE+DMA接收不定长数据
但是实际调试中发现一个问题,串口初始化完毕,使能IDLE中断,开启DMA接收,会产生一次IDLE中断,程序会进入中断处理函数,置位recv_end_flag,进入while后便会串口打印出:接收到的数据长度为0,
就是说初始化过程之后,会进入一次IDLE中断,在网上看到一篇类似文章找出了解决办法
http://news.eeworld.com.cn/mcu/2015/1029/article_23375.html
就是说UART会发送一个空闲帧,猜想初始化进入IDLE中断也许与此类似
便添加了


while(__HAL_UART_GET_FLAG(&huart1,UART_FLAG_IDLE)==RESET)
{}


或者使用延时函数进行一段延时也可以
等待IDLE标志位清0,不过,依然会进入中断,后面需要将recv_end_flag=0,这样程序可以正常的接收不定长数据,不会出现上电复位,第一次就打印接收数据长度为0。
(解决办法是:这样还是会进中断,通过recv_end_flag=0,解决第一次打印问题)


另外接收不定长数据页可以使用定时器进行不定长接收
大概流程是:串口接收到数据后,开启定时器,将接收到的数据存储起来,定时器大概定3ms左右的定时,每次进入串口中断,定时器清0 ,当完成一帧接收,不再进入中断,定时器产生中断,然后置flag值,while函数判断flag值执行相关操作(之前使用STM8弄过一次)


在使用SMT32F103和STM32F412过程中没有出现过上电复位就进入IDLE中断的现象。(猜测STM32H750_400M频率,SMT32F103_72M,H750代码执行的更快,使用__HAL_UART_GET_FLAG获取IDLE的状态,H750会出现1,而F103没有,猜测要么可能与HAL底层的库的问题,要么可能与硬件威廉希尔官方网站 有关,或者就是与空闲帧有关)
或者应该在接收之后打开空闲中断,具体没去试过。







MY_QuinTA的笔记
举报

更多回帖

×
20
完善资料,
赚取积分