Как работает eeprom. Что такое чип памяти и как программировать микросхемы. Примеры проектов и скетчей

В прошлый раз, когда я писал свой "развёрнутый ответ на вопрос" о том, как забэкапить прошивку с "Меги" меня упрекнули, что я не упомянул про бэкап EEPROM. В тот раз я не сделал этого сознательно, т.к. справедливо рассудил, что не стоит всё усложнять на этапе первоначального "подхода к снаряду". Дело в том, что не для всех очевиден тот факт, что EEPROM не прошивается при компиляции и заливки прошивки из Arduino IDE. То есть, это означает, что абсолютно ничего в EEPROM не заливается, когда прошивка заливается из IDE. А манипуляции с EEPROM (если его использование вообще включено в прошивке) производятся абсолютно на другом уровне. И следовательно, для бэкапа голой прошивки без тонких настроек, которые ВОЗМОЖНО (только возможно) могут храниться в EEPROM, вполне было достаточно сохранить только голую прошивку. Но раз уж возник вопрос, то почему бы его не "разжевать". Давайте пройдёмся по порядку.Что такое EEPROM и зачем вести о нём речь?
EEPROM - (Electrically Erasable Programmable Read-Only Memory) область энергонезависимой памяти микроконтроллера, в которую можно записать и прочитать информацию. Зачастую его используют для того, чтобы хранить настройки программы, которые могут меняться в процессе эксплуатации, и которые необходимо хранить при отключенном питании.

Как 3D принтер использует EEPROM?
Рассмотрим на примере Marlin"а. В Marlin Firmware "из коробки" EEPROM не используется. Параметры конфигуратора (Configuration.h), которые включают возможность его использования, по умолчанию, закомментированы.

#define EEPROM_SETTINGS
#define EEPROM_CHITCHAT

Если включено использование EEPROM, то принтер может хранить и использовать следующие настройки (подсмотрено у буржуев):

  • Количество шагов на миллиметр
  • Максимальная/минимальная скорость подачи [мм/с]
  • Максимальное ускорение [мм/с^2]
  • Ускорение
  • Ускорение при ретракте
  • Настройки PID
  • Отступ домашней позиции
  • Минимальная скорость подачи во время перемещения [мм/с]
  • Минимальное время участка [мс]
  • Максимальный скачок скорости по осям X-Y [мм/с]
  • Максимальный скачок скорости по оси Z [мм/с]
Редактировать эти настройки можно, используя экран принтера и органы управления. При включенном использовании EEPROM, в меню должны отображаться пункты:
  • Store memory
  • Load memory
  • Restore Failsafe
Так же, можно использовать GCode для работы напрямую (через Pronterface).
  • M500 Сохраняет текущие настройки в EEPROM до следующего запуска или выполнения команды M501.
  • M501 Читает настройки из EEPROM.
  • M502 Сбрасывает настройки на значения по-умолчанию, прописанные в Configurations.h. Если выполнить после неё M500, в EEPROM будут занесены значения по-умолчанию.
  • M503 Выводит текущие настройки – ""Те, что записаны в EEPROM.""
О EEPROM в Repitier firmware можно почитать .

Как считать и записать данные в EEPROM?
Аналогично, описанному в , методу бэкапа прошивки, используя ключ -U . Только в данном случае после него будет указатель на то, что считывать нужно EEPROM.

avrdude.exe -p atmega2560 -c wiring -PCOM5 -b115200 -Ueeprom:r:"printer_eeprom".eep:i

Этой командой производится чтение данных EEPROM"а в файл "printer_eeprom.eep". В случае успеха, на экране вы увидите примерно следующее.

Запись тоже не представляет из себя ничего сложного и выполняется аналогичной командой, которая отличается только тем, что в ключе -U стоит не "r", а "w".

avrdude.exe -p atmega2560 -c wiring -PCOM5 -b115200 -Ueeprom:w:"printer_eeprom".eep:i

В случае успеха, на экране вы увидите примерно следующее сообщение.

