Подписаться на получение новых статей на почту:

Память EEPROM (ППЗУ) в AVR. Запись и чтение. Шаг №13

Обновлено 16.12.15. Всем привет. Рассмотрев в прошлой статье взаимодействие кнопок с контроллером,  в этой записи разберем память МК AVR EEPROM (электрически стираемая ППЗУ), которая является энергонезависимой и имеет ресурс примерно в 100 000 циклов записи/чтения. Зачем нам нужна такая память с ограниченным числом обращений к ней? Такая память идеально подходит для хранения констант и исходных параметров, которые мы можем задать в начале программы, при помощи тех же кнопок.

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

Теперь рассмотрим как обращаться к ней. Для программирования памяти EEPROM используются три регистра, расположенные в области ввода/вывода памяти SRAM: восьмиразрядный регистр адреса EEAR или два регистра EEARH и EEARL; восьмиразрядный регистр данных EEDR; восьмиразрядный регистр управления EECR.  когда происходит процесс записи, байт данных адресуется регистром адреса и заносится  в регистр данных. В процессе чтения из памяти в регистр данных записывается содержимое ячейки EEPROM, адресуемой регистром адреса.

В книге Евстифеева, справочнике по микроконтроллерам (литературу я приводил в статье №1), описаны программные примеры для записи/чтения. Давайте разберем программу:

Реализация функции записи:

void EEPROM_write (unsigned int uiAddress, unsigned char uoData)
{
     while ( EECR & (1<<EEWE)); //ждем завершения предыдущей записи
     EEAR = uiAddress; //Проинициализировать регистр адреса
     EEDR = uoData ; //Проинициализировать регистр данных
     EECR |= (1<<EEMWE); //Установить флаг EEMWE
     EECR |= (1<< EEWE); //Начать запись в EEPROM
}

Разберем программу.
1. EEWE является разрядом регистра (рисунок ниже)  EECR и отвечает за разрешение записи в EEPROM, если установлен в 1, то происходит запись в EEPROM, при условии что EEMWE установлен в 1.
2. Загружаем адрес в регистр адреса EEAR
Регистр-управления-EECR

 

 

Разряды регистра управления EECR:
EERIE — разрешение прерывания от EEPROM;
EEMWE — управление разрешением записи в EEPROM;
EEWE — разрешение записи в  EEPROM;
EERE —  разрешение чтения из EEPROM.

3. Загружаем байт данных  в регистр данных EEDR.
4. EEMWE – управление разрядом разрешения записи в EEPROM. Этот флаг отвечает за функционирование разряда разрешения записи EEWE. При установке в 1 запись разрешается, если 0, то при установке EEWE в 1 запись в память не произойдет. После программной установки EEMWE сбрасывается через 4 машинных цикла.
5. Записываем данные в память.

!!!Здесь есть один нюанс. Если планируется, периодически записывать данные в EEPROM во время выполнения программы, при самопрограммировании микроконтроллера,  то необходимо знать, что запись в EEPROM не может одновременно выполняться с записью во Flash память , поэтому выше после первого пункта необходимо добавить следующий пункт:

— дождаться завершения записи во Flash-память программ, т.е. ждать пока не сброситься флаг SPMEN регистра SPMCR, тогда после этой строки необходимо добавить еще одно циклическое условие:

while (SPMCR &(1<<SPMEN));// Завершение записи во Flash память

Теперь разберем функцию чтения:

 unsigned char EEPROM_write (unsigned int uiAddress)
{
     while ( EECR & (1<<EEWE)); //ждем завершения предыдущей записи
     EEAR = uiAddress; //Проинициализировать регистр адреса
     EECR |= (1<<EERE); //Выполнить чтение
     return EEDR;
 }

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

Но прежде, чем использовать алгоритм записи или чтения  EEPROM, необходимо объявить переменную, которая будет распределена в пределах области EEPROM. Для этого в библиотеке  eeprom.h программной среды WinAVR определен специальный атрибут EEMEM. Например объявим переменную без знакового целочисленного типа с атрибутом.

EEMEM uint8_t eeprom_х ; // объявим переменную.
х –переменная;
uint8_t – целочисленный без знаковый тип, имеющие точно указанную разрядность, в данном случае 8 бит и предназначен для переносимости программ.
EEMEM – атрибут, заставляющий переменную быть распределенной в пределах раздела .eeprom. Данный атрибут определен в файле eeprom.h и выглядит он следующим образом.

#ifndef EEMEM
#define EEMEM__attribute__ ((section («.eeprom»)))
 #endif

Для работы с данными в библиотеке уже прописаны функции:
для чтения
uint8_t  eeprom_read_byte (const uint8_t *addr)
Аргументом функций eeprom_read_... является адрес переменной в EEPROM, а результатом — значение переменной в EEPROM.
для записи
void  eeprom_write_byte (uint8_t *addr, uint8_t value)
Аргументами функций eeprom_write_... являются адрес в EEPROM, куда записать данные и значение которое нужно записать.

Ну что ж все это пережевав на по следок программный пример в целом. Передадим в EEPROM данные и считаем.  Используя AVR и программу для ЖК-индикатора, выведем результат.

#include <eeprom.h>
 #include <stdio.h>
#include <avr/io.h>
#include «lcd.h»

uint8_t EEMEM eepro_х; /* такая переменная должна быть всегда глобальной и служит для передачи своего адреса в область EEPROM*/
char word[]="Hello";

main ()
 {
     uint8_t eepro_х1 = 100; /*вторая переменная для передачи данных*/
     /*Давайте запишем переменную в память*/
     eeprom_write_byte (&eeprom_x, eeprom_x1); /*передаем в функцию адрес переменной и значение которое запишем                                                                   по этому адресу*/
     /*теперь убедимся, что в памяти у нас хранится значение 100, для этого обнулим текущее значение     переменной х и присвоим считанное значение из памяти*/
      eeprom_х1 = 0;
      /*считаем содержимое памяти*/
      x1 = eeprom_read_byte (&eeprom_x);   // взятие адреса переменной
      sprintf (word,"V_eeprom x1=%3d",eeprom_x1);
      PrintString (word);
}

Ниже, на рисунке представлен результат
EEPROM на ЖКИ Если в программе изначально передаются какие то константы для хранения в памяти EEPROM, то при прошивке необходимо залить файл с расширением .eep, который будет создан компилятором и размещен в той же директории что и рабочие файлы.

На этом пока все. Здесь дан краткий обзор для работы с такой памятью.  Конечно есть куча нюансов, но это уже тонкости. В следующей статье рассмотрим ШИМ (широтно-импульсную модуляцию) и плавно перейдем к следующему проекту попробуем сконструировать «мозги» для любительского станка ЧПУ. Всем пока.

Просмотрено 11373 раз.

Я на Google+

Добавить комментарий

Ваш e-mail не будет опубликован.

Можно использовать следующие HTML-теги и атрибуты: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>

Subscribe without commenting