Виды eeprom. Основные особенности EEPROM памяти. Внутренняя энергонезависимая память EEPROM

Все микроконтроллеры семейства Mega имеют в своем составе энергонезависимую память (EEPROM память). Объем этой памяти колеблется от 512 байт в моделях ATmega8x до 4 Кбайт в старших моделях. EEPROM память расположена в своем адресном пространстве и так же, как и ОЗУ, организована линейно. Для работы с EEPROM памятью используются три регистра ввода/вывода: регистр адреса, регистр данных и регистр управления.

Регистр адреса

Регистр адреса EEPROM памяти EEAR (EEPROM Address Register) физически размещается в двух РВВ EEARH:EEARL , расположенных по
адресам $1F ($3F) и $1E ($3E) соответственно. В этот регистр загружается адрес ячейки, к которой будет производиться обращение. Регистр адреса доступен как для записи, так и для чтения. При этом в регистре EEARH задействуются только младшие разряды (количество задействованных разрядов зависит от объема EEPROM памяти). Незадействованные разряды регистра EEARH доступны только для чтения и содержат «0».

Регистр данных

Регистр данных EEPROM памяти EEDR (EEPROM Data Register) расположен по адресу $1D ($3D). При записи в этот регистр загружаются данные, которые должны быть помещены в EEPROM , а при чтении в этот регистр помещаются данные, считанные из EEPROM .

Регистр управления

Регистр управления EEPROM памяти EECR (EEPROM Control Register) расположен по адресу $1C ($3C). Этот регистр используется для
управления доступом к EEPROM памяти. Его описание показано ниже в таблице:

Разряд Название Описание
7..4 - не используются, читаются как "0"
3 EERIE Разрешение прерывания от EEPROM. Этот разряд управляет генерацией прерывания, возникающего при завершении цикла записи в EEPROM. Если этот разряд установлен в «1», прерывания разрешены (если флаг I регистра
SREG также установлен в «1»). При сброшенном разряде EEWE (см. далее в
таблице) прерывание генерируется постоянно
2 EEMWE Управление разрешением записи в EEPROM. Состояние этого разряда определяет функционирование флага разрешения записи EEWE. Если данный разряд установлен в «1», то при записи в разряд EEWE «1» происходит запись данных в EEPROM. В противном случае установка EEWE в «1» не производит никакого эффекта. После программной установки разряд EEMWE сбрасывается аппаратно через
4 машинных цикла
1 EEWE Разрешение записи в EEPROM. При установке этого разряда в «1» происходит запись данных в EEPROM (если EEMWE равен «1»)
0 EERE Разрешение чтения из EEPROM. После установки этого разряда в «1» выполняется чтение данных из EEPROM. По окончании чтения этот разряд сбрасывается аппаратно

Для записи одного байта в EEPROM необходимо:

1. Дождаться готовности EEPROM к записи данных (ждать пока не сбросится флаг EEWE регистра EECR).

2. Дождаться завершения записи во FLASH память программ (ждать пока не сбросится флаг SPMEN регистра SPMCR).

3. Загрузить байт данных в регистр EEDR, а требуемый адрес - в регистр EEAR (при необходимости).

4. Установить в «1» флаг EEMWE регистра EECR.

5. Записать в разряд EEWE регистра EECR лог. «1» в течение 4-х машинных циклов. После установки этого разряда процессор
пропускает 2 машинных цикла перед выполнением следующей инструкции.

Для чтения одного байта из EEPROM необходимо:

1. Проконтролировать состояние флага EEWE. Дело в том, что пока выполняется операция записи в EEPROM память (флаг EEWE установлен), нельзя выполнять ни чтения EEPROM памяти, ни изменения регистра адреса.

2. Загрузить требуемый адрес в регистр EEAR.

3. Установить в «1» разряд EERE регистра EECR.

Когда запрошенные данные будут помещены в регистр данных EEDR, произойдет аппаратный сброс этого разряда. Однако следить за состоянием разряда EERE для определения момента завершения операции чтения не требуется, т. к. операция чтения из EEPROM всегда выполняется за один машинный цикл. Кроме того, после установки разряда EERE в «1» процессор пропускает 4 машинных цикла перед началом выполнения следующей инструкции.

