AVR Урок 15. Внутренняя энергонезависимая память EEPROM. Часть 1



 

Урок 15

Часть 1

 

Внутренняя энергонезависимая память EEPROM

 

Я думаю, может не все, но очень многие знают, что в контроллерах AVR помимо основной оперативной памяти, а также памяти для хранения прошивки существует ещё и энергонезависимая память типа EEPROM. Данная память сделана по технологии электрического стирания информации, что в отличие от её предшественника EPROM, в котором стирание производилось только при помощи ультрафиолетовых лучей, позволило использовать данный тип памяти практически повсеместно. Как мы знаем, ещё существует энергонезависимая память типа Flesh, которая стоит намного дешевле, но у которой также есть существенный минус. Там невозможно стереть отдельный байт, стирание производится только блоками, что не совсем удобно в некоторых случаях, особенно когда информации требуется хранить немного, и информация данная представляет собой небольшие настроечные параметры. Поэтому нам стоит также остановиться на данном типе памяти. И причем не только из-за того, что он присутствует в контроллере, а из-за того, что это очень удобно для хранения некоторых величин, которые нужны нам будут даже после того, как контроллер потерял питание.

Так как мы работаем с контроллером Atmega8A, техническую документацию данного МК мы и откроем и увидим там, что всего такой памяти у нас 512 байт. Это тем не менее не так мало. Если мы, например будем какой-нибудь будильник программировать, чтобы данные установки не потерялись после отключения питания, мы вполне можем с вами обратиться к данной памяти. Также в документации написано, что данная память гарантированно переживёт 100000 циклов записи/считывания.

Теперь напрашивается вопрос. Как же организован процесс работы с данной памятью в микроконтроллере AVR? Как всегда, компания Atmel об этом позаботилась и организовала данный процесс на аппаратном уровне, что очень радует потому, что нам постоянно приходится беречь ресурсы контроллера. Для управления данным аппаратным уровнем существуют определенные регистры.

Один из них — регистровая пара EEAR. Почему пара, а потому что 512 адресов не влезут в 8 бит, требуется ещё один

 

image00

 

Как именно мы будем адресоваться, мы увидим в процессе программирования EEPROM.

Следующий — регистр данных EADR

 

image01

 

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

Ну и как водится, практически ни одна периферия и технология, организованная на аппаратном уровне, не обходится без управляющего регистра. У нас управляющим регистром является регистр EECR

 

image02

 

Давайте сразу немного познакомимся с битами данного регистра.

Бит EERE — бит, заставляющий начать процесс чтения из памяти EEPROM. И, как только данные считались и записались в регистр данных, этот бит сбросится. Поэтому мы можем считать даннй бит не только управляющим, но и статусным или битом состояния.

Бит EEWE — бит, установка которого даёт команду контроллеру записать данные из регистра данных в определенный адрес EEPROM. После завершения процедуры записи, данный бит также сбрасывается самостоятельно.

Бит EEMWE — бит, разрешающий (не начинающий) процесс записи.

Бит EERIE — бит, разрешающий прерывания.

 

Ну, теперь перейдём к проекту. Проект был создан обычным стандартным образом и назван Test13. Также был подключен файл main.h и созданы файлы eeprom.h и eeprom.c.

 

 

Вот исходный код созданных файлов

 

Test13.c:

 

#include «main.h»

int main(void)

{

  while(1)

  {

  }

}

 

main.h

 

#ifndef MAIN_H_

#define MAIN_H_

#define F_CPU 8000000UL

#include <avr/io.h>

#include <avr/interrupt.h>

#include <util/delay.h>

#include <stdio.h>

#include <stdlib.h>

#include «eeprom.h»

 

#endif /* MAIN_H_ */

 

eeprom.h

 

#ifndef EEPROM_H_

#define EEPROM_H_

#include «main.h»

void EEPROM_write(unsigned int uiAddress, unsigned char ucData);

unsigned char EEPROM_read(unsigned int uiAddress);

#endif /* EEPROM_H_ */

 

eeprom.c

 

#include «eeprom.h»

 

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

Ну, давайте не будем забивать голову и вставим код функции записи, также и функции чтения из примера в технической документации в файл eeprom.c и уберем англоязычные комментарии, вставив туда русскоязычные. После всех исправлений файл станет вот таким

 

#include «eeprom.h»

void EEPROM_write(unsigned int uiAddress, unsigned char ucData)

{

  while(EECR & (1<<EEWE)) //ждем освобождения флага окончания последней операцией с памятью

  {}

  EEAR = uiAddress; //Устанавливаем адрес

  EEDR = ucData; //Пищем данные в регистр

  EECR |= (1<<EEMWE); //Разрешаем запись

  EECR |= (1<<EEWE); //Пишем байт в память

}

unsigned char EEPROM_read(unsigned int uiAddress)

