This shows you the differences between two versions of the page.
| en:examples:storage:eeprom [2012/06/18 15:09] – created raivo.sell | en:examples:storage:eeprom [2026/02/19 11:30] (current) – external edit 127.0.0.1 | ||
|---|---|---|---|
| Line 1: | Line 1: | ||
| + | ====== EEPROM ====== | ||
| + | //Required knowledge: [HW] [[et: | ||
| + | |||
| + | ===== Theory ===== | ||
| + | [{{ : | ||
| + | EEPROM (// | ||
| + | |||
| + | When using EEPROM, it is important to remember that the lifetime of memory bytes is about 100000 write cycles. Therefore you should write only the minimum necessary data to EEPROM. | ||
| + | |||
| + | ===== Practice ===== | ||
| + | |||
| + | AVR microcontrollers have a certain amount of EEPROM built in. The HomeLab III controller ATxmega128A1U has 2 KB of EEPROM. To work with EEPROM, it is recommended to use the library already built into AVR GCC. The library defines the main functions for EEPROM access: | ||
| + | * uint8_t eeprom_read_byte (const uint8_t *addr) | ||
| + | * uint16_t eeprom_read_word (const uint16_t *addr) | ||
| + | * void eeprom_read_block (void *pointer_ram, | ||
| + | * void eeprom_write_byte (uint8_t *addr, uint8_t value) | ||
| + | * void eeprom_write_word (uint16_t *addr, uint16_t value) | ||
| + | * void eeprom_write_block (const void *pointer_eeprom, | ||
| + | * void eeprom_update_byte (uint8_t *addr, uint8_t value) | ||
| + | * void eeprom_update_word (uint16_t *addr, uint16_t value) | ||
| + | * void eeprom_update_block (const void *pointer_ram, | ||
| + | |||
| + | Simple example code for EEPROM storage. It reads a byte from address 46 and a word from address 50. Writing uses the //update// function, which reads the EEPROM location before writing and does not overwrite when the value is already correct. This saves memory cells from wear, but writing takes a bit longer. | ||
| + | |||
| + | <code c> | ||
| + | // AVR EEPROM byte and word save/read example | ||
| + | #include < | ||
| + | |||
| + | // Main program | ||
| + | int main(void) { | ||
| + | uint8_t dataByte; | ||
| + | uint8_t dataWord; | ||
| + | | ||
| + | // Write value 86 to EEPROM address 46 | ||
| + | eeprom_update_byte((uint8_t*)46, | ||
| + | // Write value 860 to EEPROM address 50 | ||
| + | eeprom_update_word((uint16_t*)50, | ||
| + | | ||
| + | // Read byte from address 46 (should be 86) | ||
| + | dataByte = eeprom_read_byte((uint8_t*)46); | ||
| + | // Read word from address 50 (should be 860) | ||
| + | dataWord = eeprom_read_word((uint16_t*)50); | ||
| + | } | ||
| + | </ | ||
| + | |||
| + | To move more data at once, use block read/write. First define a data block in RAM: | ||
| + | <code c> | ||
| + | // AVR EEPROM block save/read example | ||
| + | #include < | ||
| + | |||
| + | // Main program | ||
| + | int main(void) { | ||
| + | uint8_t dataArray1[10] = " | ||
| + | uint8_t dataArray2[10]; | ||
| + | | ||
| + | // First parameter is pointer to EEPROM block, | ||
| + | // second parameter is pointer to RAM block | ||
| + | // third parameter is dataArray length | ||
| + | eeprom_update_block((const void*)& | ||
| + | |||
| + | // First parameter is pointer to RAM block, | ||
| + | // second parameter is pointer to EEPROM block | ||
| + | // third parameter is dataArray length | ||
| + | eeprom_read_block((void*)& | ||
| + | } | ||
| + | </ | ||
| + | |||
| + | It is not always practical to remember exact EEPROM addresses. For that there is a variable attribute called EEMEM. It frees the user from managing addresses and lets the compiler do it. Note that you still must use library functions to move data in EEPROM. | ||
| + | |||
| + | <code c> | ||
| + | // AVR EEPROM EEMEM usage example | ||
| + | #include < | ||
| + | |||
| + | uint8_t | ||
| + | uint16_t EEMEM NonVolatileInt; | ||
| + | uint8_t | ||
| + | |||
| + | // Main program | ||
| + | int main(void) { | ||
| + | uint8_t | ||
| + | uint16_t SRAMint; | ||
| + | uint8_t | ||
| + | |||
| + | SRAMchar = eeprom_read_byte(& | ||
| + | SRAMint | ||
| + | eeprom_read_block((void*)& | ||
| + | } | ||
| + | </ | ||