В среде AVR Studio GCC есть стандартная библиотека для работы с EEPROM которая включается подключением файла . Основными функциями являются eeprom_read_byte(), eeprom_write_byte(), eeprom_read_word(), eeprom_write_word(). Для примера напишем программу мини-счетчика от 0 до 9, где при нажатии на одну кнопку будет добавляться значение, а на другую кнопку будет сохраняться это значение в памяти. Микроконтроллер Atmega8 работает от внутреннего тактового генератора частотой 8МГц. Одноразрядный семисегментный индикатор с общим анодом через токоограничительные резисторы R1-R7 подключается к порту В, общий анод к плюсу питания. Схема показана ниже:

Для начала подключаем необходимые для работы библиотеки, в том числе EEPROM. Определяем переменные. Переменная "s" хранит значение для вывода на индикатор, при нажатии на кнопку SB1 это значение увеличивается на единицу, но не больше 10. Переменная eeprom_var будет взаимодействовать с EEPROM. При включении питания читается EEPROM, считанные данные присваиваются переменной "s", исходя из этого на индикатор выводится определенная цифра. При нажатии на SB2 данные из переменной "s" записываютя в EEPROM, при этом индикатор мигнет один раз.

#include #include #include #define d0 ~(0x3F) // 0 #define d1 ~(0x06) // 1 #define d2 ~(0x5B) // 2 #define d3 ~(0x4F) // 3 #define d4 ~(0x66) // 4 #define d5 ~(0x6D) // 5 #define d6 ~(0x7D) // 6 #define d7 ~(0x07) // 7 #define d8 ~(0x7F) // 8 #define d9 ~(0x6F) // 9 unsigned char s; unsigned char eeprom_var EEMEM; // определяем переменную в EEPROM int main (void) { DDRB = 0xFF; // Порт В на выход PORTB = 0xFF; DDRD = 0x00; // Порт D на вход PORTD = 0xFF; // Включаем подтагивающие резисторы s = eeprom_read_byte(&eeprom_var); // считываем байт из EEPROM и помещаем его в "s" while(1) { if((PIND&(1 << PD0)) == 0) // если кнопка SB1 нажата { while((PIND&(1 << PD0)) == 0){} // ждем отпускания кнопки s++; // увеличиваем "s" на единицу _delay_ms(200); } if(s == 10) // Когда дойдет до 10 обнуляем "s" { s = 0; } if((PIND&(1 << PD1)) == 0) // если кнопка SB2 нажата { while((PIND&(1 << PD1)) == 0){} // ждем отпускания кнопки DDRB = 0xFF; // мигаем индикатором _delay_ms(200); DDRB = 0x00; _delay_ms(200); DDRB = 0xFF; eeprom_write_byte(&eeprom_var, s); // записываем "s" в EEPROM _delay_ms(200); } if(s==0) // Выводим цифры на индикатор PORTB = d0; if(s==1) PORTB = d1; if(s==2) PORTB = d2; if(s==3) PORTB = d3; if(s==4) PORTB = d4; if(s==5) PORTB = d5; if(s==6) PORTB = d6; if(s==7) PORTB = d7; if(s==8) PORTB = d8; if(s==9) PORTB = d9; } }

Комментарии

0 AntonChip 02.05.2013 22:15

Цитирую Макс:

Может я что-то путаю,но если у Вас индикатор с ОА, то достаточно одного резистора на линии 5в.Зачем ставить токоограничительные резисторы после элемента, который они должны защищать от большого тока??


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

0 AntonChip 15.05.2013 11:16

Цитирую gydok:

А как записать в eeprom двумерный массив?


Код:
#include // Подключаем библиотеку

EEMEM unsigned char colors={{1, 2, 3}, // Объявляем массив в EEPROM
{4, 5, 6}};

eeprom_write_byte(&colors, 1); // Запись элементов массива в EEPROM
eeprom_write_byte(&colors, 2);
eeprom_write_byte(&colors, 3);
eeprom_write_byte(&colors, 4);
eeprom_write_byte(&colors, 5);
eeprom_write_byte(&colors, 6);

unsigned char temp;
temp = eeprom_read_byte(&colors); // Извлекаем из EEPROM элемент массива, 2 строка(), 1 столбец(), т.е. цифру 4

Энергонезависимая
  • EEPROM
  • Первые разработки
  • Перспективные
    • CBRAM
    • SONOS
    • Беговая память (Racetrack)
  • Из истории
    • Память на магнитной проволоке
    • Пузырьковая память
    • Память на твисторах
  • Изменение заряда («запись» и «стирание») производится приложением между затвором и истоком большого потенциала чтобы напряженность электрического поля в тонком диэлектрике между каналом транзистора и карманом оказалась достаточна для возникновения туннельного эффекта . Для усиления эффекта тунеллирования электронов в карман при записи применяется небольшое ускорение электронов путем пропускания тока через канал полевого транзистора (эффект Hot carrier injection (англ.) русск. ).

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

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

    Эта конструкция снабжается элементами которые позволяют ей работать в большом массиве таких же ячеек. Соединение выполняется в виде двумерной матрицы, в которой на пересечении столбцов и строк находится одна ячейка. Поскольку ячейка EEPROM имеет третий затвор то помимо подложки к каждой ячейке подходят 3 проводника (один проводник столбцов и 2 проводника строк).

    Список производителей EEPROM

    • Mikron Sitronics
    • Aplus Flash Technology
    • Maxwell Technologies
    • Renesas Technology
    • ROHM Electronics
    • SmarfTech
    • Seiko Instruments
    • Winbond
    • Catalyst Semiconductor Inc

    Примечания


    Wikimedia Foundation . 2010 .

    Смотреть что такое "EEPROM" в других словарях:

      EEPROM - (also written E2PROM and pronounced e e prom or simply e squared), which stands for Electrically Erasable Programmable Read Only Memory, is a type of non volatile memory used in computers and other electronic devices to store small amounts of… … Wikipedia

      EEPROM - das, spezielle Ausführung eines EPROM. Wie bei diesem Speicherchip lässt sich auch der Inhalt eines EEPROM im… … Universal-Lexikon

      EEPROM - son las siglas de electrically erasable programmable read only memory (ROM programable y borrable eléctricamente). Es un tipo de memoria ROM que puede ser programado, borrado y reprogramado eléctricamente, a diferencia de la EPROM que ha de… … Enciclopedia Universal

      EEPROM - ● EEPROM nom féminin invariable (abréviation de electrically erasable programmable read only memory) Type de mémoires électroniques mortes reprogrammables, effaçables électriquement … Encyclopédie Universelle

      EEPROM - der; , s Kurzw. aus engl. electrically erasable programmable read only memory »elektrisch löschbarer (u. wieder) programmierbarer Nurlesespeicher«> Festwertspeicher, der mit einem elektrischen Signal gelöscht werden kann (EDV) … Das große Fremdwörterbuch

      EEPROM - (Electrically Erasable Programmable Read Only Memo) type of Read Only Memory that can be erased using electronic methods … English contemporary dictionary

      EEPROM - (computing) abbrev Electronically erasable programmable read only memory * * * [ˌē ē präm; ēˌpräm; dəbəl ē präm] n. Computing a read only memory whose contents can be erased and reprogrammed using a pulsed voltage Origin: acronym from… … Useful english dictionary

      EEPROM - Ein Flash EEPROM (links) und ein EPROM (rechts). EEPROM (Electrically Erasable Programmable Read Only Memory, wörtlich: elektrisch löschbarer, programmierbarer Nur Lese Speicher, auch E2PROM genannt) ist ein nichtflüchtiger, elektronischer… … Deutsch Wikipedia

      EEPROM - Electrically erasable programmable read only memory Types de mémoire RAM et ROM Volatiles DRAM eDRAM SRAM 1T SRAM à venir: Z RAM Non Volatiles ROM PROM EPROM EEPROM à venir … Wikipédia en Français

      EEPROM - Este artículo o sección necesita referencias que aparezcan en una publicación acreditada, como revistas especializadas, monografías, prensa diaria o páginas de Internet fidedignas. Puedes añadirlas así o avisar … Wikipedia Español

    Arduino – это целое семейство различных устройств для создания электронных проектов. Микроконтроллеры очень удобны для использования, доступны к освоению даже новичку. Каждый микроконтроллер состоит из платы, программ для обеспечения работы, памяти. В этой статье будет рассмотрена энергонезависимая память, используемая в Arduino.

    Описание памяти EEPROM

    Ардуино предоставляет своим пользователям три типа встроенной памяти устройств: стационарное ОЗУ (оперативно-запоминающее устройство или SRAM - static random access memory) – необходимо для записи и хранения данных в процессе использования; флеш-карты – для сохранения уже записанных схем; – для хранения и последующего использования данных.

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

    Аббревиатура расшифровывается, как Electrically Erasable Programmable Read-Only Memory и в переводе на русский дословно означает – электрически стираемая программируемая память только для чтения. Производитель гарантирует сохранность информации на несколько десятилетий вперед после последнего отключения питания (обычно приводят срок в 20 лет, зависит от скорости снижения заряда устройства).

    При этом нужно знать, что возможность перезаписи на устройство ограничена и составляет не более 100 000 раз. Поэтому рекомендуют аккуратно и внимательно относиться к вносимым данным и не допускать перезаписи лишний раз.

    Объем памяти, в сравнении с современными носителями, очень небольшой и разный для различных микроконтроллеров. Например, для:

    • ATmega328 – 1кБ
    • ATmega168 и ATmega8 – 512 байт,
    • и ATmega1280 – 4 кБ.

    Так устроено потому, что каждый микроконтроллер предназначен для определенного объема задач, имеет разное количество выводов для подключения, соответственно, необходим разный объем памяти. При этом такого количества достаточно для обычно создаваемых проектов.

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

    Библиотека

    Работа с памятью EEPROM осуществляется с помощью библиотеки, которая была специально создана для Ардуино. Главными являются способность к записи и чтению данных. активируется командой #include EEPROM.h .

    • для записи – EEPROM.write(address, data);
    • для чтения – EEPROM.read(address).

    В данных скетчах: address – аргумент с данными ячейки, куда вносятся данные второго аргумента data; при считывании используется один аргумент address, который показывает, откуда следует читать информацию.

    Функция Назначение
    read(address) считывает 1 байт из EEPROM ; address – адрес, откуда считываются данные (ячейка, начиная с 0);
    write(address, value) записывает в память значение value (1 байт, число от 0 до 255) по адресу address;
    update(address, value) заменяет значение value по адресу address, если её старое содержимое отличается от нового;
    get(address, data) считывает данные data указанного типа из памяти по адресу address;
    put(address, data) записывает данные data указанного типа в память по адресу address;
    EEPROM позволяет использовать идентификатор "EEPROM" как массив, чтобы записывать данные в память и считывать их из памяти.

    Запись целых чисел

    Запись целых чисел в энергонезависимую память EEPROM осуществить достаточно просто. Внесение чисел происходит с запуском функции EEPROM.write() . В скобках указываются необходимые данные. При этом числа от 0 до 255 и числа свыше 255 записываются по-разному. Первые вносятся просто – их объем занимает 1 байт, то есть одну ячейку. Для записи вторых необходимо использовать операторов highByte() высший байт и lowByte() низший байт.

    Число делится на байты и записывается отдельно по ячейкам. Например, число 789 запишется в две ячейки: в первую пойдет множитель 3, а во вторую – недостающее значение. В итоге получается необходимое значение:

    3 * 256 + 21 = 789

    Для « воссоединения» большого целого числа применяется функция word(): int val = word(hi, low) . Нужно читывать, что максимальное целое число для записи – 65536 (то есть 2 в степени 16). В ячейках, в которых еще не было иных записей, на мониторе будут стоять цифры 255 в каждой.

    Запись чисел с плавающей запятой и строк

    Числа с плавающей запятой и строк – это форма записи действительных чисел, где они представляются из мантиссы и показателя степени. Запись таких чисел в энергонезависимую память EEPROM производится с активацией функции EEPROM.put() , считывание, соответственно, – EEPROM.get() .

    При программировании числовые значения с плавающей запятой обозначаются, как float, стоит отметить, что это не команда, а именно число. Тип Char (символьный тип) – используется для обозначения строк. Процесс записи чисел на мониторе запускается при помощи setup(), считывание – с помощью loop().

    В процессе на экране монитора могут появиться значения ovf, что значит «переполнено», и nan, что значит «отсутствует числовое значение». Это говорит о том, что записанная в ячейку информация не может быть воспроизведена, как число с плавающей точкой. Такой ситуации не возникнет, если достоверно знать, в какой ячейке какой тип информации записан.

    Примеры проектов и скетчей

    Пример №1

    Скетч запишет до 16 символов с последовательного порта и в цикле выведет 16 символов из EEPROM. Благодаря данные записываются в EEPROM и контролируется содержимое энергонезависимой памяти.

    // проверка работы EEPROM #include int i, d; void setup() { Serial.begin(9600); // инициализируем порт, скорость 9600 } void loop() { // чтение EEPROM и вывод 16 данных в последовательный порт Serial.println(); Serial.print("EEPROM= "); i= 0; while(i < 16) { Serial.print((char)EEPROM.read(i)); i++; } // проверка есть ли данные для записи if (Serial.available() != 0) { delay(50); // ожидание окончания приема данных // запись в EEPROM i= 0; while(i < 20) { d= Serial.read(); if (d == -1) d= " "; // если символы закончились, заполнение пробелами EEPROM.write(i, (byte)d); // запись EEPROM i++; } } delay(500); }

    Пример №2

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

    #include int address = 0; // адрес eeprom int read_value = 0; // считываемые с eeprom данные char serial_in_data; // данные последовательного порта int led = 6; // линия 6 для светодиода int i; void setup() { pinMode(led, OUTPUT); // линия 6 настраивается на выход Serial.begin(9600); // скорость передачи по последовательному порту 9600 Serial.println(); Serial.println("PREVIOUS TEXT IN EEPROM:-"); for(address = 0; address < 1024; address ++) // считываем всю память EEPROM { read_value = EEPROM.read(address); Serial.write(read_value); } Serial.println(); Serial.println("WRITE THE NEW TEXT: "); for(address = 0; address < 1024; address ++) // заполняем всю память EEPROM пробелами EEPROM.write(address, " "); for(address = 0; address < 1024;) // записываем пришедшие с последовательного порта данные в память EEPROM { if(Serial.available()) { serial_in_data = Serial.read(); Serial.write(serial_in_data); EEPROM.write(address, serial_in_data); address ++; digitalWrite(led, HIGH); delay(100); digitalWrite(led, LOW); } } } void loop() { //---- мигаем светодиодом каждую секунду -----// digitalWrite(led, HIGH); delay(1000); digitalWrite(led, LOW); delay(1000); }

    Пример №3

    Запись в память два целых числа, чтение их из EEPROM и вывод в последовательный порт. Числа от 0 до 255 занимают 1 байт памяти, с помощью функции EEPROM.write() записываются в нужную ячейку. Для чисел больше 255 их нужно делить на байты с помощью highByte() и lowByte() и записывать каждый байт в свою ячейку. Максимальное число при этом – 65536 (или 2 16).

    #include // подключаем библиотеку EEPROM void setup() { int smallNum = 123; // целое число от 0 до 255 EEPROM.write(0, smallNum); // запись числа в ячейку 0 int bigNum = 789; // число > 255 разбиваем на 2 байта (макс. 65536) byte hi = highByte(bigNum); // старший байт byte low = lowByte(bigNum); // младший байт EEPROM.write(1, hi); // записываем в ячейку 1 старший байт EEPROM.write(2, low); // записываем в ячейку 2 младший байт Serial.begin(9600); // инициализация послед. порта } void loop() { for (int addr=0; addr<1024; addr++) { // для всех ячеек памяти (для Arduino UNO 1024) byte val = EEPROM.read(addr); // считываем 1 байт по адресу ячейки Serial.print(addr); // выводим адрес в послед. порт Serial.print("\t"); // табуляция Serial.println(val); // выводим значение в послед. порт } delay(60000); // задержка 1 мин }

    Пример №4

    Запись чисел с плавающей запятой и строк - метод EEPROM.put() . Чтение – EEPROM.get() .

    #include // подключаем библиотеку void setup() { int addr = 0; // адрес float f = 3.1415926f; // число с плавающей точкой (типа float) EEPROM.put(addr, f); // записали число f по адресу addr addr += sizeof(float); // вычисляем следующую свободную ячейку памяти char name = "Hello, SolTau.ru!"; // создаём массив символов EEPROM.put(addr, name); // записываем массив в EEPROM Serial.begin(9600); // инициализация послед. порта } void loop() { for (int addr=0; addr<1024; addr++) { // для всех ячеек памяти (1024Б=1кБ) Serial.print(addr); // выводим адрес в послед. порт Serial.print("\t"); // табуляция float f; // переменная для хранения значений типа float EEPROM.get(addr, f); // получаем значение типа float по адресу addr Serial.print(f, 5); // выводим с точностью 5 знаков после запятой Serial.print("\t"); // табуляция char c; // переменная для хранения массива из 20 символов EEPROM.get(addr, c); // считываем массив символов по адресу addr Serial.println(c); // выводим массив в порт } delay(60000); // ждём 1 минуту }

    Пример №5

    Использование EEPROM как массива.

    #include void setup() { EEPROM = 11; // записываем 1-ю ячейку EEPROM = 121; // записываем 2-ю ячейку EEPROM = 141; // записываем 3-ю ячейку EEPROM = 236; // записываем 4-ю ячейку Serial.begin(9600); } void loop() { for (int addr=0; addr<1024; addr++) { Serial.print(addr); Serial.print("\t"); int n = EEPROM; // считываем ячейку по адресу addr Serial.println(n); // выводим в порт } delay(60000); }

    Работа с EEPROM

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

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

    Такая память на Ардуино стандартно хранит самое важное для работы контроллера и устройства. К примеру, если на такой базе создается регулятор температуры и исходные данные окажутся ошибочными, устройство будет работать «неадекватно» существующим условиям – сильно занижать или завышать температуру.

    Существует несколько ситуаций, когда память EEPROM содержит неправильные данные:

    1. При первоначальной активации – еще не было ни одной записи.
    2. В момент неконтролируемого отключения питания – часть или все данные не запишутся или запишутся некорректно.
    3. После завершения возможных циклов перезаписи данных.

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

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

    Опытные программисты добавляют к этому коду дополнительное «исключающее ИЛИ», например, E5h. В случае если все значения равны нулю, а система по ошибке обнулила исходные данные – такая хитрость выявит ошибку.

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

    На заре возникновения памяти, сохраняющей данные при отключении пита­ния (EPROM, Erasable Programmable ROM - «стираемая/программируемая ROM», или по-русски ППЗУ - «программируемое ПЗУ»), основным типом ее была память, стираемая ультрафиолетом: UV-EPROM (Ultra-Violet EPROM, УФ-ППЗУ). Причем часто приставку UV опускали, так как всем бы­ло понятно, что EPROM - это стираемая ультрафиолетом, а ROM (или ПЗУ) просто, без добавлений- это однократно программируемые кристаллы OTP-ROM. Микроконтроллеры с УФ-памятью программ были распростране­ны еще в середине 1990-х. В рабочих образцах устройств с УФ-памятью кварцевое окошечко, через которое осуществлялось стирание, заклеивали кусочком черной липкой ленты, так как информация в UV-EPROM медленно разрушается и на солнечном свету.

    Рис. 18.7. Устройство элементарной ячейки EPROM

    На рис. 18.7 показано устройство элементарной ячейки EPROM, которая ле­жит в основе всех современных типов flash-памяти. Если исключить из нее то, что обозначено надписью «плавающий затвор», мы получим самый обыч­ный полевой транзистор - точно такой же входит в ячейку DRAM. Если по­дать на управляющий затвор такого транзистора положительное напряжение, то он откроется, и через него потечет ток (это считается состоянием логиче­ской единицы). На рис. 18.7 вверху-и изображен такой случай, когда пла­вающий затвор не оказывает никакого влияния на работу ячейки - напри­мер, такое состояние характерно для чистой flash-памяти, в которую еще ни разу ничего не записывали.

    Если же мы каким-то образом (каким- поговорим отдельно) ухитримся разместить на плавающем затворе некоторое количество зарядов - свобод­ных электронов, которые показаны на рис. 18.7 внизу в виде темных кружоч­ков со значком минуса, то они будуу экранировать действие управляющего электрода, и такой транзистор вообще перестанет проводить ток. Это состоя­ние логического нуля. Поскольку плавающий затвор потому так и называет­ся, что он «плавает» в толще изолятора (двуокиси кремния), то сообщенные ему однажды заряды в покое никуда деваться не могут. И записанная таким образом информация может храниться десятилетиями (до последнего време­ни производители обычно давали гарантию на 10 лет, но на практике в обыч­ных условиях время хранения значительно больше).

    Заметки на полях

    Строго говоря, в NAND-чипах (о которых далее) логика обязана быть обрат­ной. Если в обычной EPROM запрограммированную ячейку вы не можете от­крыть подачей считывающего напряжения, то там наоборот - ее нельзя запе­реть снятием напряжения. Поэтому, в частности, чистая NAND-память выдает все нули, а не единицы, как EPROM. Но это нюансы, которые не меняют суть дела.

    Octajiocb всего ничего - придумать, как размещать заряды на изолирован­ном от всех внешних влияний плавающем затворе. И не только разме­щать - ведь иногда память и стирать приходится, потому должен сущест­вовать способ их извлекать оттуда. В UV-EPROM слой окисла между плавающим затвором и подложкой был достаточно толстым (если величину 50 нанометров можно охарактеризовать словом «толстый», конечно), и ра­ботало все это довольно грубо. При записи на управляющий затвор подава­ли достаточно высокое положительное напряжение - иногда до 36-40 В, а на сток транзистора - небольшое положительное. При этом электроны, которые двигались от истока к стоку, настолько ускорялись полем управ­ляющего электрода, что просто перепрыгивали барьер в виде изолятора между подложкой и плавающим затвором. Такой процесс называется еще «инжекцией горячих электронов».

    Ток заряда при этом достигал миллиампера - можете себе представить, ка­ково было потребление всей схемы, если в ней одновременно программиро­вать хотя бы несколько тысяч ячеек. И хотя такой ток требовался на доста­точно короткое время (впрочем, с точки зрения быстродействия схемы не такое уж и короткое - миллисекунды), но это было крупнейшим недостат­ком всех старых образцов EPROM-памяти. Еще хуже другое - и изолятор, и сам плавающий затвор такого издевательства долго не выдерживали и посте­пенно деградировали, отчего количество циклов стирания-записи было огра­ничено нескольким сотнями, максимум- тысячами. Во многих образцах flash-памяти более позднего времени даже была предусмотрена специальная схема для хранения карты «битых» ячеек - в точности так, как это делается для жестких дисков. В современных моделях с миллионами ячеек такая карта тоже имеется - однако число циклов стирания/записи теперь возросло до сотен тысяч. Как этого удалось добиться?

    Рис. 18.8. Процесс стирания в элементарной ячейке EPROM

    Сначала посмотрим, как осуществлялось в этой схеме стирание. В UV-EPROM при облучении ультрафиолетом фотоны высокой энергии сообщали электронам на плавающем затэоре достаточный импульс для того, чтобы они «прыгали» обратно на подложку самостоятельно, без каких-либо электриче­ских воздействий. Первые образцы электрически стираемой памяти (EEPROM, Electrically Erasable Programmable ROM - «электрически стирае­мое перепрограммируемое ПЗУ», ЭСППЗУ) были созданы в компании Intel в. конце 1970-х при непосредственном участии будущего основателя Atmel Джорджа Перлегоса. Он использовал «квантовый эффект туннелирования Фаулера-Нордхейма». За этим непонятным названием кроется довольно про­стое по сути (но очень сложное с физической точки зрения) явление: при достаточно тонкой пленке изолятора (ее толщину пришлось уменьшить с 50 до 10 нм) электроны, если их слегка подтолкнуть подачей не слишком высо­кого напряжения в нужном направлении, могут просачиваться через барьер, не перепрыгивая его. Сам процесс показан на рис. 18.8 вверху (обратите внимание на знак напряжения на управляющем электроде).

    Старые образцы EEPROM именно так и работали: запись производилась «го­рячей инжекцией», а стирание - «квантовым туннелированием». Оттого они были довольно сложны в эксплуатации - разработчики со стажем помнят, что первые микросхемы EEPROM требовали два, а то и три питающих на­пряжения, причем подавать их при записи и стирании требовалось в опреде­ленной последовательности.

    Превращение EEPROM во flash происходило по трем разным направлениям. В первую очередь - в направлении совершенствования конструкции самой ячейки. Для начала избавились от самой противной стадии - «горячей ин-жекции». Вместо нее при записи стали также использовать «квантовое тун-нелирование», как и при стирании. рис. 18.8 внизу показан этот про­цесс- если при открытом транзисторе подать на управляющий затвор достаточно высокое (но значительно меньшее, чем при «горячей инжекции») напряжение, то часть электронов, двигающихся через открытый транзистор от истока к стоку, «просочится» через изолятор и окажется на плавающем затворе. Потребление тока при записи снизилось на несколько порядков. Изолятор, правда, пришлось сделать еще тоньше, что обусловило довольно большие трудности с внедрением этой технологии в производство.

    Второе направление - ячейку сделали несколько сложнее, пристроив к ней второй транзистор (обычный, не двухзатворный), который разделил вывод стока и считывающую шину всей микросхемы. Благодаря всему этому уда­лось добиться значительного повышения долговечности - до сотен тысяч циклов записи/стирания (миллионы циклов, характерные для флэш-карточек, получаются, если добавить схемы коррекции ошибок). Кроме того, схемы формирования высокого напряжения и соответствующие генераторы им­пульсов записи/стирания перенесли внутрь микросхемы, отчего пользоваться этими типами памяти стало несравненно удобнее - они стали питаться от одного напряжения (5, 3,3 или даже 1,8 В).

    И, наконец, третье, едва ли не самое главное усовершенствование заключа­лось в изменении организации доступа к ячейкам на кристалле, вследствие чего этот тип памяти и заслужил наименование - flash (то есть «молния»), ныне известное каждому владельцу цифровой камеры или карманного МРЗ-плеера. Так в середине 1980-х назвали разновидность EEPROM, в ко­торой стирание и запись производились сразу целыми блоками - страни­цами. Процедура чтения из произвольной ячейки, впрочем, по понятным причинам замедлилась- для его ускорения приходится на кристаллах flash-памяти располагать промежуточную (буферную) SRAM. Для флэш-накопителей это не имеет особого значения, так как там все равно данные читаются и пишутся сразу большими массивами, но для использования в микроконтроллерах это может оказаться неудобным. Тем более, в МК не­удобно использовать самый быстродействующий вариант flash-техноло­гии - т. н. память типа NAND (от наименования логической функции «И-НЕ»), где читать и записывать память в принципе возможно только блока­ми по 512 байт (это обычная величина сектора на жестком диске, также чи­таемого и записываемого целиком за один раз - отсюда можно понять ос­новное назначение NAND).

    В МК обычно используют традиционную (типа NOR) flash-память про­грамм, в которой страницы относительно невелики по размерам - порядка 64-256 байт. Впрочем, если пользователь сам не берется за создание про­грамматора для такой микросхемы, он может о страничном характере па­мяти и не догадываться. А для пользовательских данных применяют EEPROM либо с возможностью чтения произвольного байта, либо секцио­нированную, но на очень маленькие блоки - например, по 4 байта. При этом для пользователя все равно доступ остается побайтным. Характерной чертой такой памяти является довольно медленная (порядка миллисекунд) процедура записи, в то время как чтение протекает ничуть не медленнее любых других операций в МК.

    Развитие технологий flash-памяти имело огромное значения для удешевления и доступности микроконтроллеров. В дальнейшем мы будем иметь дело с энергонезависимой памятью не только в виде встроенных в микроконтроллер памяти программ и данных, но и с отдельными микросхемами, позволяющи­ми записывать довольно большие объемы информации.

    Урок 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