一包数据被分拆为多包,单片机如何接受

在工作中发现,有的设备串口会出现这种问题:一帧数据也就10个字节,却被随意的分成好几包数据进行发送。这种数据单片机该如何接受数据呢?

1、编写固定格式的通信协议。通信协议中应该带有固定的帧头、帧尾。如果协议携带的数据区有可能会出现与帧头和帧尾相同的字节,必须将该字节进行转义,而且还要在协议中数据长度,方便接收端判断。

2、如果协议中对上面的内容包含不完整,则可以通过设定接收数据超时来判断是否接收完一帧完整的数据。

(1)串口初始化配置函数

/***************************************************************************
 **@USART3的功能设置,用于串口通讯
****************************************************************************/
/***************************************************
**函数名称:USART3_Configuration
**函数共能:初始换USART3串口功能
**输入变量:无
**输出变量:无
****************************************************/
void USART3_Configuration(void)
{
    GPIO_InitTypeDef GPIO_InitStructure;
	USART_InitTypeDef USART_InitStructure;
	USART_ClockInitTypeDef  USART_ClockInitStructure;

	/* Configure USART3 Tx (PB.10) as alternate function push-pull */
  	GPIO_InitStructure.GPIO_Pin = GPIO_Pin_10;
  	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;
  	GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
  	GPIO_Init(GPIOB, &GPIO_InitStructure); 
    
  	/* Configure USART3 Rx (PB.11) as input floating */
  	GPIO_InitStructure.GPIO_Pin = GPIO_Pin_11;
  	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;
  	GPIO_Init(GPIOB, &GPIO_InitStructure); 

	#if 1 
    USART_ClockInitStructure.USART_Clock = USART_Clock_Disable; 
    USART_ClockInitStructure.USART_CPOL = USART_CPOL_Low; 
    USART_ClockInitStructure.USART_CPHA = USART_CPHA_2Edge; 
    USART_ClockInitStructure.USART_LastBit = USART_LastBit_Disable; 
 
    USART_ClockInit(USART3, &USART_ClockInitStructure); 
    #endif 
	USART_InitStructure.USART_BaudRate            = 115200  ;
	USART_InitStructure.USART_WordLength          = USART_WordLength_8b;
	USART_InitStructure.USART_StopBits            = USART_StopBits_1;
	USART_InitStructure.USART_Parity              = USART_Parity_No ;
	USART_InitStructure.USART_HardwareFlowControl = USART_HardwareFlowControl_None;
	USART_InitStructure.USART_Mode                = USART_Mode_Rx | USART_Mode_Tx;
	USART_Init(USART3, &USART_InitStructure);
//	USART_ITConfig(USART3, USART_IT_RXNE, DISABLE);
	USART_ITConfig(USART3, USART_IT_RXNE, ENABLE); //20190703
//	USART_ITConfig(USART3, USART_IT_IDLE, ENABLE); //20190705
	USART_Cmd(USART3, ENABLE);  
		 
}

(2)协议只有帧头,没有帧尾 接收中断函数

void USART3_IRQHandler(void)  
{ 
	u8 c,clear;
	if(USART_GetITStatus(USART3, USART_IT_RXNE) != RESET)
	{	
	  clear=USART_ReceiveData(USART3);
		if(Start_Rec==0 && clear=='5')
		{
			tcounter=0;
			Counter_USART++;
	   	Start_Rec=1;
			Buf_USART3[0]=clear;//(u8)(clear);		
		}
		else if(Start_Rec==1 && clear=='5')
		{
			tcounter=0;
		  Counter_USART++;
	   	Start_Rec=2;
			Buf_USART3[1]=clear;//(u8)(clear);	
		}
		else if(Start_Rec==2 && clear=='a')
		{
			tcounter=0;
		  Counter_USART++;
	   	Start_Rec=3;
			Buf_USART3[2]=clear;//(u8)(clear);	
		}
		else if(Start_Rec==3 && clear=='a')
		{
			tcounter=0;
		  Counter_USART++;
	   	Start_Rec=4;
			Buf_USART3[3]=clear;//(u8)(clear);	
		}
		else if(Start_Rec==4)
		{
			tcounter=0;
		  Buf_USART3[Counter_USART++]=clear;//(u8)(clear);	
		}
		else 
		{
			 Start_Rec=0;
			 Counter_USART=0;
			 memset( Buf_USART3, 0, 40);
		}
		if(Counter_USART>34)
		{
			 Start_Rec=0;
			 Counter_USART=0;
			 memset( Buf_USART3, 0, 40);
		}
	}

(3)定时器初始化函数


/******************************************************************
函数名称:TIM5_Init
输入参数:无
输出参数:无
函数功能:设置定时中断	0.5s 定时器时间T=(TIM_Period+1)*(TIM_Prescaler+1)/TIMxCLK  1
实际测试大概3mS中断一次 20190807
******************************************************************/
void TIM5_Init(void)
{
  TIM_TimeBaseInitTypeDef  TIM_TimeBaseStructure;

  RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM5, ENABLE);
  
  TIM_TimeBaseStructure.TIM_Period = 9;//3599; //(10000 - 1);
  // 这个就是预分频系数,当由于为0时表示不分频所以要减1
  TIM_TimeBaseStructure.TIM_Prescaler =36000-1;// 499;
  // 使用的采样频率之间的分频比例
  TIM_TimeBaseStructure.TIM_ClockDivision = 0;
  //向上计数
  TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up;
  //初始化定时器
  TIM_TimeBaseInit(TIM5, &TIM_TimeBaseStructure);

  /* Clear TIM5 update pending flag[清除TIM5溢出中断标志] */
  TIM_ClearITPendingBit(TIM5, TIM_IT_Update);

  //打开溢出中断
  TIM_ITConfig(TIM5, TIM_IT_Update, ENABLE);

  TIM_Cmd(TIM5, ENABLE);  //计数器使能,开始工作20170520
}

(4)定时器中断函数

void TIM5_IRQHandler(void)
{
	if (TIM_GetITStatus(TIM5, TIM_IT_Update) != RESET)
  {
        TIM_ClearITPendingBit(TIM5, TIM_IT_Update);
		tcounter++;
	    if(Start_Rec)
		{
		  if(tcounter>=3)
		  {
			    Start_Rec=0;
				Finish_Rec=1;
				Counter_USART=0;
		  }
		}  
  } 
}

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章