標題:
解析串口4接收的數(shù)據(jù)包中的一幀數(shù)據(jù)
[打印本頁]
作者:
hzh173
時間:
2025-1-17 20:43
標題:
解析串口4接收的數(shù)據(jù)包中的一幀數(shù)據(jù)
程序大部分是借鑒的網(wǎng)上或STC的例程,想實現(xiàn)從串口接收的數(shù)據(jù)包中,解析出一幀完整的命令。請教各位大神幫看一下程序,我用的STC單片機,串口4接收數(shù)據(jù),接收的數(shù)據(jù)存在ucRX4_Buffer【】中,最大存UART4_BUF_LENGTH個數(shù)據(jù)。中斷部分程序如下:
unsigned char ucRX4_index=0;
void Uart4_isr() interrupt 18 //UART4 中斷服務程序
{
UART4_INT_DISABLE(); //禁止串口4中斷
if(RI4) //串口4接收到數(shù)據(jù)
{
CLR_RI4(); //清除中斷4的接收標志
ucRX4_Buffer[ucRX4_index] = S4BUF; //將串口4接收到的數(shù)據(jù)放入ucRX4_Buffer[]
ucRX4_index++;
if(ucRX4_index>UART4_BUF_LENGTH) ucRX4_index=0;
}
if (TI4)
{
CLR_TI4(); //清除中斷4的發(fā)送標志
bTX4_Busy = 0; //設置串口4發(fā)送為空閑
}
UART4_INT_ENABLE(); //允許串口4中斷
}
數(shù)據(jù)接收后,從接收的數(shù)據(jù)包中查找以FD,FD,FD開頭的數(shù)據(jù)幀,不同的命令對應不同的數(shù)據(jù)長度,將查找出的數(shù)據(jù)存在ucRX4_CMD_Data_Buffer【】中,程序如下:
void Uart4_Read_Cmd_Data(void) //讀串口4接收的不同命令的數(shù)據(jù)
{
unsigned char i;
ucRX4_Read_Cnt = 0;
switch(ucRX4_Read_State)
{
case 0: //判斷頭文件
{
//從接收緩存中查找?guī)^
if(ucRX4_Buffer[ucRX4_Read_Cnt] == 0xFD) //幀頭0xFD 0xFD 0xFD
{
ucRX4_Read_Cnt++; //讀下一個數(shù)
if(++ucRX4_Head_Cnt >= 3) //頭0xFD 0xFD 0xFD
{
ucRX4_Read_State=1;
}
}
else
{
ucRX4_Read_Cnt++; //讀下一個數(shù)
ucRX4_Head_Cnt = 0;
ucRX4_Read_State = 0;
}
}
break;
case 1: //判斷命令長度,不同命令長度不同;
{
if(ucRX4_Buffer[ucRX4_Read_Cnt] == 0x06) //06命令,06后4個字節(jié),加上命令,共計5個字節(jié)
ucRX4_Recv_Data_Length=5;
else if(ucRX4_Buffer[ucRX4_Read_Cnt] == 0x07) //07命令
ucRX4_Recv_Data_Length=15;
else if(ucRX4_Buffer[ucRX4_Read_Cnt] == 0x08) //08命令
ucRX4_Recv_Data_Length=10;
else if(ucRX4_Buffer[ucRX4_Read_Cnt] == 0x09) //09命令
ucRX4_Recv_Data_Length=11;
else ucRX4_Recv_Data_Length=0;
ucRX4_Read_State=2;
}
break;
case 2: //接收數(shù)據(jù)
{
for(i=0;i<ucRX4_Recv_Data_Length;i++)
{
ucRX4_CMD_Data_Buffer[ i]=ucRX4_Buffer[ucRX4_Read_Cnt];
ucRX4_Read_Cnt++;
}
bRX4_Flag=1; //一幀數(shù)據(jù)接收完成
ucRX4_Read_State=0;
ucRX4_Head_Cnt = 0;
}break;
default:break;
}
}
在其它程序中,需要讀數(shù)據(jù)時,就調(diào)用 void Uart4_Read_Cmd_Data(void)函數(shù)。
以上程序,現(xiàn)在的問題是,總是查找出的數(shù)據(jù)總是不對,用串口助手驗證,比如發(fā)的數(shù)據(jù)包中包含了一幀數(shù)據(jù),F(xiàn)D FD FD 06 01 02 03 06,但解析出的數(shù)據(jù)卻不是這個,求大神幫看一下是哪里的問題,先謝。
作者:
gsr64
時間:
2025-1-18 08:07
你上述程序調(diào)用void Uart4_Read_Cmd_Data(void)函數(shù)1次只能讀取1個字節(jié)數(shù)據(jù),按你上述程序,要根據(jù)命令(0x06,0x07,0x08,0x09)的不同調(diào)用相應次數(shù)才可以。
作者:
gsr64
時間:
2025-1-18 08:16
上述讀命令程序調(diào)用1次只能讀取一個字節(jié)數(shù)據(jù),只有根據(jù)命令(0x06,0x07,0x08,0x09)的不同調(diào)用相應次數(shù)才可以。
作者:
llzfry
時間:
2025-1-19 11:04
有一個問題要注意,你是什么時候開始解析,建議要在解析前先判斷接收字節(jié)數(shù)夠不夠。只有字節(jié)數(shù)夠了才調(diào)用判斷。這個非常重要的。
作者:
lkc8210
時間:
2025-1-19 23:27
ucRX4_Read_Cnt 是全局變量嗎?
為什么要在Uart4_Read_Cmd_Data函數(shù)開頭清零?
作者:
WL0123
時間:
2025-1-20 08:51
首先要充分了解該自定義通訊協(xié)議,通常通訊協(xié)議的每一個字節(jié)都有其特定含義。例如:數(shù)據(jù)頭,數(shù)據(jù)長度,有效數(shù)據(jù),驗證碼,數(shù)據(jù)尾等。假設這串數(shù)據(jù)的前3個FD為數(shù)據(jù)頭,那么當串口連續(xù)收到3個FD即判斷為有真實信號到來,即持續(xù)對后續(xù)數(shù)據(jù)保存。否則清除緩存。如果數(shù)據(jù)長度固定很好辦,收完若干字節(jié)即給出結(jié)束標志。數(shù)據(jù)長度不固定,但有字節(jié)長度信息也好辦,根據(jù)長度信息確定結(jié)束接收并給出結(jié)束標志。如不含根據(jù)長度信息通常啟動定時器,若干時間收不到數(shù)據(jù)表示傳輸結(jié)束即給出結(jié)束標志。解析函數(shù)在得到結(jié)束標志后才開始解析并清除結(jié)束標志和緩存,為下次接收做準備。假設FD FD FD 06 01 02 03 06是固定長度,串口中斷示例:
void UARTInterrupt() interrupt 4
{
static uchar num=0; //靜態(tài)計數(shù)變量
uchar i;
RI=0; //接收中斷請求標志位清0
rec_buf[num]=SBUF; //接收到的數(shù)據(jù)串保存在緩存數(shù)組
if(rec_buf[0]==0xFD) //驗證數(shù)據(jù)頭(起始位)
{
num++;
if(num==3)
{
if((rec_buf[0]&rec_buf[1]&rec_buf[2])!=0xFD)
{
for(i=0;i>7;i++)
rec_buf[i]=0x00;//清除緩存
}
}
if(num>=8)
{
flag=1; //接收完成標志置1
num=0; //計數(shù)變量清0
}
}
}
復制代碼
作者:
Celika
時間:
2025-1-24 12:50
你調(diào)用這個函數(shù)時switch結(jié)構(gòu)只進去了一次就出來了,而且用于計數(shù)的參數(shù)又是局部變量,再次調(diào)用計數(shù)參數(shù)又會歸零,這里可以改一下
歡迎光臨 (http://www.torrancerestoration.com/bbs/)
Powered by Discuz! X3.1