Как и зачем стирать EEPROM?
Для начала,- "зачем это делать?". Стирать EEPROM нужно в том случае, если предыдущая прошивка тоже его использовала, и в памяти мог остаться мусор. Где-то я уже натыкался на людей с проблемами, что после перехода с одной прошивки на другую (с Marlin на Repitier ЕМНИП), у них принтер начинал вести себя, скажем так, "творчески". Это связанно с тем, что разные прошивки хранят свои данные под разными адресами. И при попытке читать данные из неверного адреса начинается свистопляска.
Затереть EEPROM можно только программно из прошивки, но для этого придётся - на время залить в контроллер специальный скетч. Подробно об этом можно прочитать в официальной документации по Arduino .
Если же стирается EEPROM не в Arduino плате, а в каком-то абстрактном контроллере, то код скетча нужно будет изменить с учётом размера EEPROM в конкретном контроллере на плате. Для этого нужно будет поменять условие окончания в цикле "For". Например, для ATmega328, у которой 1kb памяти EEPROM, цикл будет выглядеть так:
Вывод.
Я довольно долго распинался, а всё для чего? Для того, чтобы подвести к заключению о том, что при бэкапе прошивки, EEPROM тоже можно сохранить, но только в том случае если вам нужны сохранённые в нём настройки. Если же вы готовы ими пожертвовать, то забейте на это. Так же, если вы меняете одну прошивку на другую, или переходите с версии не версию, не поленитесь очистить EEPROM перед заливкой новой прошивки. Ну и заодно мы узнали много нового.

Урок 15

Часть 1

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

Test13.c:

#include "main.h"

int main ( void )

{

while (1)

{

}

}

#ifndef MAIN_H_

#define MAIN_H_

#define F_CPU 8000000UL

#include

#include

#include

#include

#include

#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)

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

Post Views: 7 259

Электрически стираемые программируемые микросхемы постоянной памяти (EEPROM) являются металлическими оксидными полупроводниковыми компьютерными микросхемами, которые используются на печатной плате. Этот тип чипа можно стереть и перепрограммировать с использованием сильного электронного сигнала. Поскольку это можно сделать, не удаляя чип с устройства, к которому он подключен, чипы EEPROM используются во многих отраслях.
Микросхема EEPROM содержит энергонезависимую память, поэтому её данные не теряются при нарушении питания чипа. Микросхема такого типа может быть запрограммирована выборочно, что означает, что часть её памяти может быть изменена с помощью новой перезаписи, не затрагивая остальную память. Информация, хранящаяся внутри микросхемы EEPROM, является постоянной, пока она не будет стёрта или перепрограммирована, что делает её ценным компонентом в компьютерах и других электронных устройствах.

Микросхемы EEPROM созданы на основе транзисторов с плавающим затвором. Микросхема EEPROM запрограммирована путём принудительной программируемой информации в виде электронов через оксид затвора. Затем плавающий затвор обеспечивает хранение этих электронов. Ячейка памяти считается запрограммированной, когда она заряжается электронами, и это представляется нулём. Если ячейка памяти не заряжена, она не запрограммирована, и она представлена ​​единицей.

Для широкого спектра устройств требуется память, поэтому чипы EEPROM имеют множество применений в области бытовой электроники. Они используются в игровых системах, телевизорах и компьютерных мониторах. Слуховые аппараты, цифровые камеры, технология Bluetooth и игровые системы также используют чипы EEPROM. Они используются в телекоммуникационной, медицинской и обрабатывающей промышленности. Персональные и бизнес-компьютеры содержат ЭСППЗУ.

Чип EEPROM также имеет широкий спектр применений в автомобильной отрасли. Он используется в антиблокировочных системах, подушках безопасности, электронных средствах контроля устойчивости, трансмиссиях и блоках управления двигателем. Чипы EEPROM также используются в кондиционерах, дисплеях приборной панели, модулях управления корпусом и системах ввода без ключа. Эти чипы помогают контролировать расход топлива, а также используются в различных диагностических системах.

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

EEPROM — это энергонезавимая память с электрическим стиранием информации. Количество циклов записи-стирания в этих микросхемах достигает 1000000 раз. Заминающие ячейки в них, также как и в постоянных запоминающих устройствах с электрическим стиранием EPROM, реализуются на основе транзисторов с плавающим затвором. Внутреннее устройство этой запоминающей ячейки приведено на рисунке 1:


Рисунок 1. Запоминающая ячейка ПЗУ с электрическим стиранием (EEPROM)

