欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

单片机接收一帧数据被分成几包发送的方法

程序员文章站 2024-03-26 08:12:29
...

在工作中发现,有的设备串口会出现这种问题:一帧数据也就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;
		  }
		}  
  } 
}