Goal: To write and read EEPROM
What we have: PIC16f628a and a simple devboard.
Microcontroller PIC16f628a has 128 bytes of EEPROM memory on board, not too much but we have what we have. Hi-tech PICC compiler has internal functions for work with EEPROM, but here I’m going to make some my personal functions.
Let’s look at the EECON1 register:

EEPGD – don’t use in the PIC16f628a
WRERR – error flag
• 1 – error has occurred
• 0 – operation done without errors
WREN – Permission of writing to EEPROM
• 1 – allowed
• 0 – not allowed
WR – control bit of writing
• 1 – Writing initialization
• 0 – Writing is finished
RD – control bit of reading
• 1 – Reading initialization
• 0 – Reading is finished
*Bits WR and WD can be installed only at a logic high level, they reset to logic low automatically.
There are some additional registers:
- EEDATA – 8-bit register, works as a buffer, where data is placed.
- EEADR – 7 bit register, there is an address placed for read/write operation to a single byte of EEPROM.
- Software register EECON2 – register used only for writing operation, u have to write the next sequence for successful operation:
EECON2=0x55; EECON2=0xAA;
And, of course, there is an interrupt event that could be generated, flag EEIF has a logic high value if writing operation was successfull.
Step by step reading from EEPROM:
- Write wanted address to EEADR.
- Set RD = “1”.
- Data has been collected in the EEDAT and is ready for use.
Step-by-step writing to EEPROM:
- Write wanted address to EEADR.
- Write data to EEDAT.
- Set WREN = “1”.
- Write sequence to EECON2 (0x55 and 0хАА).
- Set WR = “1”.
Also, the datasheet highly recommended to shut down interrupts for time when reading/writing operation occurs.
Example:
#include <htc.h>
#define _XTAL_FREQ 4000000
__CONFIG(MCLRDIS & UNPROTECT & WDTDIS & LVPDIS & HS);
unsigned char eeprom_read_my(unsigned char adres);
unsigned char eeprom_write_my(unsigned char data, unsigned char adres);
void main() {
unsigned char temp=0;
CMCON = 0x07; // shut down all comparators
TRISA = 0xFF;
TRISB = 0x00;
temp = eeprom_read_my(0x07); // read wanted address
for (;;) {
PORTB = temp; // value from EEPROM to PORTB
if (!RA1) {
__delay_ms(100);
if (!RA1) {
if (temp < 240) { // Write some values with step 16
temp = temp + 16;
eeprom_write_my(temp, 0x07);
} else {
temp = 16;
eeprom_write_my(temp, 0x07);
}
}
}
}
}
unsigned char eeprom_read_my(unsigned char adres) {
EEADR = adres;
RD = 1;
return EEDATA;
}
unsigned char eeprom_write_my(unsigned char data, unsigned char adres) {
GIE=0;
EEADR=adres;
EEDATA=data;
WREN=1;
EECON2=0x55;
EECON2=0xAA;
WR=1;
GIE=1;
}Example video:
Here is PORTB state:

And the EEPROM state at the moment:

There is 0х50 = 0b01010000 number at 0х07 address(B4 = 1 and B6 = 1 on the last picture).
Using built-in functions is very straightforward, so I even don’t place it here.