• 您的位置:首頁 > 新聞動態 > 技術文章

    串口數據包解析代碼(mǎ)分析

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

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


    自愉色色,亚洲色孩,jk无遮拦,日日夜夜7799天天综合,999夜夜,7799天天综合天天综合网精品视频,日日夜夜精品视频7799,天天综合7799精品影视