Login

Lost your password?
Don't have an account? Sign Up

Internal EEPROM Read Write program for PIC18F4550

EEPROM of PIC18F (PIC18F4550 Microcontroller)

Would you like to join our comprehensive practical video course on the PIC18F4550 Microcontroller?

Introduction: Internal EEPROM of the PIC18F4550

The PIC18F4550 microcontroller features an internal Electrically Erasable Programmable Read-Only Memory (EEPROM) that provides non-volatile data storage. This means the data remains even after the power is turned off.

The EEPROM is ideal for saving configuration settings, calibration data, and other user parameters that must persist across resets. Understanding how to read and write EEPROM data is essential for developing reliable and intelligent embedded systems.

Prerequisites

Before starting this topic, readers should have:

  • Basic knowledge of PIC18F4550 architecture and memory organization.
  • Experience with MPLAB X IDE and XC8 compiler.
  • Understanding of GPIO programming and C programming basics.
  • Optionally reviewed the blog on Timers (used for simple delays) and CCP Module (for timing assistance).

EEPROM Overview

The PIC18F4550 provides 256 bytes of internal data EEPROM that can be individually read or written. Unlike Flash memory, EEPROM allows byte-level access without erasing the entire block.

Key characteristics include:

  • 256 × 8-bit storage capacity.
  • Separate address space from program memory.
  • Byte-by-byte read and write capability.
  • Data retention for over 40 years and write endurance of 1,000,000 cycles.

EEPROM Memory Registers

The EEPROM operation relies on a few key registers:

  • EEADR – Holds the address of the byte to be accessed.
  • EEDATA – Holds the data byte to be written or read.
  • EECON1 – Controls the EEPROM read/write operation.
  • EECON2 – A special register used for write unlock sequence (not physically implemented).

EEPROM Write Procedure

Writing to EEPROM involves a protected sequence to prevent accidental writes.

Steps to Write a Byte
  1. Load the target address into EEADR.
  2. Load the data byte into EEDATA.
  3. Clear the EEPGD bit to select data EEPROM.
  4. Clear CFGS to select EEPROM memory.
  5. Set WREN = 1 to enable writing.
  6. Disable interrupts to protect the sequence.
  7. Write 0x55 then 0xAA to EECON2 (unlock sequence).
  8. Set WR = 1 to start the write operation.
  9. Wait for WR = 0 (write complete).
  10. Clear WREN to disable further writes.

Example Code (EEPROM Write)
#include <xc.h>

void EEPROM_Write(unsigned char address, unsigned char data)
{
    while (WR);                 // Wait for previous write
    EEADR = address;            // Set address
    EEDATA = data;              // Load data
    EECON1bits.EEPGD = 0;       // Select data EEPROM
    EECON1bits.CFGS = 0;        // Access EEPROM memory
    EECON1bits.WREN = 1;        // Enable write
    INTCONbits.GIE = 0;         // Disable interrupts
    EECON2 = 0x55;              // Required unlock sequence
    EECON2 = 0xAA;
    EECON1bits.WR = 1;          // Start write
    while (EECON1bits.WR);      // Wait until done
    EECON1bits.WREN = 0;        // Disable write
    INTCONbits.GIE = 1;         // Re-enable interrupts
}
C

EEPROM Read Procedure

Reading from EEPROM is simpler and does not require unlock sequences.

Steps to Read a Byte
  1. Load the address into EEADR.
  2. Clear EEPGD to select EEPROM.
  3. Clear CFGS.
  4. Set RD = 1 to initiate the read.
  5. Read the data from EEDATA.

Example Code (EEPROM Read)
unsigned char EEPROM_Read(unsigned char address)
{
    EEADR = address;            // Set address
    EECON1bits.EEPGD = 0;       // Select EEPROM
    EECON1bits.CFGS = 0;
    EECON1bits.RD = 1;          // Start read
    return EEDATA;              // Return data
}
C

Example Application

A common use case is storing the brightness level of an LED or calibration values that should persist after a reset.

Example: Save and Retrieve LED Brightness
#define BRIGHTNESS_ADDR 0x10

void Save_Brightness(unsigned char level) {
    EEPROM_Write(BRIGHTNESS_ADDR, level);
}

unsigned char Load_Brightness(void) {
    return EEPROM_Read(BRIGHTNESS_ADDR);
}
C

This simple logic lets your device remember user preferences such as display brightness or temperature set-points.

Important Considerations

  • Do not perform frequent writes in loops — EEPROM has limited write cycles.
  • Use flags or buffers to avoid unnecessary write operations.
  • Ensure interrupts are disabled during write operations to prevent corruption.

Code Example
//EEPROM of PIC18F ===========================================================
// Program: EEPROM Read and Write Example for PIC18F4550
// Compiler: XC8
// Author: Bitziga Technologies
//===========================================================

#include <xc.h>

// Configuration bits
#pragma config FOSC = HSPLL_HS  // High-speed oscillator, PLL enabled
#pragma config WDT = OFF        // Watchdog Timer disabled
#pragma config LVP = OFF        // Low Voltage Programming disabled
#pragma config PBADEN = OFF     // PORTB<4:0> digital on reset

#define _XTAL_FREQ 20000000     // 20 MHz Crystal Frequency
#define LED     LATBbits.LATB0  // LED connected to RB0
#define BUTTON  PORTBbits.RB1   // Push button on RB1
#define EEPROM_ADDR 0x10        // EEPROM address to store data

