Overview
Beside program memory and data memory, the ATMega32 contains up to 1024 bytes of internal EEPROM for auxiliary storage. It can handle up to 100,000 Write/Erase cycles. However its access time is slower than SRAM. Each registers of EEPROM are 8-bit wide unlike the internal program memory that is 16-bit wide. Program memory space is quite larger than EEPROM memory space. In the case of the ATMega32 the program memory is 32K bytes.
It's important to store user's settings data in to this non-volatile memory to prevent data lost next time the MCU turns on, or power interruption. We can also store this type of data in internal program memory (Flash Memory).
Writing And Reading EEPROM Example
The AVR LibC contains the "eeprom.h" library allow us to read and write different kind of data types inside EEPROM such as byte, word, float, etc. Even it's 8-bit wide the library handle this task for the programmers. This library has the following routines,
- eeprom_read_byte
- eeprom_read_word
- eeprom_read_dword
- eeprom_read_float
- eeprom_read_block
- eeprom_write_byte
- eeprom_write_word
- eeprom_write_dword
- eeprom_write_float
- eeprom_write_block
and other update routine. For more detail you can see the header file.
For an introductory example, the program will write a set of data of 256 addresses, and read them back.
Writing and Reading EEPROM Example |
/* * EepromEx1.c * * Created: 7/20/2023 6:53:22 PM * Author : Admin */ #include <avr/io.h> #include <avr/eeprom.h> #define F_CPU 8000000UL #include <util/delay.h> int main(void) { DDRC = 0xFF; for (uint8_t i= 0;i<0xFF;i++) eeprom_write_byte(i,i); while (1) { for (uint8_t i = 0; i<0xFF; i++) { PORTC = eeprom_read_byte(i); _delay_ms(250); } } }
Click here to download its zip file.
Using the EEMEM attribute
EEMEM attribute allow us to declare data on EEPROM space. We can read or write the data using its address. In the following example, I declare a data array on EEPROM first, and then I read those data back.
/* * EepromEx2.c * * Created: 7/20/2023 9:16:24 PM * Author : Admin */ #include <avr/io.h> #define F_CPU 8000000UL #include <util/delay.h> #include <avr/eeprom.h> const uint8_t myData[] EEMEM = {0x01,0x02,0x04,0x08,0x10,0x20,0x40,0x80}; int main(void) { DDRC=0xFF; while (1) { for (int i =0;i<sizeof(myData);i++) { char temp = &myData[i]; PORTC=eeprom_read_byte(temp); _delay_ms(1000); } } }
Schematic Diagram
Using the EEMEM attribute |
Click here to download its zip file.
Here's another example. I store constant 7-Segment data in EEPROM. The program will read them back and show it on display.
/* * EepromEx3.c * * Created: 7/20/2023 10:17:26 PM * Author : Admin */ #include <avr/io.h> #include <avr/eeprom.h> #define F_CPU 8000000UL #include <util/delay.h> /*Declare EEPROM Storage*/ const uint8_t cCathode[] EEMEM = {0x3F,0x06,0x5B,0x4F,0x66,0x6D,0x7D,0x07, 0x7F,0x6F,0x77,0x7C,0x39,0x5E,0x79,0x71}; const uint8_t cAnode[] EEMEM = {0xC0,0xF9,0xA4,0xB0,0x99,0x92,0x82,0xF8,0x80, 0x90,0x88,0x83,0xC6,0xA1, 0x86,0x8E}; int main(void) { DDRC=0xFF; DDRD=0xFF; while (1) { for (int i=0;i<sizeof(cCathode);i++) { PORTD=eeprom_read_byte(&cCathode[i]); PORTC=eeprom_read_byte(&cAnode[i]); _delay_ms(500); } } }
Displaying 7-Segment Data From EEPROM |
Click here to download its zip file.
Reading/Writing With Switches and a 7-Segment Display
In this example I use two DIP switches, one for input address while another one for input data that will write data into EEPROM. Input data is between 0 and 0x0F.
Reading/Writing With Switches and a 7-Segment Display |
With any input address change from DSW1, it will read the data from new given address.
/* * EepromEx4.c * * Created: 7/21/2023 9:21:18 AM * Author : Admin */ #include <avr/io.h> #define F_CPU 8000000UL #include <util/delay.h> #include <avr/eeprom.h> #define Write (PIND&0x08)==0 #define LED 7 /*Declare EEPROM Storage*/ uint8_t Edata[256] EEMEM; const uint8_t cAnode[] = {0xC0,0xF9,0xA4,0xB0,0x99,0x92,0x82,0xF8, 0x80,0x90,0x88,0x83,0xC6,0xA1,0x86,0x8E}; int main(void) { uint8_t oldAddr=1,newAddr=0,segment=0,inputData; DDRA=0x00; PINA=0xFF; DDRC=0xFF; PORTC=0xFF; DDRD=0x07; PORTD=0xF8; while (1) { /*Check Address Change*/ if (newAddr!=oldAddr) { segment = eeprom_read_byte(&Edata[newAddr]); oldAddr = newAddr; } PORTC = cAnode[segment]; newAddr = PINA; if (Write) { PORTC&=~(1<<LED); inputData = (PIND&0xF0)>>4; eeprom_write_byte(&Edata[newAddr],inputData); while(Write); segment = eeprom_read_byte(&Edata[newAddr]); PORTC|=(1<<LED); } } }
Click here to download source file.
The example above use the 7-Segment data that store in SRAM. We can also store and read it from EEPROM.
/* * EepromEx5.c * * Created: 7/21/2023 3:11:48 PM * Author : Admin */ #include <avr/io.h> #define F_CPU 8000000UL #include <util/delay.h> #include <avr/eeprom.h> #define Write (PIND&0x08)==0 #define LED 7 /*Declare EEPROM Storage*/ uint8_t Edata[256] EEMEM; uint8_t cAnode[] EEMEM = {0xC0,0xF9,0xA4,0xB0,0x99,0x92,0x82,0xF8, 0x80,0x90,0x88,0x83,0xC6,0xA1,0x86,0x8E}; int main(void) { uint8_t oldAddr=1,newAddr=0,segment=0,inputData,DisplayData=0; DDRA=0x00; PINA=0xFF; DDRC=0xFF; PORTC=0xFF; DDRD=0x07; PORTD=0xF8; while (1) { /*Check Address Change*/ if (newAddr!=oldAddr) { segment = eeprom_read_byte(&Edata[newAddr]); DisplayData = eeprom_read_byte(&cAnode[segment]); oldAddr = newAddr; } PORTC = DisplayData; newAddr = PINA; if (Write) { PORTC&=~(1<<LED); inputData = (PIND&0xF0)>>4; eeprom_write_byte(&Edata[newAddr],inputData); while(Write); segment = eeprom_read_byte(&Edata[newAddr]); DisplayData = eeprom_read_byte(&cAnode[segment]); PORTC|=(1<<LED); } } }
Click here to download its source file.
No comments:
Post a Comment