variable to EEPROM rather than SRAM. Unfortunately, this
attribute can lead to confusion later since there is nothing to
stop you from forgetting that you meant to use this variable
with the EEPROM. So, you might do something like:
uint8_t EEMEM myChar;
// BAD USE OF EEMEM
c = myChar;
If you do this, then the compiler thinks myChar is in
SRAM and loads the data from the address indicated by
myChar — which isn’t what you intended.
// CORRECT USE OF EEMEM
c = eeprom_read_byte(&myChar);
Fine. Now you know how to do it and if you mess up,
then it’s all your fault for forgetting that six months ago you
meant for myChar to be in the EEPROM. Harsh? Yeah, and
unrealistic. So, let’s apply an arbitrary programming practice
to using EEMEM: We promise to always name our variables
that we meant to have in EEPROM with the prefix EE_ so
instead of myChar, we would use EE_myChar like below:
// this is in a header we wrote six months ago
// and have now forgotten about:
uint8_t EEMEM EE_myChar;
// correct and saner use of EEMEM
c = eeprom_read_byte(&EE_myChar);
Read one byte from the EEPROM:
uint8_t eeprom_read_byte (uint8_t *addr)
Returns the byte located at addr.
Write one byte to the EEPROM:
void eeprom_write_byte (uint8_t *addr, uint8_t value)
Writes the value to addr.
Read one word from the EEPROM:
uint16_t eeprom_read_word (uint16_t *addr)
Reads the word (AVR word is 16-bit so data type is
uint16_t) at the addr.
Write one word to the EEPROM:
void eeprom_write_word (uint16_t *addr, uint16_t value)
Writes the word at addr.
54 July 2010
Read ‘n’ sequential bytes from the EEPROM:
void eeprom_read_block (void *array,void *array, uint16_t n)
Read ‘n’ bytes from the EEPROM beginning at the given
address and load them into the given array.
Write ‘n’ sequential bytes to the EEPROM:
void eeprom_write_block (void *array, void *addr, uint16_t n)
Write ‘n’ bytes from the given array into the EEPROM
beginning at the given address.
EEPROM _Test Software
One Code Module, Four Devices
The EEPROM_Test software allows us to test each of
the avrlibc EEPROM functions. It is written so that you can
use it with four different development environments.
Changing one line of code causes it to compile for one of
the four. You can use it with AVRStudio and an AVR
Butterfly, or the BeAVR (ATmega644 we discussed in
WS22), or an Arduino board. Plus, you can use it with the
Arduino board in the Arduino IDE, all by changing one
line of code! How cool is that?
Well, as usual, there is a price. This works because the
code is cluttered with ‘#if defined’ statements that cause
the compiler to only look at certain sections of the code.
As the user, you get to look at it all whether you need to
or not. For instance, if you are using an Arduino with
AVRStudio, you couldn’t care less about the Butterfly
oscillator calibration; the compiler ignores that section –
but the code is there for you to see, anyway. It doesn’t get
compiled, so it doesn’t inflate the Arduino code, but it does
add text you have to look past. It’s a trade-off that you’ll
need to get used to if you advance in C programming.
You get to tell the compiler to generate code for one
of the following:
Arduino // Arduino ATmega328 board with Arduino
IDE - 57600 baud
ATmega328 // Arduino board with AVRStudio/WinAVR
- 57600 baud
ATmega644 // BeAVR board - 16 MHz clock - 57600
Butterfly // The good old Butterfly - ATmega169
- 19200 baud
You tell the compiler which one you want to use by
removing the comment directive ‘\\’ that is in front of the
device that you will be using. Make sure the other devices
have that ‘\\’ in front of them or there is no telling what
you’ll get. This is how you would select the Butterfly:
Finally, note that if you select ‘Arduino,’ you must use
the Arduino IDE for compiling. If you select ‘ATmega328,’
you can use the Arduino hardware but must compile using
AVRStudio/WinAVR. Also, when using AVRStudio make
sure that you select the correct AVR device in the AVR
Studio Project/Configuration Options window. If you get a