Ячейка EEPROM памяти представляет собой МОП транзистор, в котором затвор выполняется из поликристаллического кремния. Затем в процессе изготовления микросхемы этот затвор окисляется и в результате он будет окружен оксидом кремния — диэлектриком с прекрасными изолирующими свойствами. В транзисторе с плавающим затвором при полностью стертом ПЗУ, заряда в "плавающем" затворе нет, и поэтому данный транзистор ток не проводит. При программировании, на второй затвор, находящийся над "плавающим" затвором, подаётся высокое напряжение и в него за счет туннельного эффекта индуцируются заряды. После снятия программирующего напряжения индуцированный заряд остаётся на плавающем затворе, и, следовательно, транзистор остаётся в проводящем состоянии. Заряд на его плавающем затворе может храниться десятки лет.

Подобная ячейка памяти применялась в ПЗУ с ультрафиолетовым стиранием (EPROM). В ячейке памяти с электрическим стиранием возможна не только запись, но и стирание информации. Стирание информации производится подачей на программирующий затвор напряжения, противоположного напряжению записи. В отличие от ПЗУ с ультрафиолетовым стиранием, время стирания информации в EEPROM памяти составляет около 10 мс.

Структурная схема энергонезависимой памяти с электрическим стиранием не отличается от структурной схемы масочного ПЗУ. Единственное отличие — вместо плавкой перемычки используется описанная выше ячейка. Ее упрощенная структурная схема приведена на рисунке 2.



Рисунок 2. Упрощенная структурная схема EEPROM

В качестве примера микросхем EEPROM памяти можно назвать отечественные микросхемы 573РР3, 558РР3 и зарубежные микросхемы серий AT28с010, AT28с040 фирмы Atmel, HN58V1001 фирмы Hitachi Semiconductor, X28C010 фирмы Intersil Corporation. В EEPROM памяти чаще всего хранятся пользовательские данные в сотовых аппаратах, которые не должны стираться при выключении питания (например адресные книги), конфигурационная информация роутеров или сотовых аппаратов, реже эти микросхемы применяются в качестве конфигурационной памяти FPGA или хранения данных DSP. EEPROM изображаются на принципиальных схемах как показано на рисунке 3.


Рисунок 3. Условно-графическое обозначение электрически стираемого постоянного запоминающего устройства

Чтение информации из параллельной EEPROM памяти производится аналогично чтению из масочного ПЗУ. Сначала на шине адреса выставляется адрес считываемой ячейки памяти в двоичном коде A0...A9, затем подается сигнал чтения RD. Сигнал выбора кристалла CS обычно используется в качестве дополнительного адресного провода для обращения к микросхеме. Временные диаграммы сигналов на входах и выходах этого вида ПЗУ приведены на рисунке 4.



Рисунок 4. Временные диаграммы сигналов чтения информации из EEPROM памяти

На рисунке 5 приведен чертеж типового корпуса микросхемы параллельной EEPROM памяти.


Рисунок 5. Чертеж корпуса микросхемы параллельной EEPROM

Обычно данные, которые хранятся в EEPROM требуются достаточно редко. Время считывания при этом не критично. Поэтому в ряде случаев адрес и данные передаются в микросхему и обратно через последовательный порт. Это позволяет уменьшить габариты микросхем за счет уменьшения количества внешних выводов. При этом используются два вида последовательных портов — SPI порт и I2C порт (микросхемы 25сXX и 24cXX серий соответственно). Зарубежной серии 24cXX соответствует отечественная серия микросхем 558РРX.

Внутренняя схема микросхем серии 24сXX (например AT24C01) приведена на рисунке 6.



Рисунок 6. Внутренняя схема микросхемы AT24C01

Подобные микросхемы широко используются для сохранения настроек телевизоров, в качестве памяти plug and play в компьютерах и ноутбуках, конфигурационной памяти ПЛИС и сигнальных процессоров (DSP). Применение последовательной EEPROM памяти позволило значительно уменьшить стоимость данных устройств и увеличить удобство работы с ними. Пример расположения данной микросхемы на печатной плате карты памяти компьютера приведен на рисунке 7.



Рисунок 7. EEPROM на печатной плате карты памяти компьютера

На рисунке 8 приведена схема электронной карты с применением внешней EEPROM микросхемы.


Рисунок 8. Схема электронной карты с применением внешней EEPROM

На данной схеме микроконтроллер PIC16F84 осуществляет обмен данными с EEPROM памятью 24LC16B. В таких устройствах, как SIM-карта, уже не применяется внешняя микросхема памяти. В SIM-картах сотовых аппаратов используется внутренняя EEPROM память однокристального микроконтроллера. Это позволяет максимально снизить цену данного устройства.