{

  while(EECR & (1<<EEWE))

  {} //ждем освобождения флага окончания последней операцией с памятью

  EEAR = uiAddress; //Устанавливаем адрес

  EECR |= (1<<EERE); //Запускаем операцию считывания из памяти в регистр данных

  return EEDR; //Возвращаем результат

}

 

Напишем прототипы на данные функции в файле eeprom.h

 

#include «main.h»

void EEPROM_write(unsigned int uiAddress, unsigned char ucData);

unsigned char EEPROM_read(unsigned int uiAddress);

 

 

Теперь вызовем функцию записи в функции main() и тем самым попробуем записать какую-нибудь 8-битную величину по адресу 1. Вообще, адресация в данной памяти начинается с 0

 

int main(void)

{

  EEPROM_write(1, 120);

  while(1)

 

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

 

image03

 

Соберём проект и перейдём в программу для прошивки Avrdude.

Выберем там наш файл прошивки, затем попытаемся считать контроллер, затем всё сотрем по кнопке «стереть все»

 

image04

 

Также в программе avrdude есть ещё одна строка «Eeprom». Данную строку мы можем использовать, чтобы записать в данную память не программно, а из файла. Но мы будем писать из нашей программы, а данную строку будем использовать, чтобы читать в файл память EEPROM. Можно написать в эту строку путь от руки и файл создастся сам. Напишем, например «C:\1\11111» и нажмем «Чтение», и по данному пути запишется в указанный файл вся информация из памяти EEPROM

 

image05

 

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

Найдём теперь на диске данный файл и откроем его в блокноте

 

image06

Данный файл имеет приблизительно такой же формат как и файл прошивки. Сначала адрес, затем 32 байта информационных и затем контрольная сумма на эти 32 байта. Если мы не разу не записывали ничего в память EEPROM, то по всем адресам у нас будут FF, то есть во всех битах памяти у нас единички.

Закрываем файл, пытаемся прошить контроллер, затем опять читаем память EEPROM в файл и откроем файл

 

image07

 

Мы видим, что в файл записалось число «78», что и означает 120 в десятичном формате.

Теперь попробуем нажать кнопку «Стереть всё», в этом случае память EEPROM стетеься не должна.

Читаем опять EEPROM в файл, открываем файл и видим, что память стёрлась, у нас опять везде «FF».

Почему так произошло? Потому что нужно настроить фьюзы. Читаем фьюзы

 

image08

 

Обратим внимание на бит EESAVE. Когда данный бит в единице (как у нас и есть, биты же с инверсией), то мы заставляем при отключении питания, а также при стирании стирать память EEPROM. А чтобы такого не происходило, данный бит нужно сбросить, то есть поставить в него галку и прошить фьюзы.

Прошиваем фьюзы, стираем контроллер, прошиваем контроллер, опять стираем, читаем память EEPROM в файл и открываем его. Теперь мы видим, что ничего у нас не стёрлось

 

image07

Теперь попробуем отключить контроллер от питания и подать через некоторое время питание опять. Опять читаем EEPROM в файл, у нас всё цело. Отлично!

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

 

 

Предыдущий урок Программирование МК AVR Следующая часть

 

Приобрести программатор USBASP USBISP с адаптером можно здесь USBASP USBISP 3.3 с адаптером

 

 

Смотреть ВИДЕОУРОК в RuTube (нажмите на картинку)

AVR Внутренняя энергонезависимая память EEPROM

 

Смотреть ВИДЕОУРОК в YouTube (нажмите на картинку)

AVR Внутренняя энергонезависимая память EEPROM

3 комментария на “AVR Урок 15. Внутренняя энергонезависимая память EEPROM. Часть 1
  1. Dmitriy:

    Добрый день! Для записи в ЕЕПРОМ 4-х байтного числа я использовал готовые функции Атмел eeprom_read_dword () и eeprom_write_dword (), предварительно создав глобальную переменную uint32_t EEMEM… Затем, прогой Hex2bin я переконвертировал файл *.еер в *.bin для нормально симуляции ЕЕПРОМ в Протеусе. В итоге, проект симуляция проекта проходит отлично. Значения в ЕЕПРОМ сохраняются и считываются так как нужно. Но меня вот что беспокоит. В исходном коде объявлена глобальная переменная uint32_t EEMEM. При перезапуске устройства ей всегда присваивается один и тот же адрес в ЕЕПРОМ? Т.е. я опасаюсь, что в реальном устройстве при попытке считать данные eeprom_read_dword (), считается FFFF, например, вместо ранее записанного числа.

  2. Юрий:

    Точно ли что при выставленом бите EESAVE стирается память при отключении питания? При перепрошивке да, но про питание не видел

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

Ваш e-mail не будет опубликован. Обязательные поля помечены *

*