Using EEPROM to store data after power down

The data memory of the PIC18F4550 is volatile. This means that information stored in this memory is lost when the power is switched off. In many cases this is not a problem, but sometimes it's useful that certain data, e.g. configuration data, is saved even when the board is powered down. To this end, the PIC18F4550 contains 256 bytes of non-volatile EEPROM memory besides the volatile data memory. This memory can be used to store non-volatile information.

The program below demonstrates how the EEPROM memory is used. The program changes the byte at address 0 by means of the push buttons. The north button increments the byte, the south button decrements the byte.

The most important parts of the program are the readEepromByte and writeEepromByte functions. The readEepromByte function reads one of the 256 EEPROM bytes while the writeEepromByte function writes a value to a given address in the EEPROM memory. For more information on the internal details of these functions please refer to chapter 7 of the PIC18F4550 datasheet .

Test the program in the following way: set a value using the buttons, switch the power off, and switch the power back on again. The value you have just set should appear unchanged on the LCD display.

  1. #include <p18f4550.h>
  2. #include "lcd.h"
  3. #include "delay50ms.h"
  4.  
  5. // Fuses configuration
  6. #pragma config PLLDIV = 5 // Divide by 5 (20 MHz oscillator input)
  7. #pragma config FOSC = HSPLL_HS // HS oscillator, PLL enabled, HS used by USB
  8. #pragma config IESO = OFF // Oscillator Switchover mode disabled
  9. #pragma config PWRT = OFF // PWRT disabled
  10. #pragma config BOR = OFF // Brown-out Reset enabled in hardware only (SBOREN is disabled)
  11. #pragma config WDT = OFF // HW Disabled - SW Controlled
  12. #pragma config WDTPS = 32768 // 1:32768
  13. #pragma config MCLRE = ON // MCLR pin enabled; RE3 input pin disabled
  14. #pragma config LVP = OFF // Disable low-voltage programming
  15. #pragma config CCP2MX = ON // Config3h
  16. #pragma config PBADEN = OFF // PORB digital IO on powerup
  17.  
  18.  
  19. #define byte unsigned char
  20.  
  21. #define PRESSED 0
  22. #define S_N PORTBbits.RB4
  23. #define S_S PORTBbits.RB5
  24.  
  25. #define BYTE_ADDR 0
  26.  
  27. #define TRUE 1
  28.  
  29. void writeEepromByte(byte addr, byte data) {
  30. INTCONbits.GIE = 0; // Disable interupts
  31.  
  32. EECON1bits.EEPGD = 0; // Select the EEPROM memory
  33. EECON1bits.CFGS = 0; // Access the EEPROM memory
  34. EECON1bits.WREN = 1; // Enable writing
  35. EEADR = addr; // Set the address
  36. EEDATA = data; // Set the data
  37. EECON2 = 0x55; // Write initiate sequence
  38. EECON2 = 0xaa; // Write initiate sequence
  39. EECON1bits.WR = 1; // Start writing
  40. while (!PIR2bits.EEIF)
  41. ; // Wait for write to finish
  42. PIR2bits.EEIF = 0; // Clear EEIF bit
  43.  
  44. INTCONbits.GIE = 1; // Enable interupts
  45. }
  46.  
  47. byte readEepromByte(unsigned char addr) {
  48. EECON1bits.EEPGD = 0; // Select the EEPROM memory
  49. EECON1bits.CFGS = 0; // Access the EEPROM memory
  50. EEADR = addr; // Set the address
  51. EECON1bits.RD = 1; // Start reading
  52. return EEDATA; // Return the read value
  53. }
  54.  
  55.  
  56. void main(void) {
  57. TRISB = 0xFF; // Configure port B as inputs
  58. INTCON2bits.NOT_RBPU = 0; // Enable internal pullup resistors
  59.  
  60. // Initiate the LCD
  61. initLCD();
  62. clearLCD();
  63.  
  64. while (TRUE) {
  65. // Write value stored in EEPROM to LCD
  66. setLineOnLCD(1);
  67. appendIntToLCD(readEepromByte(BYTE_ADDR));
  68.  
  69. // Change value stored in EEPROM with north and south button
  70. if (S_N == PRESSED) {
  71. writeEepromByte(BYTE_ADDR, readEepromByte(BYTE_ADDR) + 1);
  72. }
  73. if (S_S == PRESSED) {
  74. writeEepromByte(BYTE_ADDR, readEepromByte(BYTE_ADDR) - 1);
  75. }
  76.  
  77. Delay10KTCYx (200);
  78. }
  79. }