It is currently 20 Apr 2018 15:38

All times are UTC + 1 hour




Post new topic Reply to topic  [ 8 posts ] 
Author Message
 Post subject: Storing FLOAT in EEPROM.
PostPosted: 13 Jan 2018 00:14 
Offline

Joined: 29 Mar 2011 20:35
Posts: 115
I have a float value that I'd like to store in EEPROM, however I'm aware that a float value takes up 4 bytes, so normally I would store the lower byte, rotate right 8 spaces, store the next byte, rotate and so on.

However you don't seem to be able to rotate a float in Mikroe, is there a simple way to achieve what I'm trying to do?

Thanks, Dave.


Top
 Profile  
 
PostPosted: 13 Jan 2018 01:09 
Offline

Joined: 18 Feb 2006 13:17
Posts: 4892
These's more than one way to do it. There are built-in macros that allow for easy handling of multi-byte variables. Just add
#include <built_in.h>
to your program and then you may access the bytes in float, like
float x;

EEPROM_Write(0x10,Lo(x));
EEPROM_Write(0x11,Hi(x));
EEPROM_Write(0x12,Higher(x));
EEPROM_Write(0x13,Highest(x));
Delay_ms(20);
Lo(x)=EEPROM_Read(0x10);
Hi(x)=EEPROM_Read(0x11);
Hi(x)=EEPROM_Read(0x12);
Hi(x)=EEPROM_Read(0x13);

Or you may declare an unsigned long variable at the same space that your float variable and do the trick with shifting on it.
float x;
unsigned long lx at x;

Similarly, you could declare a union with a float and long (or array of byte) variables and access the one of the type needed at the moment, like
  union {
    float y;
    char yl[4];
  };

  y=3.14;
  EEPROM_Write(0x10,yl[0]);
  EEPROM_Write(0x11,yl[1]);
  EEPROM_Write(0x12,yl[2]);
  EEPROM_Write(0x13,yl[3]);
  Delay_ms(20);
  yl[0]=EEPROM_Read(0x10);
  yl[1]=EEPROM_Read(0x11);
  yl[2]=EEPROM_Read(0x12);
  yl[3]=EEPROM_Read(0x13);

_________________
Replacement libraries for mP PRO and PIC18 processors, mP PRO tips & trics


Top
 Profile  
 
PostPosted: 13 Jan 2018 09:32 
Offline

Joined: 24 Aug 2014 17:55
Posts: 119
Location: Sheffield
try adapting and using these
linky

http://www.xargs.com/pic/c-faq.html#eepromblock


How can I save a float, int, double, long, array, or structure to EEPROM?

void eeprom_write_block(void *ptr, unsigned short addr, unsigned char len)
{
    unsigned char *data = ptr;

    while (len--)
        eeprom_write_byte(addr++, *data++);
}

/* examples of usage: */

struct { int a; unsigned char b; } s;
unsigned int c;
float d;
unsigned char array[10];

eeprom_write_block(&s, 10, sizeof s);
eeprom_write_block(&c, 20, sizeof c);
eeprom_write_block(&d, 30, sizeof d);
eeprom_write_block(array, 40, sizeof array);

Note that this code takes advantage of C's void type to eliminate casting or the need for different functions for saving different types.

A similar method is used to read:

void eeprom_read_block(void *ptr, unsigned short addr, unsigned char len)
{
    unsigned char *data = ptr;

    while (len--)
        *data++ = eeprom_read_byte(addr++);
}

These routines assume you have a routine that can read and write byte to your EEPROM.




I use something similar my adapted code from some ccs c routines, you might have to test them first and make mods, have not been able to test em all yet
copy this below and create a c file called.....

eeprom.c

//eeprom.c file

#include <stdint.h>


//===================================================================//
//   EEPROM READ WRITE ROUTINES/
//   ADAPTED CCS C EXAMPLE FOR THE NON FLOAT ROUTINES
//   DATE 29-12-17
//==================================================================//

