Documenti di Didattica
Documenti di Professioni
Documenti di Cultura
Home
ARM Cortex Tutorials
AVR Tutorials
MSP430 Tutorials
Contact
Forum
Activity
Links
PCB Fab
AVR microcontrollers have some amount of EEPROM memory on chip. For instance Atmega328 has 1K of byte addressable EEPROM.
EEPROM memory can be used to store and read variables during program execution and is nonvolatile. It means that it retains values
when power supply is off. EEPROM memory comes handy when we need to store calibration values, remember program state before
powering off (or power failure) or simply store constants in EEPROM memory when you are short of program memory space especially
when using smaller AVRs. Think of simple security system – EEPROM is ideal place to store lock combinations and code sequences and
passwords. AVR Datasheets claim that EEPROM can withhold at least 100000 write/erase cycles.
Accessing EEPROM
Standard C functions don’t understands how one or another memory is accessed. So reading and writing EEPROM has to be done by
following special logical system. Simple EEPROM byte read and write operations has to be done via special registers. Atmega328 has
following registers to control EEPROM:
A s Atmega328 has 1K of EEPROM memory highest cell address will be 0x3FF meaning that only 10 bits of 16-bit EEAR register are
needed. EEPROM writing process is controlled via EECR register. In order to avoid failures there is some sequence of writing process:
You will find nice read and write examples in datasheet, so there is no need to repeat this here. Lets do more interesting thing – use an
interrupt to write to EEPROM. As you may know Atmega328 has one dedicated interrupt EE_READY_vect, that may be set to occur every
time when EEPROM becomes ready for writing or reading. Usually you would have to poll for EEPE bit become zero in loop – this require
active processing power. Interrupt driven EEPROM writing may be more efficient especially when memory blocs has to be accessed. Lets
write simple Interrupt driven AVR EEPROM writing routine and write to it a simple message string.
1 #include <avr/io.h>
2 #include <avr/interrupt.h>
3 //EEPROM address initial 0
4 volatile uint16_t eepromaddress;
5 //string array index initial 0
6 volatile uint8_t i;
7 //message to be written to EEPROM
8 uint8_t message[] ="Write to EEPROM";
9 //EEPROM writing ISR
10ISR(EE_READY_vect)
11{
12/*check if not end of string and address
13didn't reach end of EEPROM*/
14if ((message[i])&&(eepromaddress<=E2END))
15{
16 //loads address and increments for next load
17 EEAR=eepromaddress++;
18 //loads current byte and increments index for next load
19 EEDR=message[i++];
20 //master write enable
21 EECR|=(1<<EEMPE);
22 //strobe eeprom write
23 EECR|=(1<<EEPE);
24}
25else
26{
27 //disable eeprom ready interrupt
28 EECR &= ~(1<<EERIE);
29}
30}
31int main(void)
32{
33//Enable eeprom ready interrupt
34EECR |= (1<<EERIE);
35//enable global interrupts
36sei();
37 while(1)
38 {
39 //do other tasks or sleep
40 }
41}
As you can see ISR simply takes bytes from message buffer and writes it to EEPROM memory until buffer is empty or EEPROM end is
reached. Using EE_READY interrupt leaves EEPROM writing completely to hardware and frees MCU resources for other tasks. In other
words EEPROM itself asks for another byte when ready. This way you improve performance and reduce power consumption. Same
interrupt source can be used for reading EEPROM.
1#include <avr/eeprom.h>
This opens access to several useful routines that allow us to read/write/update bytes, words, double words , floats and even memory
blocks. Lets see how simple byte write and read looks when using eeprom.h library.
1 #include <avr/io.h>
2 #include <avr/eeprom.h>
3 //use last EEPROM cell
4 #define EEADDR 0x3FF
5 //data will be written to EEPROM
6 #define EEDATA 100
7 int main(void)
8 {
9 //put EEPROM data to this variable
10volatile uint8_t EEByte;
11//write EEPROM
12eeprom_write_byte ((uint8_t*)EEADDR, EEDATA);
13//read from EEPROM
14EEByte = eeprom_read_byte((uint8_t*)EEADDR);
15while(1)
16{
17 //do nothing
18}
19}
We have written number byte value of 100 to EEPROM address location 0x3FF and read back to some variable. Same expressions can be
used if you need to write word, double word or or even float. Just use one of prop[er functions like eeprom_read_word().
You can write, read and update memory blocks in EEPROM. Functions may not look usual to some of you they use void pointers instead
usual data-types like uint8_t. Good thing is that these functions are universal allowing to deal with any data type. Lets see how this works.
Lets take eeprom_write_block() function it has three arguments:
1 #include <avr/io.h>
2 #include <avr/eeprom.h>
3 //start from first EEPROM cell
4 #define EEADDR 0
5 //block size to be copied
6 #define BLKSIZE 16
7 //message to be written to EEPROM
8 uint8_t message[] ="Write to EEPROM";
9 int main(void)
10{
11//where block has to be read
12uint8_t readblock[BLKSIZE];
13//write block EEPROM
14eeprom_write_block((const void *)message, (void *)EEADDR, BLKSIZE);
15//read block from EEPROM
16eeprom_read_block ((void *)readblock, (const void *)EEADDR, BLKSIZE);
17while(1)
18{
19 //do nothing
20}
21}
As we see in example we only need to typecast pointers to a void pointers like (void *)readblock so they meet function requirements – this
action doesn’t affect pointer value itself. Our real concern now is to read and write correct number of bytes and that’s it.
1 #include <avr/io.h>
2 #include <avr/eeprom.h>
3 #define BLKSIZE 16
4 #define DATA 0x10
5 uint8_t EEMEM eechar;
6 uint16_t EEMEM eeword=0x1234;
7 uint8_t EEMEM eestring[] = "Write to EEPROM";
8 int main(void)
9 {
10uint16_t sramword;
11//where block has to be read
12uint8_t readblock[BLKSIZE];
13//write byte to location eechar
14eeprom_write_byte(&eechar, DATA);
15sramword=eeprom_read_word(&eeword);
16//read block from EEPROM
17eeprom_read_block ((void *)readblock, (const void *)eestring, BLKSIZE);
18while(1)
19{
20 //do nothing
21}
22}
Here we have some initial values assigned to EEPROM variables. But these have to be stored in EEPROM memory. Compiler recognizes
these values and creates separate .eep file along with .hex.
When chip is being flashed, .eep file also has to be uploaded in order to have initial EEPROM values. Otherwise your program will fail trying
to use them.
This is end of another tutorial. Comments and corrections are always welcome.
China's Largest PCB Prototype Manufacturer, 290,000+ Customers & 8,000+ Online Orders Per Day
Share this:
Click to share on Facebook (Opens in new window)
Click to share on Google+ (Opens in new window)
Click to share on Twitter (Opens in new window)
Click to share on Reddit (Opens in new window)
Click to share on LinkedIn (Opens in new window)
4 Comments
1. DT
January 5, 2011 at 2:02 am
uint8_t readblock[15];
2. admin
January 5, 2011 at 2:06 am
3. bud
March 27, 2011 at 9:17 am
thank you this is the most complete eeprom tut i have found yet
4. FAITH + 1
June 10, 2016 at 8:30 pm
nice tutorial.
Leave a Reply
Connect with:
Your email address will not be published. Required fields are marked *
Comment
Name *
Email *
Website
Post Comment
Search
Recent Comments
Categories
68HC Projects
Arduino
ARM Cortex
ARM Cortex Tutorial
ARM7 Projects
ARM9 Projects
AVR Projects
AVR Tutorial
BASIC Stamp
ChipKIT Projects
CPLD Projects
DSP Projects
dsPIC
FPGA Projects
Handy Circuits
Linux board projects
Misc
MSC-51 Projects
MSP430 Projects
MSP430 Tutorial
Netduino
Other MCU Projects
PIC Projects
PIC32
Raspberry Pi Tutorial
Technology
Uncategorized
ZiLOG
Archives
We Recommend
Recent Tutorials
Login
Username
Password
Remember Me
Login →
Register
Lost Password
Connect with:
Users Online
17 Users Online
This website uses cookies to improve your experience. We'll assume you're ok with this, but you can opt-out if you wish.Accept Read More
Skip to toolbar
About WordPress
WordPress.org
Documentation
Support Forums
Feedback
Log in
Register
Search Search