• 串口協議以及串口二進製整數據包解析

    2018/1/11      點擊:

    以串口作(zuò)為傳輸媒介,介紹下(xià)怎樣來發送接收一個完(wán)整的數(shù)據包。過程涉及到封包與(yǔ)解包。設計一個良好的包傳輸機製很有利於數據傳輸的穩(wěn)定性以及正確性。串口隻是一種傳輸媒介,這種包機製同(tóng)時也可以用於SPI,I2C的(de)總線下的數(shù)據傳(chuán)輸。在單片機通信(xìn)係統(多機通信以及PC與單片機通信)中,是很常見的問題。

    一(yī)、根(gēn)據幀頭幀尾或者幀長檢測一個數據幀

    1、幀頭(tóu)+數據+校驗+幀尾

    這是一個典型的方案,但是對幀頭與(yǔ)幀尾在設計的時候都要注意,也就是說幀頭、幀尾不(bú)能在所傳輸的數據域中出現,一旦出現可能就被誤判。如果(guǒ)用中斷來接收的話,程序基本可以這麽實(shí)現:

    unsigned char recstatu;//表示是否處於一(yī)個正在(zài)接收(shōu)數據包的狀態

    unsigned char ccnt;      //計數

    unsigned char packerflag;//是否接收到一個完整的數據包標誌(zhì)

    unsigned char rxbuf[100];//接收數據的緩衝區

    void UartHandler()

    {

    unsigned char tmpch;

    tmpch = UARTRBR;

    if(tmpch 是包頭(tóu))                          //檢測是否是包(bāo)頭(tóu)

    {  

    recstatu = 1;

    ccnt   = 0 ;

    packerflag = 0;

    return ;

    }

    if(tmpch是包尾)                          //檢(jiǎn)測是否是包(bāo)尾

    {

    recstatu = 0;

    packerflag = 1;                      //用於告(gào)知係統已經接(jiē)收到一個完整(zhěng)的數據包

    return ;

    }

    if(recstatu ==1)                           //是否處於接收數據包狀態

    {

    rxbuf[ccnt++] = tmpch; 

    }

    }

    上麵也就是接收一個數據包,但是再次提醒,包頭和包(bāo)尾不能(néng)在(zài)數據(jù)域中出現,一旦出現將會出現誤判。另外一個。數據的校驗算法是很必要的,在數據傳輸中,由於受到幹擾,很難免有時出現數據錯誤,加上校驗碼可在(zài)發現數據傳輸(shū)錯誤時,可以要求數據的另一方重新發送,或是進行簡單的丟棄處理。校驗算法(fǎ)不一定要很複雜(zá),普通的加和,異或,以及循環冗餘都是可(kě)以的。我上麵的接收程(chéng)序在接收(shōu)數據時,已經將包頭和包尾去掉,這些可以(yǐ)根據自(zì)己的需求加上(shàng),關鍵是要理解原理。

    上述包協議出現(xiàn)了以(yǐ)下(xià)的幾種變種:

    1.1 幀頭(tóu)+數據長度(dù)+數據+校驗值

    1.2包長+校驗值

    上(shàng)麵兩種其實都是知道了數據包的長度,然後根據接(jiē)收字節(jiē)的長度來判斷一個完整的數據包。例如,定義一個數據包(bāo)的長度為256字(zì)節,那我們就(jiù)可以(yǐ)一直接收,直到接收到256個字節,就認(rèn)為是(shì)一個數據包。但(dàn)是,會不會存在問題呢?比如(rú)說從機向主機(jī)發送(sòng)數(shù)據,發送了一半,掉電,重啟,開(kāi)機後繼續發送,這很明顯(xiǎn)接(jiē)收到的數據就不對了,所以此時很有必要定(dìng)義一個超限時間,比如我們可以維護(hù)下麵(miàn)這樣的一個結(jié)構體。

    struct  uartrd{

    char  rd[ 256];

    unsigned int timeout;

    }

    成員變量rd用來存放接收到的數據字節;成員變量timeout用來維(wéi)護超時值,這(zhè)裏主(zhǔ)要討論這個。這個數值怎麽維護呢,可以用(yòng)一個定時器來維護,以可以放在普通的(de)滴答中斷裏麵來(lái)維護(hù),也(yě)可以根據係統運行一條指令的周期,在自己的循環中來維護,給其設置個初值,比如說100,當有第(dì)一個數據到來以後,timeout在指定的時間就會減少1,減少到0時,就認為超時,不論是否接收到足夠的數據,都應該拋棄。


    二、根據接收超時(shí)來判(pàn)斷一個數據(jù)包

    2.1  數據+校驗

    核心思想是如果在達到一定的時間沒有接受到數據,就認為(wéi)數據(jù)包接收完成。modbus協議裏就有通(tōng)過時間間隔來判(pàn)斷幀結束的。具體實現是要使用一個定時器,在接收到第一個數據時(shí)候,開啟定時器,在接收到一個數據時候,就將定時器清零(líng),讓定時器重新開始計時,如(rú)果設定的超時時間(jiān)到(超(chāo)時時間長度可以設(shè)置為5個正常接收的周期(qī)),則認為在這一段時間內沒有接受到新的數據,就認為接(jiē)收到一個完整的數(shù)據包了。

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

    AV永久天堂网_奇米狠狠色_亚洲欧美日韩动漫_欧美日韩视频在线观看免费一区二区_日韩精品一二三区_国产AV网站18禁止人_久久久久久精品人妻免费网站不卡_国产最新视频_另类免费视频在线视频二区_久久精品免视国产