copyright, Peter H. Anderson, Baltimore, MD, Feb, '99
Introduction.
The PIC16F84 includes 64 bytes of on-board EEPROM. (The PIC12CE51X
also includes on-board EEPROM. However, the programming and reading is
much different).
Uses of this EEPROM include the storage of calibration constants, site dependent data, a unique
identity number and quite possibly a very limited data logger. We have also used the EEPROM
on the 16F84 to store the address of the next location in an external 24LCXX EEPROM to avoid
overwriting old data in a data logging application if the PIC is reset.
Initializing EEPROM.
When using Microchip's MPLAB, EEPROM may be initialized when the PIC is programmed;
ORG 2100H DE 1, 2, 3, 4
However, I had difficulty with this when using the High Tech Compiler as the compiler does not
support the DE directive. I tried the following with a version of PIC C dated December, '97. It
compiled. However, in examining the resulting .hex file I could not see anything close to that
produced by MPLAB.
#asm psect eedata, delta=2, abs, ovrld ORG 2100H ; starting point of EEPROM on 16F84 DB 1, 2, 3, 4 ; EEPROM locations initialized using DB #endasm
I then tried this with a version dated Dec, '98 and had better luck.
However, in looking at the hex file, it was of the form;
01 00 02 00 03 00 04 00
It appears that the DB directive is actually referencing a 16-bit quantity and the high byte is set to
zero. Note that the data is stored as low byte, followed by the high byte. Thus, every other data
location in EEPROM is zero.
I finally struck on the following;
#asm psect eedata, delta=2, abs, ovrld ORG 2100H ; starting point of EEPROM on 16F84 DW 0201H, 0403H ; EEPROM locations initialized using DW #endasm
Note that the DW directive is used. However, as the data is stored as least significant byte
followed by most significant, it is necessary to transpose the bytes. That is, if you desire 01 02,
then use DW 0201H.
Program EEPROM_1.C.
Program EEPROM_1.C illustrates this concept. It is presumed that the intent is to initialize four
locations to 1, 2, 3 and 4. However, when the DB directive is used, the data will be stored as 1,
0, 2, 0. When the data is defined using the DW directive, with the bytes transposed, the data is
stored correctly.
// EEPROM_1.C // // Illustrates how to initialize EEPROM. Illustrates the difference // between using DB and DW in initializing. // // Program reads four locations at adr 00 in EEPROM initialized // using DB directive and displays on LCD. Note that this will // display as 01, 00, 02, 00. // // Then reads first four locations at adr 10H in EEPROM which was // initialized using the DW directive. This will display as 01, // 02, 03, 04. // // Build project with EEPROM_1.C and LCD_F84.C // // copyright, Peter H. Anderson, Baltimore, MD, Feb, '99 // #include <pic.h> #include "lcd_f84.h" unsigned char read_16f84_eeprom(unsigned char adr); void main(void) { unsigned char adr, d; lcd_init(); for (adr=0x00; adr<4; adr ++) // fetch and display locations // 00 - 03 { d = read_16f84_eeprom(adr); // fetch from EEPROM lcd_hex_byte(d); // and display lcd_char(' '); } lcd_new_line(); for (adr=0x10; adr<(0x10)+4; adr++) // fetch and display locations // 10 - 13 { d = read_16f84_eeprom(adr); // fetch from EEPROM lcd_hex_byte(d); // and display lcd_char(' '); } #asm DONE: clrwdt GOTO DONE #endasm } unsigned char read_16f84_eeprom(unsigned char adr) { EEADR=adr; RD=1; // set the read bit return(EEDATA); } #asm psect eedata, delta=2, abs, ovrld ORG 2100H ; starting point of EEPROM on 16F84 DB 1, 2, 3, 4 ; EEPROM locations initialized using DB ORG 2110H DW 0201H, 0403H ; initialized using DW directive #endasm
Program EEPROM_2.C.
This program illustrates how to write to and read from EEPROM. The nature of the program is
to permit the user to perform n events and the device is no longer usable. In this case, 100 events
are authorized by initializing EEPROM to 100. Each time an LED is flashed, the EEPROM is
decremented and when at zero, the program goes into an endless loop.
This general concept might be used in a "charge for use" type system.
// EEPROM_2.C // // Illustrates how to initialize EEPROM, how to read from EEPROM and // write to EEPROM. Note that this EEPROM is the EEPROM on the // 16F84. // // EEPROM location 00 is initialized to 100 decimal in the assembler // using the DW directive. Each time function dec_count is called, // the program decrements this value and checks to see if it is at // zero. Such an arrangement might be used to limit the number of // accesses and might be used with a debit card type of application. // // Program continually flashes LED on RB4 at about 250 ms on and 250 // msec off. Loops indefinitely. However, counter in EEPROM is // decremented on each pass. Program locks when EEPROM counter is // decremented to zero. // // Note that even if power is turned off prior to the completion of // 100 flashes, the latest EEPROM value will be retained for the // subsequent run of the program. // // Build project with EEPROM_2.C and LCD_F84.C // // copyright, Peter H. Anderson, Baltimore, MD, Feb, '99 // #include <pic.h> #include "lcd_f84.h" #define LED_DIR TRISB4 // LED on RB4 #define IN 1 #define OUT 0 #define LED_PIN RB4 void flash_led(void); void write_16f84_eeprom(unsigned char adr, unsigned char d); unsigned char read_16f84_eeprom(unsigned char adr); void main(void) { unsigned char n; LED_DIR=OUT; LED_PIN = 0; while(1) { n = read_16f84_eeprom(0x00); // fetch from EEPROM if (n==0) break; // if at zero, lock up --n; write_16f84_eeprom(0x00, n); // decrement and save flash_led(); } #asm LOCK: clrwdt GOTO LOCK #endasm } void flash_led(void) { LED_PIN = 1; lcd_delay_ms(250); LED_PIN = 0; lcd_delay_ms(250); } unsigned char read_16f84_eeprom(unsigned char adr) { EEADR=adr; RD=1; // set the read bit return(EEDATA); } void write_16f84_eeprom(unsigned char adr, unsigned char d) { EEADR = adr; EEDATA = d; WREN = 1; // write enable EECON2 = 0x55; // protection sequence EECON2 = 0xaa; WR = 1; // begin programming sequnce lcd_delay_ms(20); WREN = 0; // disable write enable } #asm psect eedata, delta=2, abs, ovrld ORG 2100H ; starting point of EEPROM on 16F84 DW 0064H ; EEPROM location 00 initialized to 100 decimal #endasm