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