Схема управления для электрически стираемых программируемых ПЗУ получилась сложная, поэтому наметилось два направления развития этих микросхем:

  1. ЕСППЗУ (EEPROM) - электрически стираемое программируемое постоянное запоминающее устройство
  2. FLASH-ПЗУ

FLASH - ПЗУ отличаются от ЭСППЗУ тем, что стирание производится не каждой ячейки отдельно, а всей микросхемы в целом или блока запоминающей матрицы этой микросхемы, как это делалось в РПЗУ.


Рисунок 9. Условно-графическое обозначение FLASH памяти

При обращении к постоянному запоминающему устройству сначала необходимо выставить адрес ячейки памяти на шине адреса, а затем произвести операцию чтения из микросхемы. Эта временная диаграмма приведена на рисунке 11.



Рисунок 10. Временные диаграммы сигналов чтения информации из ПЗУ

На рисунке 10 стрелочками показана последовательность, в которой должны формироваться управляющие сигналы. На этом рисунке RD - это сигнал чтения, A - сигналы выбора адреса ячейки (так как отдельные биты в шине адреса могут принимать разные значения, то показаны пути перехода как в единичное, так и в нулевое состояние), D - выходная информация, считанная из выбранной ячейки ПЗУ.

Литература:

Вместе со статьей "Постоянные запоминающие устройства (ПЗУ)" читают:

Наш контроллер печи почти готов – однако пока он остаётся контроллером-«золотой рыбкой», который помнит все настройки только пять минут до первого выключения питания. Чтобы запомнить наши настройки, значение заданной температуры и точки калибровки даже после отключения питания, нужно использовать энергонезависимую память – EEPROM.
Очень хорошо о работе с EEPROM написано у наших товарищей и .

Главное, что нам нужно знать – что память EEPROM лучше рассматривать не как «просто память», а как отдельное внутреннее устройство в микросхеме.
У EEPROM отдельное адресное пространство , не имеющее никакого отношения к адресному пространству процессора (FLASH и SRAM); для того, чтобы получить доступ к данным по определённому адресу в энергонезависимой памяти, нужно выполнить определённую последовательность действий с использованием целого ряда регистров (регистров адреса EEARH и EEARL, регистра данных EEDR и регистра управления EECR).
Согласно даташиту, для записи байта по определённому адресу в EEPROM нужно выполнить следующее:

  1. ждём готовности EEPROM к записи данных (сброса бита EEPE регистра EECR);
  2. ждём окончания записи в FLASH-память (сброса бита SELFPRGEN регистра SPMCSR) – нужно выполнить, если в программе присутствует загрузчик;
  3. записываем новый адрес в регистр EEAR (при необходимости);
  4. записываем байт данных в регистр EEDR (при необходимости);
  5. устанавливаем в единицу бит EEMPE регистра EECR;
  6. в течение четырёх тактов после установки флага EEMPE записываем в бит EEPE регистра EECR логическую единицу.

После этого процессор пропускает 2 такта перед выполнением следующей инструкции.
Второй пункт нужно выполнять при наличии загрузчика в программе – дело в том, что запись в EEPROM не может выполняться одновременно с записью во FLASH-память, поэтому перед записью в EEPROM нужно убедиться, что программирование FLASH-памяти завершено; если же микроконтроллер не имеет загрузчика, то он никогда не изменяет содержимое FLASH-памяти (помним, что avr имеет гарвардскую архитектуру: память программ (FLASH) и память данных (SRAM) разделены).
Длительность цикла записи зависит от частоты внутреннего RC-генератора микросхемы, напряжения питания и температуры; обычно для моделей ATmega48x/88x/168x это составляет 3.4 мс (!), для некоторых старых моделей – 8.5 мс (!!!).
Кроме того, при записи в EEPROM могут возникнуть проблемы с вызовом прерываний в процессе выполнения последовательности действий выше – так что прерывания в процессе записи в EEPROM лучше запретить.
Чтение энергонезависимой памяти происходит чуть проще:

  1. ждём готовности EEPROM к чтению данных (сброса бита EEWE регистра EECR);
  2. записываем адрес в регистр EEAR;
  3. устанавливаем в единицу бит EERE регистра EECR;
  4. считываем данные из регистра EEDR (на самом деле, когда запрошенные данные будут перемещены в регистр данных, происходит аппаратный сброс бита EERE; но отслеживать состояние этого бита не требуется, так как операция чтения из EEPROM всегда выполняется за один такт).