//=================================================================//
//        EEPROM FLOAT ROUTINES
//        VARIBLES
//  ADDR = THE ADRESS IN EEPROM WE WANT TO STORE THE DATA AT



void write_float_to_eeprom(uint16 eaddr, float datac)
{
 uint8 i;

 for(i = 0; i < 4; i++)
     EEPROM_Write(eaddr + i, *((uint8*)&datac + i) ) ;
}

//-----------------------------------------------------------------
// datac IS THE RETURNED VARIABLE FROM THE EEPRON ADDRESS ADDR
// YOUR VARIABLE MUST BE SAME AS THE datac BEING RETURNED

float read_float_from_eeprom(uint16 eaddr)
{
uint8 i;
float datac;

for(i = 0; i < 4; i++)
   *((uint8*)&datac + i) = EEPROM_Read(eaddr + i);

return(datac);
}

//================================================================//

//=================================================================//
//        EEPROM UNSIGNED INT32 ROUTINES
//        VARIBLES
//  ADDR = THE ADRESS IN EEPROM WE WANT TO STORE THE datac AT

void write_u_int32_to_eeprom(uint16 eaddr,uint32 datac)
{
 uint8 i;

 for(i = 0; i < 4; i++)
     EEPROM_Write(eaddr + i, *((uint8*)&datac + i) ) ;
}

//-----------------------------------------------------------------
// datac IS THE RETURNED VARIABLE FROM THE EEPRON ADDRESS ADDR
// YOUR VARIABLE MUST BE SAME AS THE datac BEING RETURNED

uint32 read_u_int32_from_eeprom(uint16 eaddr)
{
uint8 i;
uint32 datac;

for(i = 0; i < 4; i++)
   *((uint8*)&datac + i) = EEPROM_Read(eaddr + i);

return(datac);
}

//================================================================//

//=================================================================//
//        EEPROM UNSIGNED INT16 ROUTINES
//        VARIBLES
//  ADDR = THE ADRESS IN EEPROM WE WANT TO STORE THE datac AT

void write_u_int16_to_eeprom(uint16 eaddr,uint16 datac)
{
 uint8 i;

 for(i = 0; i < 2; i++)
     EEPROM_Write(eaddr + i, *((uint8*)&datac + i) ) ;
}

//-----------------------------------------------------------------
// datac IS THE RETURNED VARIABLE FROM THE EEPRON ADDRESS ADDR
// YOUR VARIABLE MUST BE SAME AS THE datac BEING RETURNED

uint16 read_u_int16_from_eeprom(uint16 eaddr)
{
uint8 i;
uint16 datac;

for(i = 0; i < 2; i++)
   *((uint8*)&datac + i) = EEPROM_Read(eaddr + i);

return(datac);
}

//================================================================//

//=================================================================//
//        EEPROM UNSIGNED INT8 ROUTINES
//        VARIBLES
//  ADDR = THE ADRESS IN EEPROM WE WANT TO STORE THE datac AT

void write_u_int8_to_eeprom(uint16 eaddr, uint8 datac)
{

 EEPROM_Write(eaddr,(uint8*)&datac) ;
}

//-----------------------------------------------------------------
// datac IS THE RETURNED VARIABLE FROM THE EEPRON ADDRESS ADDR
// YOUR VARIABLE MUST BE SAME AS THE datac BEING RETURNED

uint8 read_u_int8_from_eeprom(uint16 eaddr)
{
uint8 datac;
*((uint8*)&datac) = EEPROM_Read(eaddr);

return(datac);
}

//================================================================//

//^^^^^^^^^^^^^^^^^ END OF UNSIGNED ROUTINES======================//

//===================  SIGNED EEPRON READ WRITE ROUTINES==========//

//=================================================================//
//        EEPROM signed INT32 ROUTINES
//        VARIBLES
//  ADDR = THE ADRESS IN EEPROM WE WANT TO STORE THE datac AT

