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