CCS C Software and Maintenance Offers
FAQFAQ   FAQForum Help   FAQOfficial CCS Support   SearchSearch  RegisterRegister 

ProfileProfile   Log in to check your private messagesLog in to check your private messages   Log inLog in 

CCS does not monitor this forum on a regular basis.

Please do not post bug reports on this forum. Send them to CCS Technical Support

EEPROM Garbage value

 
Post new topic   Reply to topic    CCS Forum Index -> General CCS C Discussion
View previous topic :: View next topic  
Author Message
waheed



Joined: 19 May 2012
Posts: 26
Location: Pakistan

View user's profile Send private message

EEPROM Garbage value
PostPosted: Wed May 30, 2012 3:36 am     Reply with quote

Controller: 18f452
Compiler v4.125

The program increments the 3 variables every time PIN_E0 is pressed and stores the values to EEPROM and resets cpu every time PIN_E1 is pressed.

Code:

#include <18F452_new.h>
#fuses NOWDT,HS,NOPROTECT
#use delay(clock=20000000)
#ROM int8 0xF00000 = {1, 2, 3, 4, 5}
#include <stdlib.h>
#include <dt_lcd_v01.c>

unsigned int8 lockout=0;
unsigned int8 minutes;
unsigned int16 hours;

//////////////////////////////////////////////////////////
////***            EEPROM WRITE (16 BIT)           ***////
//////////////////////////////////////////////////////////

void write_int16_eeprom(int8 n, int16 data)
{
int i;
int16 add;
add = (&data);
for (i=0; i<3; i++)
      {
      write_eeprom( i + n , *(i + add) );
      }
}

//////////////////////////////////////////////////////////
////***            EEPROM READ (16 BIT)            ***////
//////////////////////////////////////////////////////////

int16 read_int16_eeprom(int8 n)
{
int i;
int16 add;
int16 data;
add = (&data);
for (i=0; i<3; i++)
   {
    *(add+ i) = read_eeprom (i + n);
   }
return (data);
}

//////////////////////////////////////////////////////////
////***              MAIN PROGRAM               ***////
//////////////////////////////////////////////////////////

void main()
{
set_tris_a(0);
dt_lcd_init();
dt_lcd_clear_screen();
lockout = read_eeprom(1);
minutes = read_eeprom(2);
hours   = read_int16_eeprom(3);
while (1)
{
if (input(PIN_E0)== 0)
{
lockout++;
minutes = minutes+2;
hours = hours+3;
}
dt_lcd_gotoxy(0,0);printf(dt_lcd_printchar,"Lockout:   %d",lockout);
dt_lcd_gotoxy(0,1);printf(dt_lcd_printchar,"minutes:   %d",minutes);
dt_lcd_gotoxy(0,2);printf(dt_lcd_printchar,"hours  :   %Lu",hours);
if (input(PIN_E1)== 0)
   {
   write_eeprom(1,lockout);
   write_eeprom(2,minutes);
   write_int16_eeprom(3,hours);
   reset_cpu();
   }
}
}


When the program runs, it shows some initial values:
lockout = 2
minutes = 3
hours = 1284

I want these values set to 0.

I have already tried writing 0s to eeprom first but that didn't work.

If I set these values to 0 in the main function then variables will initialize every time at 0 and whole point of preserving the values is lost.
Mike Walne



Joined: 19 Feb 2004
Posts: 1785
Location: Boston Spa UK

View user's profile Send private message

PostPosted: Wed May 30, 2012 4:57 am     Reply with quote

You're trying to do too much.

You think you have a problem reading and writing eeprom.

Divide and conquer.

Reduce your code to the point where you're testing your problem area ONLY, one byte at a time.

Then put the rest back in.

Mike
Ttelmah



Joined: 11 Mar 2010
Posts: 19520

View user's profile Send private message

PostPosted: Wed May 30, 2012 5:00 am     Reply with quote

The obvious really big mistake, is size. An int16, is two bytes, but you try to store/read 3. 0,1,2.....

Best Wishes
RF_Developer



Joined: 07 Feb 2011
Posts: 839

View user's profile Send private message

PostPosted: Wed May 30, 2012 5:03 am     Reply with quote

Your read and write routines are too complex and are wrong: they try to read and write 3 bytes for each int16!

Here are my versions:

Code:

void write_int16_eeprom(int16 address, int16 data)
{
   // Portable version
//   write_eeprom(address, data & 0xFF);
//   write_eeprom(address + 1, data >> 8);

   // Non-portable version: CCS only.
   write_eeprom(address, make8(data, 0));
   write_eeprom(address + 1, make8(data, 1));
}

/******************************************************************************/

int16 read_int16_eeprom(int16 address)
{
   // Portable version
   // return read_eeprom(address) | (int16)read_eeprom(address + 1) << 8;
   // Non-portable, but faster version for CCS only.
   return make16(read_eeprom(address + 1), read_eeprom(address));
}


RF Developer


Last edited by RF_Developer on Wed May 30, 2012 5:04 am; edited 1 time in total
temtronic



Joined: 01 Jul 2010
Posts: 9229
Location: Greensville,Ontario

View user's profile Send private message

PostPosted: Wed May 30, 2012 5:04 am     Reply with quote

