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 2.0

 

 

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

 

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

2 комментария на “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 не будет опубликован. Обязательные поля помечены *

*