首页 > 解决方案 > ATTINY84:反转字节顺序的奇怪问题

问题描述

我将 6 个值(4x 3bit + 1bit)编码为 16bit 整数,并通过串行将它们传输到 ATTINY84,将它们分成 2 个字节。这一切都很好,直到我将字节重新组合成一个 16 位整数。

例子:

我正在发送以下二进制状态0001110000001100,该状态转换7180[18, 28].

我将该字节数组放入 EEPROM 并在下一次电源循环时读取它。

重启后,我的串行调试输出如下所示:

18
28
7180

惊人的。看起来一切都很好,我的那部分代码是:

byte d0 = EEPROM.read(0);
byte d1 = EEPROM.read(1);
unsigned int w = d0 + (256 * d1);

但现在最奇怪的事情发生了。当我逐位阅读时,我回来了:

0011000000111000

should be:

0001110000001100

通过:

 for(byte t = 0; t < 16; t++) {
    serial.print(bitRead(w, t) ? "1" : "0");
  }

位表示完全相反。这怎么可能?或者,也许我错过了一些东西。

我还确认,当我提取实际的 3 位位置以接收我的原始值0..7时,它全部关闭。

任何帮助,将不胜感激。

标签: arduinobitavrattiny

解决方案


所以看起来我掉进了小/大端的陷阱。

基本上正如阿兰所说,在评论中 - 一切都是正确的,这只是陈述。

我想出了以下方法,可以从需要采用大端格式的小端存储数字中提取位:

/**
 * @bex
 */
uint8_t bexd(uint16_t n, uint8_t o, uint8_t l, uint8_t d) {
  uint8_t v = 0;
  uint8_t ob = d - o;
  for (uint8_t b=ob; b > (ob-l); b--) v = ( v << 1 ) | ( 0x0001 & ( n >> (b-1) ) );
  return v;
}
uint8_t bexw(uint16_t n, uint8_t o, uint8_t l) {return bexd(n, o, l, 16);}
uint8_t bexb(uint8_t n, uint8_t o, uint8_t l) {return bexd(n, o, l, 8);}

例如:

在大端中,“第二”值存储在位 3,4 和 5 中,而小端将存储在位 10、11 和 12 中。上述方法允许使用“小端”值,例如这将是一个“大端”值。

要从此值中提取第二个值,0011000000111000只需执行以下操作:

byte v = bex(7180, 3, 3);  // 111
Serial.println(v); // prints 255

希望对某人有所帮助。


推荐阅读