請教 8051 C的4個 1byte 合併成 4byte 方法

各位師兄,小弟又有一個問題,請各位指點一下。
我由EEPROM 讀入4byte資料,例如:0x00,0x00,0x04,0xD2
希望將它合併成一個 long 的內容,即 0x000004D2 的 Hex內容(即是十進制的1234)
請問可以使甚麼方法合併起來?
還是我想錯方向?

Hint: little endian, big endian

TOP

謝謝師兄提示,從你的keyword搜尋到一些線索,我用以下程式控制,但又出現了一些問題,程式大約是這樣:
unsigned long test;
unsigned buff[4] ={0x12,0x34,0x56,0x78};

test = (buff[0] & 0x000000ff)<<8 | (buff[1] & 0x000000ff)<<8 | (buff[2] & 0x000000ff)<<8 | (buff[3] & 0x000000ff);
我希望結果是 test=0x12345678 , 但實際結果是 test=0x00005678
我做了一些測試,就是沒辦法再向左推,請問我那裡想的不對?我用的是 keil C,謝謝

TOP

回復 3 #likuen

<<8 =>推左一個 byte <<16先係推兩個 byte
Btw 8051玩32 bit?   

via HKEPC Reader for Android

TOP

本帖最後由 likuen 於 2016-9-7 18:28 編輯
回復 likuen
燕飛 發表於 2016-9-7 17:56

謝謝師兄回答,因我有一個較大的數據作處理,放在EEPROM 內容大約是0-100,000,我理解是用 long 作儲存及運算,所以需要在EEPROM 叫出4個1byte ,隨後結合成1個4byte使用。不知道對嗎?
師兄的提示是否如下:
test = (buff[0] & 0x000000ff)<<8 | (buff[1] & 0x000000ff)<<16 | (buff[2] & 0x000000ff)<<8 | (buff[3] & 0x000000ff);
以上我沒試過,但試了<<20,<<24 也不行。是不是我現在用了32Bit 數據,但8051 不能達到這種計算能力?

TOP

本帖最後由 燕飛 於 2016-9-7 20:33 編輯

回覆 5# likuen


    8051 <- 8 bit instruction set
用16 bit  register 已經係出cheat先得

你用緊咩Compiler?
有冇睇過disassembly?

TOP

回覆 6# 燕飛
非常感謝你的提醒,在你的提醒下,我開始解釋到我遇到的問題。
請問甚麼是disassembly?
我用keil c compiler.

TOP

本帖最後由 Charcoal99 於 2016-9-7 22:59 編輯

基本上這問題是不用做算術運算的,只需要把byte陣列表達為long variable type 即可,
兩個簡單方法:
1) 使用 Union
  1. union {
  2.   unsigned char u8[4];
  3.   unsigned long u32;
  4. } buffer;
  5. unsigned long test;

  6. buffer.u8[0] = 0x12;
  7. buffer.u8[1] = 0x34;
  8. buffer.u8[2] = 0x56;
  9. buffer.u8[4] = 0x78;
  10. test = buffer.u32;
複製代碼
2)  cast char pointer into long pointer
  1. unsigned long test;
  2. unsigned char buffer[4] = { 0x12, 0x34, 0x56, 0x78 };
  3. test = *(long *)buffer;       //或者是  test = *(long *)&buffer[0];
複製代碼
Keil C51 的貯存方式是 Big endian, 即4個byte的order是前方byte0 是higher order byte.

如果你仍堅持要做算術運算(對8bitCPU來說效率較差), 那應該是
  1. test = (unsigned long)buff[0]<<24 |
  2.        (unsigned long)buff[1]<<16 |
  3.        buff[2]<<8 |
  4.        buff[3];
複製代碼
Keil C51 在做算術運算 << 時, 運算元 buff[] 的default型態為 int 或 unsigned int, 即只有 16bit,
超過16bit 時要先 promote 到 32bit 的 long  型態。 所以你的做法只有低16bit的結果。
對8bit 運算元 來說 &0x000000ff 的bit Mask 操作是不必要及多餘的,也不會把前者promote到32bit 的 。

TOP

回覆 8# Charcoal99
超感謝師兄的指點,我使用的是16bit MCU, 我明天試一下你提供的程式,再一次謝謝你。

TOP

回覆 8# Charcoal99
今天已試過三種方式,正如師兄說效能最差是第三種,我選了第二種,貪佢簡單。但不是很明白第2個"*"是甚麼意思( test=*(long *)buffer; )
請問你是看那類型的參考書?因我翻遍我的書也沒有提這個,可否介紹一下書本或網上資源讓我進修。
再次謝謝你。

TOP