//-----------------------------
// Function Prototypes
//-----------------------------
void EEPROM_Write(unsigned char address, unsigned char data);
unsigned char EEPROM_Read(unsigned char address);
void Init_Ports(void);

//===========================================================
// Main Function
//===========================================================

void main(void)
{
    unsigned char stored_data = 0;
    Init_Ports();                    // Initialize ports

    // Read stored value from EEPROM on startup
    stored_data = EEPROM_Read(EEPROM_ADDR);

    // Display last stored value (0 or 1) on LED
    LED = stored_data;

    while (1)
    {
        // If button pressed, toggle LED and save to EEPROM
        if (BUTTON == 0)             // Active low button
        {
            __delay_ms(50);          // Debounce delay
            if (BUTTON == 0)
            {
                LED = !LED;           // Toggle LED
                EEPROM_Write(EEPROM_ADDR, LED); // Save state
                while (BUTTON == 0);  // Wait until release
            }
        }
    }
}

//===========================================================
// Function: EEPROM_Write
// Description: Writes a byte to internal EEPROM
//===========================================================

void EEPROM_Write(unsigned char address, unsigned char data)
{
    while (EECON1bits.WR);          // Wait for previous write
    EEADR = address;                // Set address
    EEDATA = data;                  // Set data
    EECON1bits.EEPGD = 0;           // Access data EEPROM
    EECON1bits.CFGS = 0;            // Access EEPROM not config
    EECON1bits.WREN = 1;            // Enable writes

    INTCONbits.GIE = 0;             // Disable interrupts
    EECON2 = 0x55;                  // Required unlock sequence
    EECON2 = 0xAA;
    EECON1bits.WR = 1;              // Start write
    while (EECON1bits.WR);          // Wait until complete
    EECON1bits.WREN = 0;            // Disable writes
    INTCONbits.GIE = 1;             // Enable interrupts
}

//===========================================================
// Function: EEPROM_Read
// Description: Reads a byte from internal EEPROM
//===========================================================

unsigned char EEPROM_Read(unsigned char address)
{
    EEADR = address;                // Set address
    EECON1bits.EEPGD = 0;           // Access data EEPROM
    EECON1bits.CFGS = 0;            // Access EEPROM not config
    EECON1bits.RD = 1;              // Start read
    return EEDATA;                  // Return data
}

//===========================================================
// Function: Init_Ports
// Description: Initialize I/O ports for LED and button
//===========================================================

void Init_Ports(void)
{
    TRISBbits.TRISB0 = 0;           // RB0 as output (LED)
    TRISBbits.TRISB1 = 1;           // RB1 as input (Button)
    LED = 0;                        // LED off initially
}
C

Working Principle

  1. When the system starts, it reads the last saved LED state from EEPROM and updates the LED.
  2. Pressing the push button toggles the LED and stores the new state (0 or 1) in EEPROM.
  3. After a reset or power-off, the LED retains its last state because the value is fetched from EEPROM.

Output Observation

  • Initially, the LED will reflect the stored state.
  • Each button press toggles the LED and updates the EEPROM.
  • After resetting the board, the LED restores the previous state automatically.

Applications

  • Storing system flags or user preferences.
  • Maintaining device mode (ON/OFF) across power cycles.
  • Retaining calibration or configuration data.

Summary

This example demonstrates how to use the internal EEPROM of the PIC18F4550 to store data permanently. It’s an essential skill for embedded developers who need non-volatile memory in their designs.

Do you want to go beyond just configuring the EEPROM of PIC18F and build complete projects?
🎓 Join our Complete Practical Video Course on PIC18F4550 Microcontroller
Get step-by-step guidance on USB, I²C, SPI, UART, ADC, and more — with real circuits and projects!

Datasheet: EEPROM of PIC18F (PIC18F4550 Microcontroller)

Q1. What is the purpose of EEPROM in the PIC18F4550?

EEPROM (Electrically Erasable Programmable Read-Only Memory) is a non-volatile memory used to store data permanently, even after the power is turned off. It is ideal for saving user settings, calibration data, or device states.

Q2. How much EEPROM memory does the PIC18F4550 have?

The PIC18F4550 has 256 bytes of internal EEPROM memory, which can be accessed for both read and write operations using program code.

Q3. Can I write to EEPROM continuously in my program?

Writing too frequently can reduce the EEPROM’s lifespan because it has a limited number of write cycles (typically 100,000 writes). It’s recommended to use buffering or write only when data changes.

Q4. What is the difference between EEPROM and Flash memory in PIC18F4550?

EEPROM is designed for storing small amounts of data that need frequent updates, while Flash memory stores the program code and is not typically used for variable data storage.

Q5. Is it necessary to disable interrupts while writing to EEPROM?

Yes, disabling interrupts during EEPROM writes ensures the correct sequence and prevents accidental corruption of data.

Q6. How can I verify if data was correctly written to EEPROM?

You can perform a read operation immediately after writing and compare the read value with the intended data to verify a successful write.

Q7. Can I simulate EEPROM read/write operations in Proteus?

Yes, Proteus fully supports EEPROM simulation for PIC18F4550. You can observe the LED and button behavior as shown in the circuit diagram to verify your code functionality.

Q8. What tools are required to compile and upload this program?

You’ll need MPLAB X IDE, XC8 Compiler, and optionally Proteus for circuit simulation. A programmer such as PICkit 3 or PICkit 4 can be used for real hardware programming.

Home » Recent posts » Learn › eeprom of pic18f

https://bitziga.com

Leave a Comment

Your email address will not be published. Required fields are marked *

*
*