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