Print this page

Учебный курс AVR. Работа с EEPROM. Объявление переменных. Чтение и запись данных. Ч1

19/07/2013 - 00:00 Павел Бобков

Введение

   При программировании микроконтроллеров AVR иногда возникает потребность сохранять данные, которые бы после выключения питания или сброса контроллера не изменяли свое значение. Для этих целей в составе AVR есть энергонезависимая память данных EEPROM (Electrically Erasable Programmable Read-Only Memory — электрически стираемое перепрограммируемое ПЗУ). 
   EEPROM имеет адресное пространство отличное от адресных пространств ОЗУ и flash памяти, в котором можно читать и записывать одиночные байты. В зависимости от модели микроконтроллера EEPROM может иметь объем от 512 байт (как, например, в микроконтроллере atmega16) до нескольких килобайт. Гарантированное количество циклов перезаписи этой памяти составляет не меньше 100000. 
   В этой статье на примере atmega16 мы разберемся, как работать с этим типом памяти, какие возможные проблемы при этом могут возникать и как с ними бороться.

Объявление переменных в EEPROM

   Использование EEPROM начинается с объявления переменных, хранящиеся в этой памяти. Синтаксис объявления таких переменных отличается от объявлений обычных переменных (хранящихся в ОЗУ) только наличием ключевого слова. В зависимости от компилятора данное ключевое слово может разным. 


Объявление переменной в EEPROM для IAR AVR и CodeVision AVR:


//8-ми разрядная переменная
__eeprom uint8_t setting_2

//объявление массива 16-ти разрядных переменных 
__eeprom uint16_t set[8];

//объявление массива и его инициализация
__eeprom uint8_t data[3] = {11, 3, 13};

//указатель на 8-ми разрядную переменную в EEPROM, который сам хранится в RAM
uint8_t __eeprom * pSetting;

//указатель на 8-ми разрядную переменную в EEPROM, который сам храниться в EEPROM
__eeprom uint8_t __eeprom*pSetting;


Объявление переменной в EEPROM для AtmelStudio 6: 


#include <avr/eeprom.h>

//8-ми разрядная переменная в EEPROM
uint8_t setting EEMEM;

//объявление массива в EEPROM
uint16_t set[8] EEMEM;

//указатель на 8-ми разрядную переменную в EEPROM, который сам хранится в RAM
uint8_t *pSetting;

//указатель на 8-ми разрядную переменную в EEPROM, который сам храниться в EEPROM
uint8_t *pSetting EEMEM;

Инициализация переменных в EEPROM

   При объявлении переменных в EEPROM их можно инициализировать, то есть присвоить начальные значения. 


//для IAR AVR, CodeVision AVR
__eeprom uint8_t counter = 100;
__eeprom uint16_t data[3] = {20, 08, 1981};

//для AtmelStudio 6
uint8_t counter EEMEM = 23;
uint8_t data[3] EEMEM = {21, 04, 1979};


   Инициализацию переменных хранящихся в ОЗУ компилятор "запихивает" в начало программы микроконтроллера - перед вызовом функции main. И она выполняется каждый раз, когда на микроконтроллер подается питание или происходит его сброс. 
   С EEPROM переменными ситуация немного другая, их должен инициализировать сам пользователь путем программирования EEPROM специальным файлом (с расширением .eep). 
   
Как сгенерировать файл для EEPROM? Если в коде есть инициализация EEPROM переменных, то AtmelStudio 6 и CodeVision AVR создадут этот файл автоматически. А вот в IAR`e для этого нужно прописывать линкеру команды. Делается это так.
   
Меню Project > Options...>Linker вкладка Output. Устанавливаем значения по умолчанию - галочка Override default снята, формат - Debug information for C-SPY. На вкладке Extra Options ставим галочку Use Command Options и в окошке ниже прописываем такие строчки:

-Ointel-standard,(CODE)=.hex
-Ointel-standard,(XDATA)=.eep




   После компиляции и сборки проекта IAR создаст файл прошивки - .hex и файл для EEPROM`a - .eep 

   Полученный eep файл записывается с помощью программатора в микроконтроллер.

Чтение и запись EEPROM

   В IAR`e и CodeVision AVR использование EEPROM переменных по сути ничем не отличается от использования обычных переменных (хранящихся в ОЗУ и регистрах). Вся работа по организации чтения и записи в эти EEPROM переменные выполняется компилятором.


//для IAR AVR, CodeVision AVR
__eeprom uint8_t data;
...
//читаем из EEPROM
uint8_t tmp = data;

//записываем в EEPROM
data = 129;


   В AtmelStudio для чтения/записи EEPROM переменных используются специальные макросы. Они определены в файле eeprom.h. Вот некоторые из них:


uint8_t eeprom_read_byte (const uint8_t *__p) - прочитать байт 
uint16_t eeprom_read_word (const uint16_t *__p) - прочитать слово (2 байта)
uint32_t eeprom_read_dword (const uint32_t *__p) - прочитать двойное слово (4 байта)

void eeprom_write_byte (uint8_t *__p, uint8_t __value) - запись байта
void eeprom_write_word (uint16_t *__p, uint16_t __value) - запись слова (2 байта)
void eeprom_write_dword (uint32_t *__p, uint32_t __value) - запись дв. слова (4 байта)


   Макросы принимают в качестве параметра адрес переменной размещенной в EEPROM. Для взятия адреса переменной используется оператор &. Примеры ниже поясняют использование этих макросов. 


//для AtmelStudio

#include <avr/eeprom.h>

//объявляем переменные
uint8_t data EEMEM;
uint16_t pin_code EEMEM;
...
//читаем байт из eeprom
uint8_t tmp = eeprom_read_byte(&data);

//записываем слово в eeprom
eeprom_write_word (&pin_code, 5327)

Заключение

Из этой статьи вы узнали:

- как объявить переменную в EEPROM памяти,
- как создать файл для инициализации EEPROM,
- как прочитать и записать данные в EEPROM.

   В следующей статье будут разобраны регистры, используемые для чтения и записи в EEPROM, а также низкоуровневая работа с этим типом памяти.

Related items