q1. What controls the PIN_E0 ? If a simple swtich or pushbutton you will have serious 'bounce' to deal with.You'll need to 'cleanup' the signal !

q2...
unsigned int8 lockout=0;
unsigned int8 minutes;
unsigned int16 hours;
...
this code forces lockout to 0, but only reserves space for minutes and hours.Unless YOU put something there, it WILL be a random value.

q3. You should add 'PUT' to the fuses options.It'll help 'stabilze' the PIC.

q4. You may want to add a 'delay_ms(500)' after your LCD init code,just before the MAIN loop. Again to get the PIC 'stable'.
ezflyr



Joined: 25 Oct 2010
Posts: 1019
Location: Tewksbury, MA

View user's profile Send private message

PostPosted: Wed May 30, 2012 6:42 am     Reply with quote

Hi,

Another really important question that is being overlooked is where did you get that code? If you wrote it yourself, I would assume that you would have enough understanding of the code to troubleshoot it too.

What does this line of code do?

Code:

#ROM int8 0xF00000 = {1, 2, 3, 4, 5}


Answer: it "preloads" EEPROM locations 0 thru 4 with the values 1, 2, 3, 4, 5 during chip programming. If you want everything to be zeroed the very first time you run the program, just leave out that line as the EEPROM defaults to all 0's after chip programming.

This code
Code:

lockout = read_eeprom(1);
minutes = read_eeprom(2);


is working exactly right. It's reading the preloaded values of 2, and 3 from EEPROM locations 1 and 2.

This comes up over and over on the forums. You can't simply cut-n-paste code that you find elsewhere, cobble it together, and then expect it to work out of the box. There is nothing wrong with "re-using" code from others, but you've absolutely got to understand it, and then when it doesn't work, learn to divide your program into manageable bits, and troubleshoot them separately until the program does what you want!

If it were me, I'd start by writing a simple program to write one EEPROM location, and then read it right back. If that worked OK, I'd try to write two EEPROM locations, and so on until I had built the entire program.

John
Mike Walne



Joined: 19 Feb 2004
Posts: 1785
Location: Boston Spa UK

View user's profile Send private message

PostPosted: Wed May 30, 2012 7:46 am     Reply with quote

Quote:
If you want everything to be zeroed the very first time you run the program, just leave out that line as the EEPROM defaults to all 0's after chip programming.
The EEPROM on my PIC16F877 defaults to 0xFF after programming.


The code below was loaded into a PIC16F877 on a PICDEM 2 PLUS board.
Button A4 pulls down when pressed.
Code advances test_value in EEPROM location 0 when A4 held down.
Test_value resumes from old value after any reset.

Code:
#include <16F877.h>

#fuses HS,NOWDT,NOLVP
#use delay(clock=4000000)    //one instruction=1us
#use rs232(baud=9600, xmit=PIN_c6, rcv=PIN_c7)

int test_value;

void main()
{
  test_value = 0;
  while (1)
  {
    if (input(pin_A4) == 0 )
    {
      test_value = read_eeprom(0);
      printf ("Old value from eeprom = %d \r" , test_value) ;
      test_value++;
      printf ("New value to eeprom = %d \r\r" , test_value) ;
      write_eeprom(0,test_value);
      delay_ms(100);
    }
  } 
}


Mike
ezflyr



Joined: 25 Oct 2010
Posts: 1019
Location: Tewksbury, MA

View user's profile Send private message

PostPosted: Wed May 30, 2012 8:11 am     Reply with quote

Hi Mike,

Yeah, you are correct, I was thinking about something else. If he absolutely needs to read the EEPROM right off the bat, and see '0' values he can change the #ROM directive to:

Code:

#ROM int8 0xF00000 = {0, 0, 0, 0, 0}


Actually, a better way to do it that uses the compiler to obtain the address of the EEPROM is this:

Code:

#ROM int8 getenv("EEPROM_ADDRESS") = {0, 0, 0, 0, 0}


This method is "transportable" from chip to chip without requiring you to explicitly define the EEPROM address.

John
asmboy



Joined: 20 Nov 2007
Posts: 2128
Location: albany ny

View user's profile Send private message AIM Address

PostPosted: Wed May 30, 2012 8:30 am     Reply with quote

And of course none of these approaches offers any protection
for invalid eeprom data values.

That's what an added CRC word or check sum Byte( or word) for each stored value adds to the value of the code.

I have never made use of eeprom for any important stored value without such protection, as blind, unverified trust in an eeprom stored parameter can lead to another cascade of trouble in runtime.
It also inherently catches and allows recovery /default trapping for un-inited data too.

Just my 2 cents
Mike Walne



Joined: 19 Feb 2004
Posts: 1785
Location: Boston Spa UK

View user's profile Send private message

PostPosted: Wed May 30, 2012 2:07 pm     Reply with quote

Quote:
And of course none of these approaches offers any protection
for invalid eeprom data values.
Agreed.

Mike
Display posts from previous:   
Post new topic   Reply to topic    CCS Forum Index -> General CCS C Discussion All times are GMT - 6 Hours
Page 1 of 1

 
Jump to:  
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 vote in polls in this forum


Powered by phpBB © 2001, 2005 phpBB Group