最近著手於開發rpimouse的通訊協議,第一次接觸crc校驗,發現有很多問題。32本身是帶有硬體crc校驗的,但是他的校驗結果和pc演算法計算出來的完全不同。在查詢解決方法的過程中得知32資料和pc資料的大小端不同,資料計算結果當然不同。什麼是大小端呢?比如:數字0x12 34 56 78 在記憶體中的表示形式為:
1)大端模式:
低位址------------------>高位址
0x12 | 0x34 | 0x56 | 0x78
2)小端模式:
低位址------------------>高位址
0x78 | 0x56 | 0x34 | 0x12
3)具體例子:
16bit寬的數0x1234在小端模式及大端模式cpu中存放的方式(假設從0x4000開始存放)為:
記憶體位址
小端模式存放內容
大端模式存放內容
0x4000
0x34
0x12
0x4001
0x12
0x34
記憶體位址
小端模式存放內容
大端模式存放內容
0x4000
0x78
0x12
0x4001
0x56
0x34
0x4002
0x34
0x56
0x4003
0x12
0x78
以unsigned int value = 0x12345678為例,分別看看兩種位元組序下其儲存情況。我們可以用unsigned char buf[4] 來表示 value
大端模式:
高位址| buf[3] (0x78) 低位
| buf[2] (0x56)
| buf[1] (0x34)
| buf[0] (0x12) 高位
低位址小端模式:
高位址| buf[0] (0x12) 低位
| buf[1] (0x34)
| buf[2] (0x56)
| buf[3] (0x78) 高位
低位址一般通過union型別來測試。以下**可用來測試編譯器大小端模式。
#include int main (void)
u; u.a[0] = 0x11;
u.a[1] = 0x22;
printf ("0x%x\n", u.i); //0x2211 為小端 0x1122 為大端
return 0;
}輸出結果:
0x2211
對於單字資料(16bit)
#define bigtolittle16(a) (( ((uint16)(a) & 0xff00) >> 8) | \
(( (uint16)(a) & 0x00ff) << 8))
對於雙字資料(32bit)
#define bigtolittle32(a) ((( (uint32)(a) & 0xff000000) >> 24) | \
(( (uint32)(a) & 0x00ff0000) >> 8) | \
(( (uint32)(a) & 0x0000ff00) << 8) | \
(( (uint32)(a) & 0x000000ff) << 24))
以上方法及內容來自csdn: ,程式未經測試。
所以,如果想使用32的硬體crc,首先要將小端資料轉為大端,得到crc後與初值(0xffff ffff)按位異或,即可得到主流crc32-mpeg2的校驗結果。
stm32的硬體crc32使用
stm32 大小端模式 與 堆疊及其增長方向分析
how to set stm32 to generate standard crc32
stm32內建crc模組的使用
至此,32crc問題解決完畢(大概?),下一步繼續完善專案的通訊協議。
stm32中大小端轉換
相同位元組序的平台 你是大端平台 在進行網路通訊時可以不進行位元組序轉換,但是跨平台 你是小端平台 進行網路資料通訊時必須進行位元組序轉換。網路協議規定接收到得第乙個位元組是高位元組,存放到低位址,所以傳送時會首先去低位址取資料的高位元組。小端模式的多位元組資料在存放時,低位址存放的是低位元組,而被...
大小端模式,stm32採用小端模式
儲存模式 小端 較高的有效位元組儲存在較高的儲存器位址,較低的有效位元組儲存在較低的儲存器位址。大端 較高的有效位元組儲存在較低的儲存器位址,較低的有效位元組儲存在較高的儲存器位址。那麼,在記憶體裡面,其儲存就變成了 位址 hex 0x4000 0000 78 56 34 12 更為簡單一點 低位址...
STM32 關於GPIO的問題
stm32 關於gpio的問題集錦 1 關於gpio 問 stm32的io口初始化為輸入浮空,那管腳是高電平還是低電平呢?答 既不是高電平也不是低電平,懸空的意思是沒有使用的狀態。2 有關stm32f103 埠復用的問題?問 配置io口的頻率時,為什麼只給乙個io口配置?答 gpio initstr...