Go Down

Topic: How do I get the 3d byte of a word? (Read 1 time) previous topic - next topic

clone45

Hello,

How do I get the 3rd byte of a word?

I have code that can get me the low and high bytes of an int, which looks like this:

  byte high_byte = ( addr >> 8 ) & 0xff; // 0xff is 11111111 in binary
  byte low_byte = addr & 0xff;

But now I need to get the three lowest bytes of a word.  How would I do that?  For example:

Code: [Select]

  byte first_byte = ??;      // lowest byte
  byte second_byte = ??;   // second lowest byte
  byte third_byte = ??;     // third lowest byte


I find myself in this situation after upgrading some ram from a 256k chip to a 1-meg chip.  Having done so, the memory addresses can't fit in a word anymore, and the chip that I'm using (a FM25V10) requires that I use 17bit addresses which are passed in via the SPI interface.

My old code looks like this:

Code: [Select]

  byte addrByte2 = ( addr >> 8 ) & 0xff; // 0xff is 11111111 in binary
  byte addrByte1 = addr & 0xff;
   
  digitalWrite(chip_select, LOW);
  SPI.transfer(CMD_WREN);  //write enable
  digitalWrite(chip_select, HIGH);
 
  digitalWrite(chip_select, LOW);
  SPI.transfer(CMD_WRITE); //write command
 
  // Transfer memory address
  SPI.transfer(addrByte2);
  SPI.transfer(addrByte1);

  // Transfer value (byte)
  SPI.transfer(value);


Thanks,
- Bret

PaulS

word seems to be a Microsoft-specific term. While the Arduino unfortunately supports such a term, it is not common usage, so one of us needs to look up its size.

If the first byte occupies the lowest 8 bits, and the second bytes occupies the next 8 bits, it doesn't seem unlikely that the 3rd byte occupies the next 8 bits.

Code: [Select]
  byte third_byte = ( addr >> 16 ) & 0xff; // 0xff is 11111111 in binary


clone45

Thanks Paul.  Woops... I mean "3d byte of a long" I think!

I figured as much, but I wanted to be sure. :-)

Cheers,
- Bret

clone45

I have a follow up question.  I now need to go the other direction.  I have three bytes representing the lower 3 bytes of a long.  I need to construct an unsigned long out of them and set the remaining 8 most significant bits of the long to 0.  How do I pull that off?

Thanks,
- Bret

guix

#4
Dec 21, 2012, 06:17 am Last Edit: Dec 21, 2012, 06:19 am by guix Reason: 1
Hello, something like that:
Code: [Select]

b3 | (b2 << 8) | (b1 << 16)

AWOL

Be careful; shifting an Arduino "int" left sixteen bits is likely to leave you with nothing.
Best cast it to "unsigned long" first.
"Pete, it's a fool looks for logic in the chambers of the human heart." Ulysses Everett McGill.
Do not send technical questions via personal messaging - they will be ignored.

clone45

AWOL,

You got me thinking.  I have each of the values stored in bytes.  Wouldn't guix's solution not work?  Wouldn't b2 << 8 shift all the bits off of my byte completely?

For example:

byte my_variable;
print my_variable << 8;  // would this print 0?

Cheers,
- Bret

winner10920

Add
Unsigned long 3dbyte =
Before that and youl be fine

AWOL

Quote
Unsigned long 3dbyte

You can't have a variable or function name that starts with a digit.
"Pete, it's a fool looks for logic in the chambers of the human heart." Ulysses Everett McGill.
Do not send technical questions via personal messaging - they will be ignored.

Khalid


You can't have a variable or function name that starts with a digit.

This happen last night to me when i defined
Code: [Select]
byte 1stTime=30;
and i was unable to compile with a bizaree error of Arduino...
I replaced the 1 with f and now its working fine.
Lesson Learnt:
1-Always define variable without using the digit.
2- If forget , then visit this thread
Simply...You can't afford me..

Author Of:
http://my-woodcarving.blogspot.com/
http://www.free3dscans.blogspot.com/
http://my-diysolarwind.blogspot.com/

Oops..some one gave me Karma...:)

PaulS

#10
Dec 22, 2012, 01:39 pm Last Edit: Dec 22, 2012, 01:41 pm by PaulS Reason: 1
Quote
Add
Unsigned long 3dbyte =
Before that and youl be fine

Aside from the incorrect name, the underlying premise is false.

Try this:
unsigned long validName = 60 * 1000 * 10;
The result of 60 * 1000 * 10 will fit in an unsigned long, right? Of course. But, what value is actually there when you print validName? It will not print as 600000.

Why? Because all the values on the right are int values, so int arithmetic is used. And, 60 * 1000 is NOT going to fit in an int.

The same problem happens with bit shifting. When all the values in the equation are int or smaller (as in b1 << 16), the registers used will be int registers, and the result of b1 << 16 will be that all the bits in b1 got shifted out of the int register.

On the other hand, ((unsigned long)b1 << 15) will cause the use of a larger register, so the shifted result is not lost. When the contents of this unsigned long register are ultimately assigned to an unsigned long, the result will be correct.

The type on the left side of the equal sign is not even considered until the compiler has created a result based on the right side information, types, and values to be assigned, so changing the left side type only won't help.

dhenry

3rd byte of a word doesn't exist.

There are a few ways to get to the 3rd (most significant) byte of an unsigned long. The fastest would be to cast it to a unsigned char pointer, and advance that pointer by 2 to get to the 3rd byte.

You can also use union, or a pointer to a struct that contains 4 bytes.

The downside with such approaches would be that they are endian dependent.

clone45

#12
Dec 24, 2012, 05:51 am Last Edit: Dec 24, 2012, 09:08 am by Coding Badly Reason: 1
PaulS,

So, are you saying that this might work?:

unsigned long somevar = (unsigned long)b3 | ((unsigned long)b2 << 8) | ((unsigned long)b1 << 16)

And, I hope this isn't a dump question, but how could I test this code?  Should I use the arduino simulator?

Cheers,
- Bret

AWOL

Quote
And, I hope this isn't a dump question, but how could I test this code?

With an Arduino?
Just a thought.
"Pete, it's a fool looks for logic in the chambers of the human heart." Ulysses Everett McGill.
Do not send technical questions via personal messaging - they will be ignored.

clone45

AWOL,

Oh, yeah... I think I get where you're coming from.  You mean, like use Serial.print()?  I forgot that even existed.  Thanks for the tip.

- B

Go Up