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