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:
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);
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.
byte third_byte = ( addr >> 16 ) & 0xff; // 0xff is 11111111 in binary
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?
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?
AWOL:
You can't have a variable or function name that starts with a digit.
This happen last night to me when i defined
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
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.
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.