• 串口(kǒu)協議以及串口(kǒu)二進(jìn)製整數據包解析

    2018/1/11      點擊:

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

    一、根據幀頭幀尾(wěi)或者幀長(zhǎng)檢測一(yī)個數據幀

    1、幀頭+數據+校驗+幀尾

    這是一個典型(xíng)的方案,但是對幀頭(tóu)與幀尾在設計的時候都要注意,也就(jiù)是(shì)說(shuō)幀頭、幀尾(wěi)不能在所傳輸的數據域中出現,一旦出現可能就被誤判。如果用中斷(duàn)來(lái)接收的話,程序基本可以(yǐ)這麽實現:

    unsigned char recstatu;//表示(shì)是否處於一個正在接收數據(jù)包的狀態

    unsigned char ccnt;      //計數

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

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

    void UartHandler()

    {

    unsigned char tmpch;

    tmpch = UARTRBR;

    if(tmpch 是包頭)                          //檢測是否是包頭

    {  

    recstatu = 1;

    ccnt   = 0 ;

    packerflag = 0;

    return ;

    }

    if(tmpch是包尾)                          //檢測(cè)是否是包尾

    {

    recstatu = 0;

    packerflag = 1;                      //用於告知係統已經接收到一個完整的數據包

    return ;

    }

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

    {

    rxbuf[ccnt++] = tmpch; 

    }

    }

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

    上述包協議(yì)出現了以下的幾種(zhǒng)變種:

    1.1 幀頭+數據長度+數據+校驗值

    1.2包長+校驗值

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

    struct  uartrd{

    char  rd[ 256];

    unsigned int timeout;

    }

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


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

    2.1  數據(jù)+校驗

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

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

    91影视免费版下载-91麻豆国产福利精品-91麻豆精品一二三区在线-国产91系列视频在线观看