1

I wrote a simple code where I add hexadecimal values multiplied by 0x1, 0x100 and so on together.

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

when I pass numbers D1,55,BF,2D result is D154BF2D but on some numbers combination it is working well, I am using Arduino IDE 1.8.5, can you explain?

andz
  • 274
  • 1
  • 3
  • 12

1 Answers1

1

The code you have is working perfectly, so there's rather little to explain, if you assume that it is doing what you want it to do. If it's not doing what you want it to do, then we can guess what you want it to do, but then it could be that you wanted it to make you a nice cup of tea, and in that case this won't be much help.

Since you don't give the definitions of the variables, I will assume you have something like:

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);

which outputs

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

And you can verify that it does exactly what you asked it to.

However, given the values you're multiplying by, you seem to be trying to make a mask from four signed bytes.

Multiplying a int8_t by an integer literal causes it to be extended to an int, and so

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

0xbf * 0x100 = -16640 or 0xffffbf00

Those leading 0xffff are called 'sign extension' and are causing the next higher byte value to differ from what you would get if you were just shifting and combining the bits.

If you want to combine signed bytes, you need to mask off the sign extension:

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

or

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

but usually it's easier to use unsigned bytes for bit masks as they don't have sign extension:

    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
Pete Kirkham
  • 48,893
  • 5
  • 92
  • 171