Turn-key PCB assembly services in prototype quantities or low-volume to mid-volume production runs

Tip on storing initial values in EEPROM of AVR microcontroller

AVR microcontrollers have EEPROM memory built-in, which adds a lot of abilities to store constant values, calibration data, and other data that may be read and changed at any time during program flow. I have used EEPROM for storing the last device configuration on a couple of projects, e.g., in TDA7313 volume, BASS, TREBLE input, and output channel information is updated each time when it has been changed. After the device is turned ON, it reads the last saved settings from EEPROM memory and restores the last device state. But what happens when you turn the device for the first time. It has to read initial values that have to be stored or read ‘FF,’ which may lead to a crash or something else. One way is to prepare a separate *.eep file with initial EEPROM data and then burn it separately to microcontrollers EEPROM. But this may not always be handy.

So this is a simple trick to store initial values to EEPROM at the first microcontroller run and skip this part later without additional files needing to be flashed in. Probably others are doing a bit. Differently, this is how I do.

#include <avr/eeprom.h>
//Define EEPROM locations for restoring state
#define E_VOLUME 0
#define E_LF 1
#define E_RF 2
#define E_LR 3
#define E_RR 4
#define E_ch 5
#define E_BASS 6
#define E_TREBLE 7
#define E_INIT 8

After main() I add following code:

//------EEPROM initial values-------------
if (eeprom_read_byte((uint8_t*)E_INIT)!='T')
{
eeprom_write_byte((uint8_t*)E_VOLUME,0x0F);//0dB
eeprom_write_byte((uint8_t*)E_LF,0x80);//0dB
eeprom_write_byte((uint8_t*)E_RF,0xA0);//0dB
eeprom_write_byte((uint8_t*)E_LR,0xC0);//0dB
eeprom_write_byte((uint8_t*)E_RR,0xE0);//0dB
eeprom_write_byte((uint8_t*)E_ch,0x58);//ch1 0dB, Loudness OFF
eeprom_write_byte((uint8_t*)E_BASS,0x6F);//0dB
eeprom_write_byte((uint8_t*)E_TREBLE,0x7f);//0dB
eeprom_write_byte((uint8_t*)E_INIT,'T');//marks once that eeprom init is done
//once this procedure is held, no more initialization is performed
}

//--------Restore values from EEPROM------
ST.value[0]=eeprom_read_byte((uint8_t*)E_VOLUME);
ST.value[1]=eeprom_read_byte((uint8_t*)E_BASS);
ST.value[2]=eeprom_read_byte((uint8_t*)E_TREBLE);
ST.value[3]=eeprom_read_byte((uint8_t*)E_ch);
ST.value[4]= ST.value[3]&0b00011000;//restore gain
ST.LD=ST.value[3]&0b00000100;//restore Laudness
ST.MT=0;//default Mute OFF
ST.value[5]=eeprom_read_byte((uint8_t*)E_LF);
ST.value[6]=eeprom_read_byte((uint8_t*)E_RF);
ST.value[7]=eeprom_read_byte((uint8_t*)E_LR);
ST.value[8]=eeprom_read_byte((uint8_t*)E_RR);

EEPROM initial values– block is executed only once. It initializes first values for the first time and sets the ‘T’ flag at  E_INIT EEPROM address. The second block – Restore values from EEPROM– now can read values initialized and continue normal program flow. So next time the program is started, it skips the EEPROM initialization block as there is already an E_INIT flag set to ‘T.’ This way, EEPROM data can be initialized for any situation from a single source file if needed.

Comments are closed.