• 您(nín)的位置:首頁 > 新聞動態 > 技術文(wén)章

    串口數據包解析代碼分析

    2019/1/10      點擊:
    這裏以串口作為傳輸媒介,介紹下怎(zěn)樣來發送接收一個完整的數據包。過程涉及到封包與解包。設計一個良好的包傳輸機製很有利於數(shù)據傳輸的穩定性以及正確性。串口隻是一種傳輸媒介,這種包機製同時(shí)也可以(yǐ)用於(yú)SPI,I2C的總線(xiàn)下的數據傳輸。在單片機通信係統(多機通信以及PC與單片機通信)中,是很常見的問題。
    一、根據幀頭幀尾或者幀長檢測一個數據幀
    1、幀頭+數據+校驗+幀尾
    這是(shì)一個(gè)典型的方案,但是對幀頭與幀尾在設計的(de)時候都要注(zhù)意,也就是說幀頭、幀尾不能在(zài)所傳輸的數據域中出(chū)現,一旦出現可能(néng)就被誤(wù)判。如果用中斷來接收的話,程序基本可以這麽實現:
    unsigned char recstatu;//表示是否處於一個正在接收數據(jù)包的狀態
    unsigned char ccnt;      //計數
    unsigned char packerflag;//是否接收到一個完整的數據包標誌
    unsigned char rxbuf[100];//接收(shōu)數據的(de)緩衝區
    void UartHandler()
    {
           unsigned char tmpch;
           tmpch = UARTRBR;
           if(tmpch 是(shì)包頭)                          //檢測是否是包頭
          {  
                recstatu = 1;
                ccnt   = 0 ;
                packerflag = 0;
                return ;
           }
           if(tmpch是(shì)包尾)                          //檢測是否是包尾
           {
                recstatu = 0;
                packerflag = 1;                      //用於(yú)告知係統已經接收到一個完整的數據(jù)包
                return ;
           }
          if(recstatu ==1)                           //是否處於接收數(shù)據包狀態
          {
                rxbuf[ccnt++] = tmpch; 
          }
    }
    上麵也(yě)就是(shì)接收一個數據包,但是再次提醒,包頭和包尾不能在數據域中出現,一旦出現將會出現誤判。另外一(yī)個。數據的校驗算法是很必要的,在數據傳(chuán)輸中,由於受到幹擾,很難免有時出現數據錯誤,加(jiā)上校驗碼可在發現數據傳輸錯誤時,可以要求數據的另一方重新(xīn)發送,或是進行簡單的丟棄處(chù)理(lǐ)。校驗算法不一定要很複雜,普通的加和,異或,以及(jí)循環冗餘都是可以的。我上麵的接收程(chéng)序在接收(shōu)數據時,已經將包頭和包尾去掉,這些(xiē)可以根據自(zì)己的需求加上,關鍵是要理解原理。
    上述包協議出現了以下的幾種變種(zhǒng):
    1.1 幀頭+數據長度+數據(jù)+校驗值
    1.2包長+校驗(yàn)值(zhí)
    上麵(miàn)兩種其實都是知道了數據包的長度,然後根據接(jiē)收字節(jiē)的長度來(lái)判(pàn)斷一個完整的數據包。例如,定義一個數據包(bāo)的長度(dù)為256字節,那我們就可以一直接收,直到接收到(dào)256個字節,就認為是一個數據包(bāo)。但是,會不會存在問題呢?比如說從機向(xiàng)主機發送數據(jù),發送了一半,掉電,重啟,開機(jī)後繼續發送,這很明顯接收到的數據就不對(duì)了,所以此時很有必要定義一個超限時間,比如我們可以維護下麵這樣的一個結構體。
    struct  uartrd{
    char  rd[ 256];
    unsigned int timeout;
    }
    成員變量rd用來存(cún)放接收到的數據(jù)字節;成員變量timeout用來維護超(chāo)時值,這裏主要討論這個。這個數值怎麽維護呢,可以用一個定時器來維護,以可以放在普(pǔ)通的滴答中斷裏麵來維護,也可以根據(jù)係統運行一條指令(lìng)的周期,在自己的循環中來維護,給其設置(zhì)個初值,比如說100,當有第一個數據到來以後,timeout在(zài)指定的時間就會減(jiǎn)少1,減少(shǎo)到0時,就(jiù)認為超時(shí),不論是否接收到足夠的(de)數據,都應該拋棄。
    二、根據接收超(chāo)時來判斷一個數據包
    2.1  數據+校驗
    核心思想是如果在達到(dào)一(yī)定的時間沒有接受到數據,就認為數據包接收完成。modbus協議裏就(jiù)有通(tōng)過時間間隔來判斷幀結束的。具體實現是要使用一個定時器,在接收到(dào)第一個數據時候,開啟定時器,在接收到一個數據時候,就(jiù)將定時器清零,讓定時(shí)器重新開始計時,如果設(shè)定的超時時(shí)間到(dào)(超時時間長度可以設置為5個(gè)正常接收的周期),則認為在這一段時間(jiān)內沒有接受到新的數據,就認為接收到一個完(wán)整的數據(jù)包了。

    簡單的小的總結,上述幾種方法都還是較為常用的,在具體的實現上,可以根據具體的實際情況,設計出具體的通訊協(xié)議。數據校驗位,有時候感覺不出來其重要性,但是一定要加上,對數據進行一個相關的驗證還(hái)是必(bì)要的。現在很在MCU都帶有FIFO,DMA等功能,所以有時候(hòu)利用上這些特性,可(kě)以設計出更好的通訊方(fāng)式。有的人問在接受串(chuàn)口數據時候是應該中斷一次接收一個,還是進入(rù)中斷後(hòu)接收一段數據呢,我(wǒ)認(rèn)為應該中斷接收一個,因為CPU是(shì)很快(kuài)的,至少對於串口是這樣,在接受每個數據的間隔期間,處理器還是可以做些其他工作的。這是在裸機下的模(mó)型。在多線程中,那就可以直接建立一個數據接收線程。


    网站地图 正能量网-传播正能量弘扬主旋律-免费正能量网站www正能量-免费正能量网站www正能量下载在线观看官网