一包數據被分拆爲多包,單片機如何接受

在工作中發現,有的設備串口會出現這種問題:一幀數據也就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;
		  }
		}  
  } 
}

 

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