這裡以串列埠作為傳輸媒介,介紹下怎樣來傳送接收乙個完整的資料報。過程涉及到封包與解包。設計乙個良好的包傳輸機制很有利於資料傳輸的穩定性以及正確性。串列埠只是一種傳輸媒介,這種包機制同時也可以用於spi,i2c的匯流排下的資料傳輸。在微控制器通訊系統(多機通訊以及pc與微控制器通訊)中,是很常見的問題。
一、根據幀頭幀尾或者幀長檢測乙個資料幀
1、幀頭+資料+校驗+幀尾
這是乙個典型的方案,但是對幀頭與幀尾在設計的時候都要注意,也就是說幀頭、幀尾不能在所傳輸的資料域中出現,一旦出現可能就被誤判。如果用中斷來接收的話,程式基本可以這麼實現:
unsigned char recstatu;//表示是否處於乙個正在接收資料報的狀態
unsigned char ccnt; //計數
unsigned char packerflag;//是否接收到乙個完整的資料報標誌
unsigned char rxbuf[100];//接收資料的緩衝區
void uarthandler()
if(tmpch是包尾) //檢測是否是包尾
if(recstatu ==1) //是否處於接收資料報狀態
}上面也就是接收乙個資料報,但是再次提醒,包頭和包尾不能在資料域中出現,一旦出現將會出現誤判。另外乙個。資料的校驗演算法是很必要的,在資料傳輸中,由於受到干擾,很難免有時出現資料錯誤,加上校驗碼可在發現資料傳輸錯誤時,可以要求資料的另一方重新傳送,或是進行簡單的丟棄處理。校驗演算法不一定要很複雜,普通的加和,異或,以及迴圈冗餘都是可以的。我上面的接收程式在接收資料時,已經將包頭和包尾去掉,這些可以根據自己的需求加上,關鍵是要理解原理。
上述包協議出現了以下的幾種變種:
1.1 幀頭+資料長度+資料+校驗值
1.2包長+校驗值
上面兩種其實都是知道了資料報的長度,然後根據接收位元組的長度來判斷乙個完整的資料報。例如,定義乙個資料報的長度為256位元組,那我們就可以一直接收,直到接收到256個位元組,就認為是乙個資料報。但是,會不會存在問題呢?比如說從機向主機傳送資料,傳送了一半,掉電,重啟,開機後繼續傳送,這很明顯接收到的資料就不對了,所以此時很有必要定義乙個超限時間,比如我們可以維護下面這樣的乙個結構體。
struct uartrd
成員變數rd用來存放接收到的資料位元組;成員變數timeout用來維護超時值,這裡主要討論這個。這個數值怎麼維護呢,可以用乙個定時器來維護,以可以放在普通的滴答中斷裡面來維護,也可以根據系統執行一條指令的週期,在自己的迴圈中來維護,給其設定個初值,比如說100,當有第乙個資料到來以後,timeout在指定的時間就會減少1,減少到0時,就認為超時,不論是否接收到足夠的資料,都應該拋棄。
二、根據接收超時來判斷乙個資料報
2.1 資料+校驗
核心思想是如果在達到一定的時間沒有接受到資料,就認為資料報接收完成。modbus協議裡就有通過時間間隔來判斷幀結束的。具體實現是要使用乙個定時器,在接收到第乙個資料時候,開啟定時器,在接收到乙個資料時候,就將定時器清零,讓定時器重新開始計時,如果設定的超時時間到(超時時間長度可以設定為5個正常接收的週期),則認為在這一段時間內沒有接受到新的資料,就認為接收到乙個完整的資料報了。流程大體如下圖所示:
進行乙個簡單的小的總結,上述幾種方法都還是較為常用的,在具體的實現上,可以根據具體的實際情況,設計出具體的通訊協議。資料校驗位,有時候感覺不出來其重要性,但是一定要加上,對資料進行乙個相關的驗證還是必要的。現在很在mcu都帶有fifo,dma等功能,所以有時候利用上這些特性,可以設計出更好的通訊方式。有的人問在接受串列埠資料時候是應該中斷一次接收乙個,還是進入中斷後接收一段資料呢,我認為應該中斷接收乙個,因為cpu是很快的,至少對於串列埠是這樣,在接受每個資料的間隔期間,處理器還是可以做些其他工作的。這是在裸機下的模型。在多執行緒中,那就可以直接建立乙個資料接收執行緒。
1、根據幀頭幀尾檢測乙個資料幀
1).幀頭+資料+校驗+幀尾
這是乙個典型的資料接收方案,但是需要注意幀頭幀尾的設計,意思是幀頭幀尾不能出現與傳輸的資料內容相同,一旦出現可能會被誤判。以下為中斷接收的基本程式:
[cpp]
view plain
copy
unsigned
char
flagpacker;
//全域性變數 是否完整接收乙個資料報
unsigned char
rxpacker[255];
//全域性變數 完整資料報
#pragma vector = urx0_vector
__interrupt void
uart0_isr(
void
)
if(rxbuf == (自定義幀尾))
flagpacker = 1;//告訴系統已接收乙個完整的資料報
return
; }
if(rec)
//判斷是否處於接收狀態
} 2、根據幀頭資料長度檢測乙個資料幀
1).幀頭+資料長度+資料+校驗
這也是乙個典型的資料接收方案,但是需要注意幀頭的設計,意思是幀頭不能出現與傳輸的資料內容相同,一旦出現可能會被誤判。以下為中斷接收的基本程式:
[cpp]
view plain
copy
unsigned
char
flagpacker;
//全域性變數 是否完整接收乙個資料報
unsigned char
rxpacker[255];
//全域性變數 完整資料報
#pragma vector = urx0_vector
__interrupt void
uart0_isr(
void
)
if(rec)
rec = 0;
flagpacker = 1;
} }
}
串列埠中怎樣接收乙個完整資料報的解析
這裡以串列埠作為傳輸媒介,介紹下怎樣來傳送接收乙個完整的資料報。過程涉及到封包與解包。設計乙個良好的包傳輸機制很有利於資料傳輸的穩定性以及正確性。串列埠只是一種傳輸媒介,這種包機制同時也可以用於spi,i2c的匯流排下的資料傳輸。在微控制器通訊系統 多機通訊以及pc與微控制器通訊 中,是很常見的問題...
串列埠中怎樣接收乙個完整資料報的解析
這裡以串列埠作為傳輸媒介,介紹下怎樣來傳送接收乙個完整的資料報。過程涉及到封包與解包。設計乙個良好的包傳輸機制很有利於資料傳輸的穩定性以及正確性。串列埠只是一種傳輸媒介,這種包機制同時也可以用於spi,i2c的匯流排下的資料傳輸。在微控制器通訊系統 多機通訊以及pc與微控制器通訊 中,是很常見的問題...
串列埠中怎樣接收乙個完整資料報的解析
這裡以串列埠作為傳輸媒介,介紹下怎樣來傳送接收乙個完整的資料報。過程涉及到封包與解包。設計乙個良好的包傳輸機制很有利於資料傳輸的穩定性以及正確性。串列埠只是一種傳輸媒介,這種包機制同時也可以用於spi,i2c的匯流排下的資料傳輸。在微控制器通訊系統 多機通訊以及pc與微控制器通訊 中,是很常見的問題...