void write_s_int32_to_eeprom(uint16 eaddr, sint32 datac)
{
 uint8 i;

 for(i = 0; i < 4; i++)
     EEPROM_Write(eaddr + i, *((uint8*)&datac + i) ) ;
}

//-----------------------------------------------------------------
// datac IS THE RETURNED VARIABLE FROM THE EEPRON ADDRESS ADDR
// YOUR VARIABLE MUST BE SAME AS THE datac BEING RETURNED

sint32 read_s_int32_from_eeprom(uint16 eaddr)
{
uint8 i;
uint32 datac;

for(i = 0; i < 4; i++)
   *((uint8*)&datac + i) = EEPROM_Read(eaddr + i);

return(datac);
}

//================================================================//

//=================================================================//
//        EEPROM signed INT16 ROUTINES
//        VARIBLES
//  ADDR = THE ADRESS IN EEPROM WE WANT TO STORE THE datac AT

void write_sint16_eeprom(uint16 eaddr,sint16 datac)
{
 uint8 i;
 volatile signed int *data_ptr;
 data_ptr=&datac;
 for(i = 0; i < 2; i++)
     EEPROM_Write(eaddr + i,(*data_ptr++));
}

//-----------------------------------------------------------------
// datac IS THE RETURNED VARIABLE FROM THE EEPRON ADDRESS ADDR
// YOUR VARIABLE MUST BE SAME AS THE datac BEING RETURNED

sint16 read_sint16_eeprom(uint16 eaddr)
{
uint8 i;
sint16 datac;
volatile signed int *data_ptr;
*data_ptr=&datac;
for(i = 0; i < 2; i++)
*(data_ptr++) = EEPROM_Read(eaddr + i);
 //datac=data_ptr;
return(datac);
}
/*
float Eeprom_Read_Float(word addr)
{
      float result;
      byte *ptr= (byte *)&result;
      byte i;

      for (i=0;i<4;i++)
          *(ptr++)=Eeprom_Read(addr++);

      return result;
}

void Eeprom_Write_Float(word addr,float data)
{
      byte *ptr= (byte *)&data;
      byte i;

      for (i=0;i<4;i++)
            Eeprom_Write(addr++,*(ptr++));
}
*/

//================================================================//

//=================================================================//
//        EEPROM signed INT8 ROUTINES
//        VARIBLES
//  ADDR = THE ADRESS IN EEPROM WE WANT TO STORE THE datac AT

void write_sint8_eeprom(uint16 eaddr,uint8 datac)
{
volatile signed char *data_ptr;
data_ptr=&datac;
 EEPROM_Write(eaddr,*data_ptr) ;
 delay_ms(20);
 /*
x = 5;
ptr_p = &x;
y = *ptr_p;
*/
}

//-----------------------------------------------------------------
// datac IS THE RETURNED VARIABLE FROM THE EEPRON ADDRESS ADDR
// YOUR VARIABLE MUST BE SAME AS THE datac BEING RETURNED

sint8 read_sint8_eeprom(uint16 eaddr)
{
volatile signed char *data_ptr;
sint8 datac;
*data_ptr = EEPROM_Read(eaddr);
datac=data_ptr;
delay_ms(20);
return(datac);
}




^^^^^^
Obviously just for the single byte read write routines you can just use the lib read write, but i put these routines in as well
test prog


#include <built_in.h>
#include "eprom.c"




void main(void)
{
volatile  signed char *val_ptr;
volatile signed int val,k;
k=-1560;
val_ptr=&k;
val=*val_ptr;
/*
x = 5;
ptr_p = &x;
y = *ptr_p;
*/
while(1){
        write_sint16_eeprom(0x0010,k);
        k++;
        val=read_sint16_eeprom(0x0010);
        k++;
        }
}



Hope these can help

Dave

_________________
"When the bugs strike it's no good bashing your head against a brick wall, you might damage the wall"


Top
 Profile  
 
PostPosted: 13 Jan 2018 13:52 
Offline

