我写了一个简单的代码,我将十六进制值乘以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,你能解释一下吗?
答案 0 :(得分:1)
您拥有的代码可以完美运行,因此,如果您假设它正在执行您想要的操作,则几乎没有什么需要解释的。如果它没有按照您想要的去做,那么我们可以猜测您想要去做的事,但是可能是您想要它来使您喝一杯好茶,在这种情况下,这不会太多救命。
由于您没有给出变量的定义,所以我假设您有类似的东西:
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被称为'sign extension',并导致下一个更高的字节值不同于仅移位和组合这些位时所得到的值。
如果要组合带符号的字节,则需要屏蔽符号扩展名:
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