Память данных EEPROM

Микроконтроллеры / Для начинающих / Архитектура /

Микроконтроллеры для начинающих Что нужно для того, чтобы стать профессиональным разработчиком программ для микроконтроллеров и выйти на такой уровень мастерства, который позволит с лёгкостью найти и устроиться на работу с высокой зарплатой (средняя зарплата программиста микроконтроллеров по России на начало 2017 года составляет 80 000 рублей). Подробнее...

ATtiny13A содержит 64 байта памяти данных EEPROM. Эта память организована как отдельное пространство данных, в котором отдельные байты могут быть прочитаны и записаны. EEPROM имеет выносливость по крайней мере 100 000 циклов записи/стирания. Обмен данными между EEPROM и процессором описан далее, и основан на использовании Регистров Адреса EEPROM (EEPROM Address Registers), Регистра Данных EEPROM (EEPROM Data Register) и Регистра Управления EEPROM (EEPROM Control Register). Подробное описания последовательной загрузки данных в EEPROM описано в документации (в оригинале это страница 106, на моём сайте будет опубликовано позже).

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

  • EEAR - Регистр Адреса EEPROM (EEPROM Address Register)
  • EEDR - Регистр Данных EEPROM (EEPROM Data Register)
  • EECR - Регистр Управления EEPROM (EEPROM Control Register)

Если объём EEPROM превышает 256 байт (вообще в AVR эта память может иметь объём до 8 КБ в зависимости от модели МК), то вместо одного регистра адреса EEAR микроконтроллер имеет два регистра: EEARH и EEARL. Регистры доступа к EEPROM имеют следующие номера:

  • EEAR - 0x1E
  • EEARL - 0x1E
  • EEARH - 0x1F
  • EEDR - 0x1D
  • EECR - 0x1C

Как видите, регистры EEAR и EEARL имеют одинаковые номера. То есть в микроконтроллере, где объём EEPROM меньше 256 байт (в таком, как ATtiny13A), можно использовать только EEAR (он же EEARL).

Регистры EEAR (или EEARH и EEARL) работают только на запись. То есть в эти регистры вы можете только записать значение - адрес EEPROM, тем самым указав микроконтроллеру, с какой ячейкой памяти дальше надо будет работать.

Регистр EEDR работает как на запись, так и на чтение. При записи через этот регистр в EEPROM поступает записываемый байт. При чтениии через этот регистр микроконтроллер получает байт из EEPROM.

Регистр управления EECR устанавливает режим работы. Через него подаются команды чтения и записи EEPROM. Установка 0-го бита начинает чтение из EEPROM. Установка 1-го бита начинает запись в EEPROM. Для управляющих битов имеются соответствующие константы (биты регистра EECR будут описаны позже в других статьях, в оригинальной документации см. стр. 21).

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

Регистры Адреса EEPROM (EEPROM Access Registers) доступны через область ввода-вывода.

Время доступа для записи в EEPROM приведено в таблице 5.1. Функция самоуправления временем, однако, позволяет программному обеспечению пользователя определить, когда можно записать следующий байт. Если код пользователя содержит инструкции по записи EEPROM, необходимо принять некоторые меры предосторожности. В источниках питания с мощными фильтрами, питание VCC при включении/выключении медленно повышается (понижается). По этой причине микроконтроллер в течение некоторого времени запускается на более низком напряжении, чем допустимо для используемой тактовой частоты. Дополнительные сведения о том, как избежать сложностей в таких случаях, см. ниже в разделе “Предотвращение повреждения EEPROM”.

Таблица 5.1. Биты режимов EEPROM.

EECR Время программирования Операция
EEPM1 EEPM0
0 0 3,4 мс Стирание и запись за одну операцию (Атомарная операция)
0 1 1,8 мс Только стирание
1 0 1,8 мс Только запись
1 1 - Зарезервировано для будущего использования

Чтобы предотвратить непреднамеренную запись EEPROM, необходимо выполнить определенные правила записи. Подробности см. ниже в разделах “Атомарное программирование байта” и “Раздельное программирование байта”.

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

Атомарное программирование байта (Atomic Byte Programming)

Операция в общей области памяти называется атомарной, если она завершается в один шаг (не путать с тактом!) относительно других потоков (процессов), имеющих доступ к этой памяти. Во время выполнения такой операции над переменной, ни один поток не может наблюдать изменение наполовину завершенным. То есть пока атомарное обращение к памяти не будет завершено, доступ к этой памяти из другой операции невозможен. Атомарная загрузка гарантирует, что переменная будет загружена целиком в один момент времени.

Неатомарные операции не дают такой гарантии (то есть при неатомарных операциях возможен одновременный доступ к памяти из нескольких потоков, что может привести к непредсказуемым результатам).

Использование Атомарного Программирования байта (Atomic Byte Programming) - это самый простой режим. Записывая байт в EEPROM, пользователь должен записать адрес в регистр EEARL, а данные в регистр EEDR. Если биты EEPMn равны нулю, запись EEPE (в течение четырех тактов после записи EEMPE) вызовет операцию стирания/записи.

И стирание, и запись выполняются за одну операцию (полное время программирования показано в таблица 5-1 выше). Бит EEPE остается установленным до завершения операций стирания и записи. Пока микроконтроллер занят программированием, невозможно выполнять какие-либо другие операции с EEPROM.

Раздельное программирование байта (Split Byte Programming)

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

Стирание EEPROM

