Reading and writing Atmega168 EEPROM Tutorial

Not rated 14,695

Circuit Image

EEPROM (Electrically Erasable Programmable Read-Only Memory) is non-volatile memory, meaning it retains data even after power is removed. The ATmega168 microcontroller includes 512 bytes of EEPROM, which can be utilized to store system parameters and small amounts of data. This tutorial demonstrates how to read from and write to EEPROM, including counting the number of times the device has been powered up or reset. Future examples will incorporate additional data types and explore different interactions with the EEPROM. The circuit used is based on the Character LCD Displays Part 2 post from the previous year, constructed on a breadboard. The initial step involves building a basic ATmega168 breadboard circuit, referencing the ATmega8 breadboard circuit from Parts 1 and 2, substituting the ATmega168 for the ATmega8. The default value for an erased byte is 0xFF. Lines 11 and 12 of the code set the variable `num_executions` to 0 if the EEPROM is in its erased state (e.g., during the first execution). Reading and writing an 8-bit value is nearly identical to handling a 16-bit value. Lines 20-25 illustrate the use of different functions and data types, with minor differences. In C, `void *` denotes a generic pointer, requiring casting when passing actual pointers to functions, as shown in lines 28 and 36. The `eeprom_read_block` and `eeprom_write_block` functions are versatile, capable of handling any data type, including structs or multi-dimensional arrays. In larger projects, specifying addresses for each EEPROM-stored variable can be cumbersome. The `EEMEM` attribute automates address allocation for non-volatile variables. Although these variables appear similar to standard variables, they cannot be accessed directly; instead, EEPROM read and write functions must be used, utilizing pointers to indicate the EEPROM address, as seen in lines 15, 19, 21, 26, 29, and 37. The AVRdude `-D` option can disable erasure but is not advisable, as FLASH sections not written with new firmware will remain unchanged. A more effective method is to adjust fuse settings. The ATmega168 typically ships with fuse settings of 0G—62 and 0xDF (low and high). By enabling the EESAVE bit, EEPROM erasure during the chip erase cycle can be prevented. This can be accomplished with a specific command. When compiled, an `.eep` file is generated, containing an EEPROM map that can be uploaded to the microcontroller as needed. The contents of this file can be initialized by setting the non-volatile variables accordingly. The `.eep` file can be uploaded using the command `-U eeprom:w:main.eep` in the AVRdude command line. If utilizing the make program for firmware uploads, uncommenting line 208 of the makefile is necessary.

The ATmega168 microcontroller's EEPROM functionality is crucial for applications requiring persistent data storage. The EEPROM's non-volatile nature allows it to retain critical configuration settings and operational parameters across power cycles. The integration of EEPROM read and write functions into the firmware enables developers to implement robust data handling features without the need for complex external storage solutions.

The versatility of the `eeprom_read_block` and `eeprom_write_block` functions allows for efficient data management, accommodating various data types. The use of the `EEMEM` attribute streamlines the process of managing EEPROM addresses, making it easier to handle multiple variables without manual address assignment. This is particularly beneficial in larger projects where maintaining clarity and organization in code can be challenging.

In terms of firmware development, the ability to generate an EEPROM map file during compilation provides a straightforward method for initializing EEPROM contents. This feature is essential for applications that require specific data to be preloaded into EEPROM upon deployment, ensuring that the system is ready for operation immediately after powering up.

Moreover, the fuse settings offer a critical level of control over EEPROM behavior during programming. By enabling the EESAVE bit, developers can safeguard important data against unintended erasures, enhancing the reliability of the system. This precaution is vital in applications where data integrity is paramount.

Overall, the ATmega168's EEPROM capabilities, combined with effective programming practices, empower developers to create sophisticated embedded systems that leverage persistent memory for enhanced functionality and user experience.EEPROM (Electrically Erasable Programmable Read Only Memory) Is non-volatile memory, meaning it persists after power is removed. The ATmega168 microcontroller has 512 bytes of EEPROM which can be used to store system parameters and small amounts of data.

This tutorial shows you how to read and write EEPROM. This counts how many times the device ha s been powered up or reset. In later examples we`ll be adding other datatypes and interracting with the EEPROM in slightly different ways. No need to reinvent the wheel here. We will use the circuit from the Character LCD Displays Part 2 post we did last year, but build it on a breadboard instead.

First we need to build a basic Atmega168 breadboard circuit. See Atmega8 breadboard circuit  Part 1 and Part 2 but substitute an Atmega168 for the Atmega8. You will recall that the default values for an erase byte is 0xFF. At lines 11 & 12 we set num_executions to 0 if being run against an erase EEPROM (e. g. first execution). Reading and writing the 8 bit value is almost identical to reading and writing the 16 bit value. If you look at lines 20-25 you will see different functions and datatypes being used but the differences are minor. In c, void *  is used to denote a generic pointer. When we pass real pointers to the function we need to cast them as void * . This is shown in lines 28 and 36. The eeprom_read_block and eeprom_write_block function are very versatile as they can be used with any datatype.

For example you could read/write structs or multi dimension arrays using these 2 functions. In large projects, it can be tedious to define the addresses for each EEPROM stored variable. The EEMEM attribute is used to auto allocate addresses for the non-volatile variables. Consider the following code example. Even though these variables look like any other variable, we cannot use them directly. We still need to use the EEPROM read and write functions, but this time we use a pointer to the variable to denote the EEPROM address. This can be seen in lines 15, 19, 21, 26, 29 & 37. The AVRdude -D option can disable the erasure, but this is not recommended as FLASH sections that are not being written with the new firmware will remain as they are.

A much better approach is to use fuse settings. By default the Atmega168 ships with fuse settings of 0G—62 and 0xDF (low and high). By setting the EESAVE bit, we can prevent an EEPROM erasure during the chip erase cycle. To do this, use the following command. When the program is compiled, an eep file is generated. This contains an EEPROM map which can be uploaded to the microcontroller if required. The contents of this file can be set by initializing the non-volatile variables as follows. The eep file can be uploaded to the microcontroller by adding -U eeprom:w:main. eep  to your AVRdude command string. If you are using the make program  command to upload your firmware, simply uncomment line 208 of the makefile as follows 🔗 External reference