在 Arduino 中添加以错误结果结尾的十六进制数

Adding hexadecimal numbers in Arduino ending with wrong result

我写了一个简单的代码,其中我将十六进制值乘以 0x1、0x100 等相加。

  uid = (nuidPICC[0] * 0x1000000);
  uid = uid + (nuidPICC[1] * 0x10000);
  uid = uid + (nuidPICC[2] * 0x100);
  uid = uid + nuidPICC[3];

当我传递数字 D1、55、BF、2D 结果是 D154BF2D 但在某些数字组合上它运行良好,我使用的是 Arduino IDE 1.8.5,你能解释一下吗?

您拥有的代码运行良好,因此如果您假设它正在执行您希望它执行的操作,则无需解释。如果它没有按照您的意愿去做,那么我们可以猜测您想要它做什么,但也可能是您希望它为您泡一杯好茶,在这种情况下,这不会太多帮助。

因为你没有给出变量的定义,我假设你有这样的东西:

int8_t nuidPICC[] = { 0xD1,0x55,0xBF,0x2D };

printf("nuidPICC = { %d, %d, %d, %d }\n", nuidPICC[0], nuidPICC[1], nuidPICC[2], nuidPICC[3]);

int32_t     uid = (nuidPICC[0] * 0x1000000);
uid = uid + (nuidPICC[1] * 0x10000);
uid = uid + (nuidPICC[2] * 0x100);
uid = uid + nuidPICC[3];

printf("uid = %d * %d + %d * %d + %d * %d + %d  = %d\n",
    nuidPICC[0], 0x1000000,
    nuidPICC[1], 0x10000,
    nuidPICC[2], 0x100,
    nuidPICC[3], uid);

printf("%d in hex is %08x\n",uid,uid);

输出

nuidPICC = { -47, 85, -65, 45 }
uid = -47 * 16777216 + 85 * 65536 + -65 * 256 + 45  = -782975187
-782975187 in hex is d154bf2d

并且您可以验证它是否完全按照您的要求执行。

但是,鉴于您要乘以的值,您似乎正试图从四个有符号字节制作掩码。

将 int8_t 乘以整数文字会导致它扩展为 int,因此

int32_t x = int8_t(0xbf) * 0x100;
printf("0xbf * 0x100 = %d or 0x%08x\n",x,x);

0xbf * 0x100 = -16640 or 0xffffbf00

那些领先的 ​​0xffff 被称为“”,并且导致下一个更高的字节值与您只是移动和组合位时得到的值不同。

如果你想合并带符号的字节,你需要屏蔽掉符号扩展:

uid = (nuidPICC[0] << 24);
uid = uid | (nuidPICC[1] << 16) & 0xff0000;
uid = uid | (nuidPICC[2] << 8) & 0xff00;
uid = uid | nuidPICC[3] & 0xff;

uid = ( 0xffffffd1 << 24) 
      | ( ( 0x00000055 << 16 )  & 0xff0000 )
      | ( ( 0xffffffbf << 8 ) & 0xff00 ) 
      | ( 0x0000002d & 0xff ) 
    = 0xd155bf2d

但通常使用无符号字节作为位掩码更容易,因为它们没有符号扩展:

    uint8_t nuidPICC[] = { 0xD1,0x55,0xBF,0x2D };
    uint32_t uid = (nuidPICC[0] << 24);
    uid = uid | (nuidPICC[1] << 16);
    uid = uid | (nuidPICC[2] << 8);
    uid = uid | nuidPICC[3];

    printf("uid = ( 0x%x << %d) | ( 0x%x << %d ) | ( 0x%x << %d ) | 0x%x  = 0x%x\n",
        nuidPICC[0], 24,
        nuidPICC[1], 16,
        nuidPICC[2], 8,
        nuidPICC[3], uid);

uid = ( 0x000000d1 << 24)
    | ( 0x00000055 << 16 )
    | ( 0x000000bf << 8 ) 
    |   0x0000002d  
    = 0xd155bf2d