基于stm32cube的stm32系列不定长度串口接收(IDLE接收)

来源:互联网 发布:各国历年gdp数据 编辑:程序博客网 时间:2024/06/05 04:48

串口接收的数据如果是符合一定的协议帧就比较好处理,比如说遍历帧头,寻找帧长,遍历帧尾,最后取出一帧数据,但是如果是不定长度的一帧数据,需要完整的接收处理一般使用的方法是这样的:在串口有中断接收的时候重置一个在定时器中累加的值,主循环等到这个数值到达一定高度后(一段时间没新数据接收),就处理这帧数据。程序流程大楷如下:

1串口中断:

void USART1_IRQHandler(void){      unsigned char temp=0;      if(USART_GetITStatus(USART1,USART_IT_RXNE)!=RESET){          temp=USART_ReceiveData(USART1);//读完即自动清除RXNE          if(data_wifi_ble_frame.Receivelength[WIFI_position]<rxBufferSize){            data_wifi_ble_frame.ReceiveFlag[WIFI_position]=1;            data_wifi_ble_frame.ReceiveData[WIFI_position][data_wifi_ble_frame.Receivelength[WIFI_position]]=temp;            data_wifi_ble_frame.Receivelength[WIFI_position]++;        }

2 TIMER中断

void TIM3_IRQHandler(void){    TIM_ClearITPendingBit(TIM3, TIM_IT_Update);    if(data_wifi_ble_frame.ReceiveFlag[WIFI_position]>0){        data_wifi_ble_frame.ReceiveFlag[WIFI_position]++;    } }
3 主循环:

while(1){    if(data_wifi_ble_frame.ReceiveFlag[WIFI_position]>3){        data_wifi_ble_frame.ReceiveFlag[WIFI_position]=0;//处理数据帧        } 

第一种方法虽然可以处理一帧完整的数据,但是如果接收的数据速度太快,中间间隔太短,会不好处理数据帧。

下面介绍另一种方法:使用空闲帧接收不定长数据帧。


1 选择stm32cube的串口,开启中断:

2 生成的代码中开启中断接收,使能空闲中断

  if(HAL_UART_Receive_IT(&huart1,frame.ReceiveUsart1Data,128)!=HAL_OK)Error_Handler();  __HAL_UART_ENABLE_IT(&huart1, UART_IT_IDLE); 
3 在中断函数中加入判断语句,是否完成一帧数据接收;

 HAL_UART_IRQHandler(&huart2);  /* USER CODE BEGIN USART2_IRQn 1 */    frame.ReceiveUsart2length++;    if( __HAL_UART_GET_FLAG(&huart2, UART_FLAG_IDLE)){        __HAL_UART_FLUSH_DRREGISTER(&huart2);         frame.ReceiveUsart2Flag=1;  }
4 在主函数中处理数据:

    if(LORASemHandle!=NULL){          err=xSemaphoreTake(LORASemHandle,portMAX_DELAY);           if(err==pdTRUE){              printf(" FatFs is working well!!!\r\n");              }            }
5 经过测试,数据能够完整接收 ;




注意事项 :
1,开启串口中断中有一个参数是设置接收多少数据后停止接收的,你可以在 HAL_UART_IRQHandler 中的 UART_Receive_IT 里面 把这段代码屏蔽掉;

 if(--huart->RxXferCount == 0U)    {      /* Disable the UART Parity Error Interrupt and RXNE interrupt*/      CLEAR_BIT(huart->Instance->CR1, (USART_CR1_RXNEIE | USART_CR1_PEIE));      /* Disable the UART Error Interrupt: (Frame error, noise error, overrun error) */      CLEAR_BIT(huart->Instance->CR3, USART_CR3_EIE);      /* Rx process is completed, restore huart->RxState to Ready */      huart->RxState = HAL_UART_STATE_READY;           HAL_UART_RxCpltCallback(huart);      return HAL_OK;    }

下面补充个小技巧 使用printf 输出数据。在代码前面加上这段代码,现在使用的是串口1,可以修改映射到初始化的串口;

#ifdef __GNUC__   #define PUTCHAR_PROTOTYPE int __io_putchar(int ch)#else  #define PUTCHAR_PROTOTYPE int fputc(int ch, FILE *f)#endif PUTCHAR_PROTOTYPE{   // HAL_UART_Transmit_DMA(&huart1, (uint8_t *)&ch,1);   HAL_UART_Transmit(&huart1, (uint8_t *)(&(ch)), 1, 10);  return ch;}

0 0
原创粉丝点击