大端模式,是指數據的高字節保存在內存的低地址中,而數據的低字節保存在內存的高地址中,這樣的存儲模式有點兒類似於把數據當作字符串順序處理:地址由小向大增加,而數據從高位往低位放;
小端模式,是指數據的高字節保存在內存的高地址中,而數據的低字節保存在內存的低地址中,這種存儲模式將地址的高低和數據位權有效地結合起來,高地址部分權值高,低地址部分權值低,和我們的邏輯方法一致。
data0 |
Data1 |
Data2 |
Data3 |
Data4 |
Data5 |
Data6 |
Data7 |
Data8 |
Data9 |
幀頭 |
指令 |
參數 |
CRC校驗碼 |
||||||
0xaabb |
0x0001 |
0x01 |
0x02 |
0x1234 |
|
如上指令協議,我在解讀時會按照大端模式理解,
即數據發送的順序爲:aabb 0001 0102 1234 crc
爲了處理方便,構建如下結構體:
typedef struct
{
u16 frame_head;
u16 module_cmd;
u8 cmd_data4;
u8 cmd_data5;
u16 cmd_data67;
u16 crc_data;
}ProtocolType;
但我用的stm32f4系列爲小端模式,這麼構建結構體會帶來一些問題:
問題1: 不能使用memcpy函數向結構體中複製數據,如果直接複製,frame_head中存儲的數據爲0xbbaa,這是大小端模式導致的。
問題2:crc碼的計算,正如問題1所述,若要爲計算crc16建立一個u16的數組,需要將源數據按字節取出,按照小端模式組合,再賦值到數組中:
for(;word_len < (len>>1) ;word_len++)
{
rec_cmd_buff[word_len] = ((u16)p_data[(word_len<<1)]<<8)+p_data[(word_len<<1)+1];
}
問題3:按照問題2的處理方法,我們可以很容易計算數據的crc碼,並校驗,而且還可以直接把這個數組複製到問題1設想的結構體中,但又會出現新的問題:結構體中的cmd_data4並非是0x01,而是0x02,這是因爲單字節數據本身不受大小端存儲方式的影響,但在問題2中,我們強行把cmd_data4,cmd_data5合併爲了u16類型數據,導致兩個數據顛倒了位置,所以要想正常使用ProtocolType結構體,可以把cmd_data4,cmd_data5的定義顛倒一下,或者乾脆也定義成u16類型數據,高低字節分別取用就是了。
至於爲什麼非要定義成一個結構體呢,爲了維護方便,提高可讀性。。。