Dealing with 32 bit numbers

I have a 32 bit array defines as a uint32_t data type and I want to fill it with four uint8_t bytes. Then I want to print it out in two ints, (because Serial.print doesn't cope with 32 bit numbers) but it is not giving the numbers I expect.

So I thought the answer could be I am printing it out incorrectly or not putting them in correctly. When I run the following code I get:-

start of code
0
3060

// Dealing with 32 bit numbers
uint32_t array1[30];

void setup() {
  Serial.begin(9600);
  delay(1000);
  Serial.println("start of code");
  setArray(0, 0xF2, 0x10, 0x30, 0x60);      // set first element in array
  // print out the 32 bit number in two ints
  Serial.println((array1[0]>>16) ,HEX);     // keep it a 16 bit number
  Serial.println((array1[0] & 0xFFFF),HEX); // mask off upper bit
  
}

void loop() {  
}

void setArray(uint16_t num, uint8_t a, uint8_t b, uint8_t c, uint8_t d){
  if(num < 30 && num >= 0){
    array1[num] = (a<<24) | (b<<16) | (c<<8) | d; // is this right?
  }
}

I have tried all sorts of casting but not hit on the right one yet.
Thanks

Don't have an answer off the top of my head, but when messing with something like this, I'd fill the 32-bit uint with an identifiable pattern, either byte-by-byte or nibble-by-nibble, then start
masking and shifting. Start with
unsigned int test = 0xAABBCCDD; //you know this will be in a certain order
and see where what is stored.
Hope that helps.

a<<24 and b<<16 generated warnings, i believe because the result was being treated as a uint8_ts (c ??)

seems to fix

 array1 [num] = ((int32_t)a<<24) | ((int32_t)b<<16) | (c<<8) | d;

Is that correct?

Given:

uint32_t y = 0xF2345678;  //32-bit number
Serial.println(y, HEX);  //shows: F2345678

Output:

20:50:04.110 -> F2345678

Can a 32-bit number be assigned to a 16-bit variable?

Thanks @camsysca that also worked but not the full answer.

Thanks that fixed it. At one stage i was using

array1 [num] = ((int32_t)(a<<24)) | ((int32_t)(b<<16) | (c<<8) | d;
Which didn't seem to work.

More coffee required. my only explanation. Sigh. Missed the "long".
@Grumpy_Mike Thought you were chasing byte storage order, though.

It seems not sorry.

I had read an old thread where it didn't work so it looks like it is fixed by now. Seeing as the data was never there in the first place it was no wonder it didn't work when I tried it.

Thanks for pointing this out to me.

the difference is casting the variable, (int32_t)a rather than the result (int32_t)(a<<24)

2 Likes

c<<8 doesn't generate a warning because byte/char values are promoted to uint16_t/int at the start of an expression. Shifting them 8 bits left won't throw all of the bits off the top. Any shift more than 8 and less than 16 will keep at least one bit, so you won't get a warning even though some bits are lost.

Thanks.

Indeed there was a problem with c. When I checked all possible values for c then once it reached 0x80 then all the upper bits were over written with a 1. It was of course a sign extension, but why that happened on an unsigned variable I don't understand.

So when I cast c as (int16_t) it didn't have this problem anymore. But this is beginning to look like voodoo to me.

This topic was automatically closed 180 days after the last reply. New replies are no longer allowed.