Для того, чтобы стереть байт, его адрес необходимо записать в регистр EEARL. Если биты EEPMn равны 0b01, то запись EEPE (в течение четырех тактов после записи EEMPE) вызовет только операцию стирания (время программирования указано выше в таблице 5-1). Бит EEPE остается установленным до завершения операции стирания. Пока микроконтроллер занят программированием, невозможно выполнить какие-либо другие операции с EEPROM.

Запись EEPROM

Для записи ячейки памяти пользователь должен записать адрес в EEARL, а данные - в EEDR. Если биты EEPMn равны 0b10, то запись EEPE (в течение четырех тактов после записи EEMPE) вызовет только операцию записи (время программирования приведено выше в таблице 5-1). В EEPE бит остается установленным до тех пор, пока операция записи не завершится. Если записываемая ячейка не была очищена (стерта) перед записью, сохраненные данные должны считаться потерянными. Пока микроконтроллер занят программированием, невозможно выполнить какие-либо другие операции с EEPROM.

Калибровка генератора тактовой частоты с помощью регистра калибровки (Oscillator Calibration Register) используется для настройки времени доступа к EEPROM. Убедитесь, что частота генератора соответствует требованиям, описанным в разделе “OSCCAL – Oscillator Calibration Register " (в оригинальной документации стр. 27, на моём сайте будет описана позже).

В следующих примерах кода показана одна функция на Ассемблере и C для стирания, записи или атомарной записи EEPROM. В примерах предполагается, что прерывания управляются (например, отключением прерываний глобально) таким образом, что во время выполнения этих функций прерывания не будут происходить.

Пример на Ассемблере:

EEPROM_write:
; Дождаться завершения предыдущей записи
sbic EECR, EEPE
rjmp EEPROM_write
; Установить режим программирования
ldi r16, (0<<EEPM1)|(0<<EEPM0)
out EECR, r16
; Записать начальный адрес (r17) в регистр адреса
out EEARL, r17
; Записать данные (r16) в регистр данных
out EEDR, r16
; Записать логическую единицу в EEMPE
sbi EECR, EEMPE
; Начать запись EEPROM, установив EEPE
sbi EECR, EEPE
ret

Пример на Си:

void EEPROM_write(unsigned char ucAddress, unsigned char ucData)
{
/* Дождаться завершения предыдущей записи */
while(EECR & (1<<EEPE)) ;
/* Установить режим программирования */
EECR = (0<<EEPM1)|(0>>EEPM0)
/* Настроить регистры адреса и данных */
EEARL = ucAddress;
EEDR = ucData;
/* Записать логическую единицу в EEMPE */
EECR |= (1<<EEMPE);
/* Начать запись EEPROM, установив EEPE */
EECR |= (1<<EEPE);
}

См. также пример здесь.

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

Пример на Ассемблере:

EEPROM_read:
; Дождаться завершения предыдущей записи
sbic EECR, EEPE
rjmp EEPROM_read
; Записать начальный адрес (r17) в регистр адреса
out EEARL, r17
; Начать запись EEPROM, записав EERE
sbi EECR, EERE
; Читать данные из регистра данных
in r16, EEDR
ret

Пример на Си:

unsigned char EEPROM_read(unsigned char ucAddress)
{
/* Дождаться завершения предыдущей записи */
while(EECR & (1<<EEPE))
;
/* Настроить регистра адреса */
EEARL = ucAddress;
/* Начать чтение EEPROM, записав EERE */
EECR |= (1<<EERE);
/* Вернуть данные из регистра данных */
return EEDR;
}

См. также пример здесь.

Предотвращение повреждения EEPROM

Если напряжение питания VCC слишком низкое (например, во время включения питания), данные в EEPROM можно повредить, потому что нарастание напряжения может оказаться слишком медленным для процессора и EEPROM, что не позволит им работать правильно. Эти вопросы такие же, как для систем, использующих память EEPROM, и должны быть применены такие же проектные решения.

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

Повреждения данных EEPROM можно легко избежать, следуя этому совету по проектированию:

Поддерживайте активный (низкий) сброс AVR во время недостаточного напряжения питания. Это можно сделать, включив внутренний детектор (Brown-out Detector (BOD)). Если уровень напряжения BOD не соответствует необходимому уровню напряжения, то можно использовать внешнюю цепь сброса, поддерживающую низкий уровень на выводе сброса и предохраняющую EEPROM от порчи. Если сброс происходит во время выполнения операции записи, операция записи будет завершена при условии, что напряжение питания достаточно.

ПРИМЕЧАНИЕ
Обычно все типовые схемы предусматривают такую защиту без дополнительного программирования (без использования BOD). Самое простое решение - подключить вход сброса микроконтроллера к плюсу источника питания через резистор, а к минусу - через конденсатор. При подаче питания на входе сброса будет низкий уровень, пока не зарядится конденсатор. То есть микроконтроллер не запустится, пока не зарядится конденсатор. Остаётся только рассчитать номиналы резистора и конденсатора, но это уже другая тема...


Вступить в группу "Основы программирования"

Подписаться на RUTUBE-канал

Подписаться на Дзен-канал

Подписаться на рассылки по программированию

Микроконтроллеры для ЧАЙНИКОВ Микроконтроллеры для ЧАЙНИКОВ

Бесплатная рассылка о микроконтроллерах. Рассылка содержит как бесплатную информацию для начинающих, так и ссылки на платные продукты (книги, видеокурсы и др.) для тех, кто захочет вникнуть в тему более глубоко. Подробнее...

Инфо-МАСТЕР ®
Все права защищены ©
e-mail: mail@info-master.su