找回密碼
 立即注冊

QQ登錄

只需一步,快速開始

搜索
查看: 1081|回復: 6
打印 上一主題 下一主題
收起左側(cè)

解析串口4接收的數(shù)據(jù)包中的一幀數(shù)據(jù)

[復制鏈接]
回帖獎勵 10 黑幣 回復本帖可獲得 1 黑幣獎勵! 每人限 1 次
跳轉(zhuǎn)到指定樓層
樓主
ID:590050 發(fā)表于 2025-1-17 20:43 | 只看該作者 回帖獎勵 |倒序瀏覽 |閱讀模式
      程序大部分是借鑒的網(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 中斷服務(wù)程序
{
        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;           //設(shè)置串口4發(fā)送為空閑
    }
        UART4_INT_ENABLE();                  //允許串口4中斷
}

數(shù)據(jù)接收后,從接收的數(shù)據(jù)包中查找以FD,FD,FD開頭的數(shù)據(jù)幀,不同的命令對應(yīng)不同的數(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ù)卻不是這個,求大神幫看一下是哪里的問題,先謝。
分享到:  QQ好友和群QQ好友和群 QQ空間QQ空間 騰訊微博騰訊微博 騰訊朋友騰訊朋友
收藏收藏 分享淘帖 頂 踩
回復

使用道具 舉報

沙發(fā)
ID:338503 發(fā)表于 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)用相應(yīng)次數(shù)才可以。
回復

使用道具 舉報

板凳
ID:338503 發(fā)表于 2025-1-18 08:16 | 只看該作者
上述讀命令程序調(diào)用1次只能讀取一個字節(jié)數(shù)據(jù),只有根據(jù)命令(0x06,0x07,0x08,0x09)的不同調(diào)用相應(yīng)次數(shù)才可以。
回復

使用道具 舉報

地板
ID:1143113 發(fā)表于 2025-1-19 11:04 | 只看該作者
有一個問題要注意,你是什么時候開始解析,建議要在解析前先判斷接收字節(jié)數(shù)夠不夠。只有字節(jié)數(shù)夠了才調(diào)用判斷。這個非常重要的。
回復

使用道具 舉報

5#
ID:161164 發(fā)表于 2025-1-19 23:27 | 只看該作者
ucRX4_Read_Cnt 是全局變量嗎?
為什么要在Uart4_Read_Cmd_Data函數(shù)開頭清零?
回復

使用道具 舉報

6#
ID:1133081 發(fā)表于 2025-1-20 08:51 | 只看該作者
首先要充分了解該自定義通訊協(xié)議,通常通訊協(xié)議的每一個字節(jié)都有其特定含義。例如:數(shù)據(jù)頭,數(shù)據(jù)長度,有效數(shù)據(jù),驗證碼,數(shù)據(jù)尾等。假設(shè)這串數(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é)束標志和緩存,為下次接收做準備。假設(shè)FD FD FD 06 01 02 03 06是固定長度,串口中斷示例:

  1. void UARTInterrupt() interrupt 4
  2. {
  3.         static uchar num=0;                //靜態(tài)計數(shù)變量
  4.         uchar i;
  5.         RI=0;                                        //接收中斷請求標志位清0
  6.         rec_buf[num]=SBUF;                //接收到的數(shù)據(jù)串保存在緩存數(shù)組
  7.         if(rec_buf[0]==0xFD)        //驗證數(shù)據(jù)頭(起始位)
  8.         {
  9.                 num++;
  10.                 if(num==3)
  11.                 {
  12.                         if((rec_buf[0]&rec_buf[1]&rec_buf[2])!=0xFD)
  13.                         {
  14.                                 for(i=0;i>7;i++)
  15.                                         rec_buf[i]=0x00;//清除緩存
  16.                         }
  17.                 }
  18.                 if(num>=8)
  19.                 {
  20.                         flag=1;                        //接收完成標志置1
  21.                         num=0;                        //計數(shù)變量清0
  22.                 }
  23.         }
  24. }
復制代碼



回復

使用道具 舉報

7#
ID:1143357 發(fā)表于 2025-1-24 12:50 | 只看該作者
你調(diào)用這個函數(shù)時switch結(jié)構(gòu)只進去了一次就出來了,而且用于計數(shù)的參數(shù)又是局部變量,再次調(diào)用計數(shù)參數(shù)又會歸零,這里可以改一下
回復

使用道具 舉報

您需要登錄后才可以回帖 登錄 | 立即注冊

本版積分規(guī)則

手機版|小黑屋|51黑電子論壇 |51黑電子論壇6群 QQ 管理員QQ:125739409;技術(shù)交流QQ群281945664

Powered by 單片機教程網(wǎng)

快速回復 返回頂部 返回列表