View previous topic :: View next topic |
Author |
Message |
Diode
Joined: 27 Jul 2012 Posts: 35
|
(SOLVED) Saving a 16bit signed integer in eeprom. |
Posted: Tue Dec 04, 2012 12:37 pm |
|
|
I'm having some difficulties with saving 16 bit signed integers in the eeprom of a pic18F2523.
The idea is to periodically store some data in the internal eeprom. My code is working fine for unsigned int16 data but as soon as I try to use it for a signed int16 it doesn't work anymore.
Here is the declaration of the variables:
Code: |
int8 setpoint_lowbyte;
int8 setpoint_highbyte;
signed int16 setpoint;
|
The eeprom function:
Code: |
Setpoint_lowByte = ((setpoint >> 0) & 0xFF);
Setpoint_highByte = ((setpoint >> 8) & 0xFF);
write_eeprom(eeprom_address+6,setpoint_lowByte);
write_eeprom(eeprom_address+7,setpoint_highByte);
SETPOINT = ((setpoint_highByte << 8));
SETPOINT = SETPOINT | (setpoint_lowbyte);
|
Let's assume setpoint is 275. If I declare setpoint as int16 (unsigned by default) highbyte is 1 and lowbyte is 19, this is correct.
When I declare setpoint as signed int16 highbyte remains 0 and lowbyte is 19.
Does anyone know why this happens with signed int16 data? All help will be appreciated.
Last edited by Diode on Wed Dec 05, 2012 9:37 am; edited 1 time in total |
|
![](templates/subSilver/images/spacer.gif) |
bkamen
Joined: 07 Jan 2004 Posts: 1611 Location: Central Illinois, USA
|
|
Posted: Tue Dec 04, 2012 1:10 pm |
|
|
There's kind of an easier way if you're interested...
I make a struct called "config"...
Code: |
struct {
unsigned int byte1;
unsigned int byte2;
signed int16 word1;
} config;
|
then I have a routine that looks like this
Code: |
// ============================
// load_save_config( mode ) : load_save_config routine
//
void config_load_save ( int rw ) {
int i;
for (i=0;i<=(sizeof(system_config)-1);++i) {
switch (rw) {
case load : *(( (int8 *) &config) + i) = read_eeprom(i);
break;
case save : write_eeprom( i, *(( (int8 *) &config) + i) );
break;
}
}
}
|
_________________ Dazed and confused? I don't think so. Just "plain lost" will do. :D |
|
![](templates/subSilver/images/spacer.gif) |
Diode
Joined: 27 Jul 2012 Posts: 35
|
|
Posted: Tue Dec 04, 2012 1:25 pm |
|
|
Thanks for your reply. I'm a "beginner" in C programming so your solution might be a bit hard to understand for me.
If I understand it correct you have made a for_loop to write the different addresses of the eeprom. The RW is a read/write bit depending of it's value you read or write the data.
Then you do something with pointers and that's the part where I get lost. |
|
![](templates/subSilver/images/spacer.gif) |
bkamen
Joined: 07 Jan 2004 Posts: 1611 Location: Central Illinois, USA
|
|
Posted: Tue Dec 04, 2012 1:32 pm |
|
|
Diode wrote: | Thanks for your reply. I'm a "beginner" in C programming so your solution might be a bit hard to understand for me.
If I understand it correct you have made a for_loop to write the different addresses of the eeprom. The RW is a read/write bit depending of it's value you read or write the data.
Then you do something with pointers and that's the part where I get lost. |
It's probably mandatory then that you read up more on C and also get the book "The C Programming Language" written by Dennis Ritchie and Brian Kernighan -- the guys who invented C.
Correct: The RW bit tells the function whether to load the struct config with EEPROM contents or to SAVE the struct config contents to EEPROM.
The loop automatically sizes against config's number of bytes and then saves/loads those bytes to/from EEPROM.
Remember that a variable stores values (contents) but also must live in memory (location).
A pointer is the value of that location. (its address)
Again, I can't stress/recommend getting that book enough.
-Ben _________________ Dazed and confused? I don't think so. Just "plain lost" will do. :D |
|
![](templates/subSilver/images/spacer.gif) |
ezflyr
Joined: 25 Oct 2010 Posts: 1019 Location: Tewksbury, MA
|
|
Posted: Tue Dec 04, 2012 2:32 pm |
|
|
Hi,
You didn't post your compiler version, so I won't test your code. I will note,
however, that CCS does provide a canned function, Make8(), that will
extract the bytes from either an int16 or an int32, so you might give that a
try and see if it solves your problem? This function, and companion functions
like Make16() are described in the manual.
Good Luck!
John |
|
![](templates/subSilver/images/spacer.gif) |
Diode
Joined: 27 Jul 2012 Posts: 35
|
|
Posted: Tue Dec 04, 2012 3:33 pm |
|
|
Ben, I will look for the book you mentioned. I have a book about C but this one is more focused on C for computers.
The book I have describes the use of pointers but it still is a bit vague to me. Probably wise to read it a few times again.
John, the compiler version is 4.013. Just had a quick look at the help function and it seems to do exactly what I need. Tomorrow I will try make8 and make16 to see if it solves the problem.
Both thanks a lot for the help.
Bas (from the Netherlands) |
|
![](templates/subSilver/images/spacer.gif) |
ezflyr
Joined: 25 Oct 2010 Posts: 1019 Location: Tewksbury, MA
|
|
Posted: Tue Dec 04, 2012 4:46 pm |
|
|
Hi Bas,
You should be aware that your compiler version is one of the very early
version 4 releases of the compiler, and predates by quite a bit the first
'stable' releases for version 4. Keep that in mind as you develop your code
!
John |
|
![](templates/subSilver/images/spacer.gif) |
ckielstra
Joined: 18 Mar 2004 Posts: 3680 Location: The Netherlands
|
|
Posted: Tue Dec 04, 2012 5:30 pm |
|
|
ezflyr wrote: | ... and predates by quite a bit the first 'stable' releases for version 4. | I would state that stronger: if anything works in 4.013 than you should be considered lucky. The first versions that started to work more or less reliable required CCS to release 60 more versions, that is to say that from around 4.073 the compiler became usable again.
Either downgrade to v3.249 that was a very good version but lacks the new v4 features, or upgrade to one of the newer versions. |
|
![](templates/subSilver/images/spacer.gif) |
Diode
Joined: 27 Jul 2012 Posts: 35
|
|
Posted: Wed Dec 05, 2012 2:11 am |
|
|
John, seen the post of ckielstra I must be lucky that it works at all
At least your comment about the make8 and make16 functions solved my problem, it works fine now. Even in version 4.013
These functions perform the same function as the code I wrote but apparently I have made a mistake somewhere.
I have heard before that my version was not one of the best versions made. First I want to finish this project and then I will see.
In general I'm quite satisfied with the compiler and ICD-64 programmer of CCS.
Thanks for the help, I was struggling quite a long time with this problem and now it is solved within a few hours! |
|
![](templates/subSilver/images/spacer.gif) |
Ttelmah
Joined: 11 Mar 2010 Posts: 19368
|
|
Posted: Wed Dec 05, 2012 2:52 am |
|
|
As a general comment, shifts are always dangerous with signed numbers. K&R has the comment 'the result is undefined if the right expression is negative'. The problem is what you do with the sign. This depends on the processor.
For storing numbers, if you needed to use shifts, and work with signed numbers, you are actually better to convert the number to unsigned before shifting and similarly on the re-assembly, do the work with unsigned values, and then put them back to signed again afterwards.
Generally though, a Union, is a more 'universal' solution, while with CCS, the make8, and make16 functions avoid the overheads of shifting at all.
Have to re-iterate that 4.013, is an 'accident waiting to happen'. Things _will_ have a habit of having inexplicable failures with this. Some basic stuff did work (funnily in this, it was perhaps better than some of the versions up around 4.050), but it was no more than an alpha test release, in terms of being even remotely 'useable'.....
Best Wishes |
|
![](templates/subSilver/images/spacer.gif) |
|