arduino 大小端資料問題

2021-07-12 04:25:26 字數 2441 閱讀 9187

arduino資料的儲存方式是小端的,除錯了兩天的程式,終於發現這個問題了。

下面說一下發現問題的過程:

首先我定義了乙個結構體,用來接收串列埠傳送來的資料,串列埠傳送來的資料首先放到陣列中,再強制轉換成結構體型別,定義結構體的意義就在於我想實現一種自定義的協議。

協議如下

命令頭+命令長度+資料長度+命令+錯誤**+資料+校驗碼

由於命令頭是固定的,我的命令以0xfe開頭,因此沒有定義到結構體中。

結構體如下

/******************

* uartcmdlen:uartcmd + uarterrcode

* uartdatalen:uartdatabuf

*******************/

typedef struct __suartdata

*psuartdata;

定義的陣列

uint8_t uartbuf[uart_max_len] = ;

用於存放串列埠接收的資料。

把陣列的資料轉換成結構體格式

psuartdatarevsend = (psuartdata)uartbuf;

這樣訪問傳送來的資料就方便多了,比如psuartdatarevsend->uartcmdlen ,psuartdatarevsend->uartdatalen等。

但是發現傳送來的資料發生了錯誤。讀取陣列的資料沒有錯誤,訪問結構體中uint8_t型別的資料也正常,uint16_t型別的資料卻不符。

比如我傳送如下資料(16進製制)

fe 03 04 0003 00 00000000 fa

傳送的不含空格,為方便大家看清協議,新增了空格。我發現收到的是0x300(或者是0x000300),而不是0x0003(也就是0x03),我懷疑uint16_t型別的資料多了乙個位元組。

首先我以為是int型別長度的問題,arduino uno的int是2個位元組,arduino due的是4個位元組,我的是uno,板子是uno,ide中選擇的也是uno,

應該不是型別長度的問題。在arduino ide中如下定義也是編譯通過的 uint8_t t=0xffffffff;,這個明顯超出了範圍,不知道原因啊。

其次我也為時結構體對齊的問題,我用sizeof()測試結構體的大小也是6,也不是這個問題,為保險起見,我用

#pragma pack(1)指定對齊方式,但是還是不對,應該也不是這個原因。

百思不得其解的時候,我決定多用幾組資料去測試,後面是得到的uint16_t成員變數的值(16進製制)

fe0304 0130 0001000000c9      3001

fe0304 0003 0000000000fa      300

fe0304 0102 0304050607fe      201

fe0304 0310 0001000000c9      1003

這樣大家可能沒發現什麼問題,我給大家補齊一下

fe0304 0130 0001000000c9      3001

fe0304 0003 0000000000fa      0300

fe0304 0102 0304050607fe      0201

fe0304 0310 0001000000c9      1003

再轉一下

fe0304    01 30    0001000000c9                    30 01

fe0304    00 03    0000000000fa                    03 00

fe0304    01 02    0304050607fe                    02 01

fe0304    03 10    0001000000c9                    10 03

應該發現uint16_t型別的資料高低位顛倒了,這就是大小端儲存方式不同造成的。

下面分別是2位元組和4位元組轉換的巨集命令。arduino論壇有用union來轉換4位元組的方法,至於更大的資料float也是用union,再大的資料就是用陣列,陣列從大到小讀取就能實現轉換了。

#define htons(a)  ((((uint16_t)(a) & 0xff00) >> 8 ) | (((uint16_t)(a) & 0x00ff) << 8 ))

#define htonl(a)  ((((uint32_t)(a) & 0xff000000) >> 24)  |  (((uint32_t)(a) & 0x00ff0000) >> 8 )  |  (((uint32_t)(a) & 0x0000ff00) << 8 )  | (((uint32_t)(a) & 0x000000ff) << 24)) 

這樣就能正確識別命令了htons(psuartdatarevsend->uartcmd);

下面show一下具體的使用**

switch(htons(psuartdatarevsend->uartcmd))

資料大小端問題

假如有乙個4位元組的資料為 0x12 34 56 78 十 進製 305419896 0x12為高位元組,0x78為低位元組 若將其存放於位址0x4000 8000,則有 記憶體中乙個每乙個位址用四個位元組表示 32位系統中 每乙個位址裡面存放乙個位元組 記憶體位址 0x4000 8000 低位址 ...

大小端問題

對於位數大於 8位的處理器,例如 16位或者 32位的處理器,由於暫存器寬度大於乙個位元組,那麼必然存在著乙個如果將多個位元組安排的問題。因此就導致了大端儲存模式和小端儲存模式。例如乙個 16bit 的short型x 在記憶體中的位址為 0x0010,x 的值為0x1122 那麼0x11 為高位元組...

大小端問題

大小端問題 跨位元組位域大小端轉換例項講解 注 結構體整體當做u16 u32來賦值時才會產生這種問題,如果是按位元組或者移位方式訪問則沒有問題 typedef struct s bit sample 測試程式 vos void bigendiandomainfiledtest vos void 1 ...