После установки бита в EERE в единицу процессор пропускает 4 такта перед началом выполнения следующей инструкции.
Как мы видим, работа с энергонезависимой памятью – процесс времязатратный; если мы часто будем записывать-считывать данные с EEPROM – программа может начать тормозить.

Однако мы пишем программу в среде IAR, и нам повезло: всю работу с чтением-записью из EEPROM будет выполнять среда разработки – в iar есть модификатор «__eeprom», который создает переменные в энергонезависимой памяти – а далее нам нужно будет просто или считывать из «постоянных» переменных в «текущие» (при инициализации контроллера), или записывать из «текущих» переменных в «постоянные» – то есть, при изменении текущего значения нужно изменять и значение переменной в энергонезависимой памяти.
Выглядеть новые переменные будут вот так:

Eeprom uint16_t EEP_MinTemperature;

Ещё пару общих слов: и хотя указатели на eeprom-переменные у нас не предполагаются, нужно помнить, что eeprom – отдельное адресное пространство, и чтобы создать указатель на eeprom (и это позволяет нам сделать компилятор), необходимо указывать, что это указатель на адрес в eeprom:

Uint16_t __eeprom *EEP_MinTemperatureAdr;

Возвращаемся к контроллеру печки и EEPROM. В нашем случае, для EEPROM никакой виртуальной машины, конечно, не предполагается; более того, стоит подумать, нужна ли отдельная библиотека для работы с энергонезависимой памятью – уж больно «разбросаны» по программе записи важных настроек; если пытаться сделать отдельную библиотеку, то придётся делать перекрестные ссылки: в библиотеке для EEPROM подключать библиотеки АЦП, нагревательного элемента, глобальных настроек; а в этих библиотеках периферии подключать библиотеку EEPROM – такой подход не очень хорош.
Другой вариант – дописать в каждую библиотеку, где нужно сохранять настройки, eeprom-переменную, и сохранять соответствующие настройки прямо в виртуальных машинах. Мы реализуем этот вариант.
Сначала перечислим, какие переменные нам нужно сохранять в EEPROM:

  1. точки калибровки
  2. значения максимальной-минимальной задаваемой температуры и шага настройки температуры
  3. значение заданной температуры
  4. коэффициенты ПИД-регулятора

Значение кухонного таймера не сохраняем – будем считать, что пользователь после выключения питания должен сам каждый раз настраивать таймер печки.
Все эти настройки задаются пользователем посредством поворотов энкодера и дальнейшего краткого нажатия на пользовательскую кнопку. При этом помним, что количество циклов чтения-записи EEPROM все-таки ограничено, поэтому лишний раз одну и ту же информацию (например, если пользователь выбрал то же самое значение какой-то настройки, что и было) не перезаписывать. Поэтому перед каждым изменением __eeprom-переменной проверяем, а нужно ли её переписывать:

//если значение изменилось - перезаписываем в энергонезависимой памяти if (ADCTemperature.atMinTemperatureValue != (uint16_t)VMEncoderCounter.ecntValue) { ADCTemperature.atMinTemperatureValue = (uint16_t)VMEncoderCounter.ecntValue; EEP_MinTemperature = ADCTemperature.atMinTemperatureValue; }

С чтением настроек из EEPROM тоже все просто – при инициализации «текущих» настроек мы просто считываем значение из энергонезависимой памяти:

ADCTemperature.atMinTemperatureValue = EEP_MinTemperature;

Для того, чтобы наше устройство с самого начала имело какие-нибудь настройки в EEPROM, проект для первой загрузки можно скомпилировать с инициализацией этих переменных:

Eeprom uint16_t EEP_MinTemperature = 20; … //массив для хранения точек калибровки в энергонезависимой памяти __eeprom TCalibrationData EEP_CalibrationData = {{20, 1300}, {300, 4092}};

В этом случае компилятор инициализирует __eeprom переменные до начала работы с основной функцией. Чтобы получить файл с энергонезависимой памятью (.eep), нужно залезть в следующие настройки:
Project->Options..->Linker->Extra Options
Если галочка «Use command line options» не стоит, поставьте её и добавьте строку
-Ointel-standard,(XDATA)=.eep
Компилируем сначала проект с инициализированными переменными, сохраняем eep-файл отдельно; затем убираем инициализацию при создании переменных.

Вот и все – наша печка готова!