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