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