Assign the address of the long variable to a byte pointer and then increase it subsequently.
This can have issues relating to endianess: Endianness - Wikipedia
Also other contributors replied that union can be used for this purpose.
Assign the address of the long variable to a byte pointer and then increase it subsequently.
This can have issues relating to endianess: Endianness - Wikipedia
Also other contributors replied that union can be used for this purpose.
You can save yourself a lot of detail greef by just arranging your byte variables on top of a long variable(s) using the powerful C user type of structure. Then you can use the write anything EEPROM library to do the actual writing and reading to the internal EEPROM.
http://arduino.cc/playground/Code/EEPROMWriteAnything
I love the C strut type sense first learning about it. So elegant, so simple, so useful.
Lefty
retrolefty:
I love the C strut type sense first learning about it. So elegant, so simple, so useful.
I agree! A bit of trivia: the assignment operator is supported...
typedef struct
{
uint8_t id;
uint32_t value;
uint16_t whatever;
}
mystruct_t;
mystruct_t saved;
void setup( void )
{
mystruct_t temp;
temp = saved;
// work with temp
temp.id = random();
temp.value = random();
temp.whatever = random();
saved = temp;
}
void loop( void )
{
}
This is handy when dealing with complex data shared with an ISR (volatile is technically not necessary [and I may have it in the wrong place] but, when in doubt, protection is always a good idea)...
typedef struct
{
volatile uint8_t id;
volatile uint32_t value;
volatile uint16_t whatever;
}
mystruct_t;
mystruct_t saved;
void setup( void )
{
mystruct_t temp;
noInterrupts();
temp = saved;
interrupts();
// use temp so we don't have to leave interrupts disabled so long
temp.id = random();
temp.value = random();
temp.whatever = random();
noInterrupts();
saved = temp;
interrupts();
}
void loop( void )
{
}
I don't think anyone mentioned unions. That makes it pretty clear:
typedef union
{
long l;
byte c [sizeof (long)];
} long_to_chars;
void setup ()
{
Serial.begin (115200);
long_to_chars foo;
foo.l = 305419896; // that is 0x12345678
Serial.println (foo.l);
Serial.println (foo.c [0], HEX);
Serial.println (foo.c [1], HEX);
Serial.println (foo.c [2], HEX);
Serial.println (foo.c [3], HEX);
} // end of setup
void loop () {}
Output:
305419896
78
56
34
12
The union makes it clear you are looking at the long "in a different way" that is, broken down into bytes.
Like I say I need to to this convertion on mikroC compiler.Does this code will also work? I mean the C struture?
The split long on bytes was easy with the help from all that answer me.I belive the way AWOL say would be more easier for me.
I just need to reverse this :
void write_eeprom()
{
eeprom_byte1 = piece & 0xff;
eeprom_byte2 = (piece >> 8) & 0xff;
eeprom_byte3 = (piece >> 16) & 0xff;
eeprom_byte4 = (piece >> 24) & 0xff;
EEPROM_Write(0x00, eeprom_byte4);
delay_ms(25);
EEPROM_Write(0x01, eeprom_byte3);
delay_ms(25);
EEPROM_Write(0x02, eeprom_byte2);
delay_ms(25);
EEPROM_Write(0x03, eeprom_byte1);
delay_ms(25);
}
This sintaxe if from mikroC compliler and is working fine, of course I can do this in a more eficient way using a for loop but for now I just want to put all working then I will get the code more human readable :)!
I belive the way AWOL say would be more easy for me.
So do you know how to do this or do you want telling.
By the way there is no need to put a delay after the EEPROM_Write().
I'm not sure about it! Since I'm working with a PIC every change I have to burn the program an put it on the board to see the results.Is very boring do this every 5 minutes ![]()
I have no other way of debuging the code for now.Can you just give me a hand ?
About the delay on the mikroC help they recommend this delay soo I put it.
Thanks for the great help
The "union" works both ways. Either you put in a long, and then pull out 4 bytes, or you put in 4 bytes and then pull out the long. Nice and symmetrical.
ok I will try the "union"
Tomorrow I will post the result
Thanks Nick Gammon
Well bit of a nerve asking about a PIC on an arduino forum, but never mind. ![]()
void read_eeprom()
{
eeprom_byte4 = EEPROM_Read(0x00);
eeprom_byte3 = EEPROM_Read(0x01);
eeprom_byte2 = EEPROM_Read(0x02);
eeprom_byte1= EEPROM_Read(0x03);
piece =( eeprom_byte4 << 24) | (eeprom_byte3 << 16) | (eeprom_byte2 << 8) | eeprom_byte1;
}
"mikroC PRO for PIC is a full-featured ANSI C compiler for PIC devices from Microchip®."
Should
Grumpy_Mike:
Well bit of a nerve asking about a PIC on an arduino forum, but never mind.
Yes but Mike, maybe the people on the PIC forum are all young. ![]()
![]()
yes probbly just like you know who!
Grumpy_Mike:
Your advice is rather bazaar, I have noted in other threads you hand out bad or irrelevant advice.
I also sometimes contributed to a solution, here, and on other forums.
I agree my original reply was a quick judgement and I removed sentences/replies
that are not contributing to a solution and/or irrelevant to the thread topic.
Unions and typecasts (see my reply) are archieving a similar thing, in the end.
I used assembler for some years not only for MCUs, and currently I move away from it,
because the poor maintainability. I am here on the forum basically also to learn from others.
There is one assembler source about 1 megabyte which I browsed some months ago the largest I wrote is only 300k unfortunately it is lost. Isn't one great feature of C the portability, you can understand Atmel sources, or PIC sources, even if you don't use it currently?
Remember these are mainly beginners and are easly confused.
I'd second that, people out there are surprisingly intelligent at times, while over time, not all of them will become programmers or even professional users.
They'd use the advice that is most appreciate to them, and more or less ignore the others.
Grumpy_Mike:
piece =( eeprom_byte4 << 24) | (eeprom_byte3 << 16) | (eeprom_byte2 << 8) | eeprom_byte1;
Mike, isn't there an issue with that code? Namely, that the two highest bytes will be lost because the compiler will treat eeprom_byte4 << 24 and eeprom_byte3 << 16 as int expressions without an explicit cast?
E.g., the following code:
unsigned long foo;
byte bar = 255;
foo = ( bar << 24) | (bar << 16);
Serial.println(foo,DEC);
foo = ((unsigned long)bar << 24) | ((unsigned long)bar << 16);
Serial.println(foo,DEC);
Produces output of:
0
4294901760
.... showing that the bits are lost without the cast.
Can anyone explain the code in reply #8, please?
No, because it is Complete Nonsense.
if((phase>>1)==0)led_data=led_numbers&0x000f;
What is phase? Why is it shifted right 1 bit? I guess we will never know.
Can anyone explain the code in reply #8, please?
It's not just me then. Good.
Mike, isn't there an issue with that code? Namely, that the two highest bytes will be lost because the compiler will treat eeprom_byte4 << 24 and eeprom_byte3 << 16 as int expressions without an explicit cast?
It depends on how these variables were defined. If they were defined as longs then there will be no problem.
If they were defined as bytes or ints I would expect the compiler to automatically promote them to longs because the left hand side is a long. However I know that some compilers do this while others do not. Good point have you tried it?