Joined: 29 Mar 2011 20:35
Posts: 115
Thank you Janni and Dave, both interesting solutions, I'll take a look at trying these tonight.

Janni, I have to admit I've never used Union's before, but I'm self taught so that's possibly not a surprise.

Dave, bearing in mind what I've said above, from your example I guess you're casting each of the 4 parts as an 8-bit value, then moving on to the next? so rather than rotating the value, you're in fact addressing individual 8-bit chunks within the value?
this is kind of what I was thinking of doing.

Thanks, Dave.


Top
 Profile  
 
PostPosted: 13 Jan 2018 14:02 
Offline

Joined: 24 Aug 2014 17:55
Posts: 119
Location: Sheffield
davegsm82 wrote:
Thank you Janni and Dave, both interesting solutions, I'll take a look at trying these tonight.

Janni, I have to admit I've never used Union's before, but I'm self taught so that's possibly not a surprise.

Dave, bearing in mind what I've said above, from your example I guess you're casting each of the 4 parts as an 8-bit value, then moving on to the next? so rather than rotating the value, you're in fact addressing individual 8-bit chunks within the value?
this is kind of what I was thinking of doing.

Thanks, Dave.


Basically I'm no genius by any means and I just about understand it, but the code uses pointers to point to the address of the variable you want to store, i have to keep refreshing my memory on pointer usage and derefrencing.... :( , but basically yes that is what is happening.
regards
Dave

_________________
"When the bugs strike it's no good bashing your head against a brick wall, you might damage the wall"


Top
 Profile  
 
PostPosted: 13 Jan 2018 21:55 
Offline

Joined: 29 Mar 2011 20:35
Posts: 115
diode_blade wrote:

Basically I'm no genius by any means and I just about understand it.....


I think we're on a level playing field lol.

I'll try and bodge something together to work in my code, hopefully it works. Thanks for the help!

Dave.


Top
 Profile  
 
PostPosted: 15 Jan 2018 15:01 
Offline

Joined: 29 Mar 2011 20:35
Posts: 115
janni wrote:
These's more than one way to do it....
Similarly, you could declare a union with a float and long (or array of byte) variables and access the one of the type needed at the moment, like
  union {
    float y;
    char yl[4];
  };

  y=3.14;
  EEPROM_Write(0x10,yl[0]);
  EEPROM_Write(0x11,yl[1]);
  EEPROM_Write(0x12,yl[2]);
  EEPROM_Write(0x13,yl[3]);
  Delay_ms(20);
  yl[0]=EEPROM_Read(0x10);
  yl[1]=EEPROM_Read(0x11);
  yl[2]=EEPROM_Read(0x12);
  yl[3]=EEPROM_Read(0x13);


In the end this was the winner, works fine for my application and I'll also be able to re-use the union for other values rather than being dedicated to a single function.

Had to implement it like;

static union{
float yf;
char yc[4];
}


Union has to be declared as 'static' otherwise you get an error on compilation;
"Anonymous struct/union must be of static or auto variables"

Thanks Janni!

Dave.


Top
 Profile  
 
PostPosted: 15 Jan 2018 15:24 
Offline

Joined: 18 Feb 2006 13:17
Posts: 4892
davegsm82 wrote:
In the end this was the winner, works fine for my application and I'll also be able to re-use the union for other values rather than being dedicated to a single function.
Whatever fits your needs :) .

Quote:
Had to implement it like;

static union{
float yf;
char yc[4];
}


Union has to be declared as 'static' otherwise you get an error on compilation;
"Anonymous struct/union must be of static or auto variables"
Indeed, if you want unnamed union to have global scope. In my example the automatic storage-class was employed (for local variable).

_________________
Replacement libraries for mP PRO and PIC18 processors, mP PRO tips & trics


Top
 Profile  
 
Display posts from previous:  Sort by  
Post new topic Reply to topic  [ 8 posts ] 

All times are UTC + 1 hour


Who is online

Users browsing this forum: No registered users and 4 guests


You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot post attachments in this forum

Search for:
Jump to: