Arduino энергонезависимая память: описание, библиотека

Работа со встроенной EEPROM в микроконтроллерах на Arduino

Микроконтроллеры AVR, на основе которых создаются платы Arduino и Genuino, обладают встроенной EEPROM: памятью, которая хранит значения переменных, пока плата выключена (подобно крошечному жесткому диску). Описываемая в данной статье библиотека позволяет считывать и записывать данные в EEPROM.

Поддерживаемые микроконтроллеры на различных платах Arduino и Genuino обладают разным размером EEPROM: 1024 байта в ATmega328, 512 байт в ATmega168 и ATmega8, 4 KB (4096 байт) в ATmega1280 и ATmega2560. Платы Arduino и Genuino 101 обладают эмуляцией EEPROM пространства размером 1024 байт.

Функции для работы с EEPROM:

  • read()
  • write()
  • update()
  • get()
  • put()
  • EEPROM[]

read()

ОписаниеСчитывает байт из EEPROM. Ячейки, которые никогда не были записаны, содержат значение 255.СинтаксисEEPROM.read(address)Параметрыaddress: адрес ячейки для считывания, начинается с 0 (int).Возвращаемое значениеЗначение, записанное в ячейку (byte).Пример/* * EEPROM Read * * Считывает значение каждого байта в EEPROM и выводит его * на компьютер.

*/ #include // начать чтение с первого байта (адрес 0) в EEPROM int address = 0; byte value; void setup() { // инициализировать последовательный порт и ждать, // пока порт не будет открыт: Serial.begin(9600); while (!Serial) { ; // ждать подключения последовательного порта. Необходимо только для встроенного USB порта.

} } void loop() { // прочитать байт из текущего адреса EEPROM value = EEPROM.read(address); Serial.print(address); Serial.print(» «); Serial.print(value, DEC); Serial.println(); /*** Перейти к следующему адресу, или, если находимся в конце, вернуться в начало.

Большие AVR контроллеры обладают большим размером EEPROM, например: — Arduno Duemilanove: 512b EEPROM; — Arduino Uno: 1kb EEPROM; — Arduino Mega: 4kb EEPROM; Вместо жесткого прописывания размера EEPROM, лучше использовать предусмотренную функцию определения размера. Это сделает ваш код портируемым на все микроконтроллеры AVR.

***/ address = address + 1; if (address == EEPROM.

length()) { address = 0; } /*** Поскольку размеры EEPROM являются степенями двойки, то возврат к началу EEPROM можно было бы реализовать с помощью операции побитового И со значением (размер — 1). ++address &= EEPROM.length() — 1; ***/ delay(500); }

write()

ОписаниеЗаписывает байт в EEPROM.СинтаксисEEPROM.write(address, value)Параметрыaddress: адрес ячейки для записи, начинается с 0 (int).
value: значение для записи, от 0 до 255 (byte).Возвращаемое значениеНичего не возвращается.ПримечаниеЗапись в EEPROM занимает 3,3 мс.

Память EEPROM обладает жизненным циклом 100 000 операций записи/стирания, поэтому, возможно, вам придется быть осторожными с тем, как часто записываете её.Пример/* * EEPROM Write * * Записывает значения, считанные с аналогового входа 0, в EEPROM. * Эти значения будут оставаться в EEPROM, когда плата будет * выключена, и могут быть извлечены позже при следующем запуске.

*/ #include /** текущий адрес в EEPROM (т.е. какой байт мы собираемся записать следующим) **/ int addr = 0; void setup() { /** Нет никаких начальных настроек. **/ } void loop() { /*** Необходимо делить на 4, так как диапазон значений на аналоговых входах составляет от 0 до 1023, а каждый байт EEPROM может хранить значения только от 0 до 255.

***/ int val = analogRead(0) / 4; /*** Записать значение в соответствующий байт EEPROM. Эти значения останутся там, когда плата будет выключена. ***/ EEPROM.write(addr, val); /*** Перейти к следующему адресу, или, если находимся в конце, вернуться в начало.

Большие AVR контроллеры обладают большим размером EEPROM, например: — Arduno Duemilanove: 512b EEPROM; — Arduino Uno: 1kb EEPROM; — Arduino Mega: 4kb EEPROM; Вместо жесткого прописывания размера EEPROM, лучше использовать предусмотренную функцию определения размера. Это сделает ваш код портируемым на все микроконтроллеры AVR.

***/ addr = addr + 1; if (addr == EEPROM.

length()) { addr = 0; } /*** Поскольку размеры EEPROM являются степенями двойки, то возврат к началу EEPROM можно было бы реализовать с помощью операции побитового И со значением (размер — 1). ++addr &= EEPROM.length() — 1; ***/ delay(100); }

update()

ОписаниеЗаписывает байт в EEPROM. Значение записывается, только если оно отличается от значения уже записанного по этому адресу.СинтаксисEEPROM.update(address, value)Параметрыaddress: адрес ячейки для записи, начинается с 0 (int).
value: значение для записи, от 0 до 255 (byte).Возвращаемое значениеНичего не возвращается.

ПримечаниеЗапись в EEPROM занимает 3,3 мс. Память EEPROM обладает жизненным циклом 100 000 операций записи/стирания, поэтому данная функция, в отличие от write(), может сохранить время, если записываемые данные часто не меняются.Пример/*** EEPROM Update Сохраняет значения, считанные с аналогового входа 0, в EEPROM.

Эти значения будут оставаться в EEPROM, когда плата будет выключена, и могут быть извлечены позже при следующем запуске. Если значение не изменилось, то EEPROM не перезаписывается, что поможет без необходимости не сокращать срок службы EEPROM. ***/ #include /** текущий адрес в EEPROM (т.е.

какой байт мы собираемся записать следующим) **/ int address = 0; void setup() { /** EMpty setup **/ } void loop() { /*** Необходимо делить на 4, так как диапазон значений на аналоговых входах составляет от 0 до 1023, а каждый байт EEPROM может хранить значения только от 0 до 255. ***/ int val = analogRead(0) / 4; /*** Обновить конкретную ячейку EEPROM.

Эти значения останутся там при выключении платы. ***/ EEPROM.update(address, val); /*** Функция EEPROM.update(address, val) эквивалентна следующему: if( EEPROM.read(address) != val ){ EEPROM.write(address, val); } ***/ /*** Перейти к следующему адресу, или, если находимся в конце, вернуться в начало.

Большие AVR контроллеры обладают большим размером EEPROM, например: — Arduno Duemilanove: 512b EEPROM; — Arduino Uno: 1kb EEPROM; — Arduino Mega: 4kb EEPROM; Вместо жесткого прописывания размера EEPROM, лучше использовать предусмотренную функцию определения размера. Это сделает ваш код портируемым на все микроконтроллеры AVR.

***/ address = address + 1; if (address == EEPROM.

length()) { address = 0; } /*** Поскольку размеры EEPROM являются степенями двойки, то возврат к началу EEPROM можно было бы реализовать с помощью операции побитового И со значением (размер — 1). ++addr &= EEPROM.length() — 1; ***/ delay(100); }

get()

ОписаниеСчитывает любой тип данных или объект из EEPROM.СинтаксисEEPROM.get(address, data)Параметрыaddress: адрес для чтения, начинается с 0 (int).
data: данные для чтения, могут быть примитивным типом (например, float) или пользовательской структурой struct.Возвращаемое значениеСсылка на переданные данные.

Пример/*** Чтобы предварительно записать данные в EEPROM, используйте пример для функции put(). Можно обойтись и без этого, но значения, выводимые этим скетчем, зависят от того, что содержится в EEPROM.

Это может заставить объект последовательного порта вывести на печать длинную строку мусора, если в загруженной строке не будет найден нулевой символ. ***/ #include void setup() { float f = 0.00f; // Переменная для хранения данных, прочитанных из EEPROM. int eeAddress = 0; // Адрес EEPROM, откуда следует начать чтение. Serial.

begin(9600); while (!Serial) { ; // ждать подключения последовательного порта. Необходимо только для встроенного USB порта. } Serial.print(«Read float from EEPROM: «); // Получить данные типа float из EEPROM в месте 'eeAddress' EEPROM.get(eeAddress, f); Serial.

println(f, 3); // Это может напечатать 'ovf, nan', если данные в EEPROM // не корректны для float. /*** Так как get возвращает ссылку на 'f', вы можете использовать ее в качестве аргумента То есть: Serial.print( EEPROM.get( eeAddress, f ) ); ***/ /*** Get может использоваться и с пользовательскими структурами.

Пример с ними выделен в отдельную функцию. ***/ secondTest(); // Запустить следующий тест. } struct MyObject { float field1; byte field2; char name[10]; }; void secondTest() { int eeAddress = sizeof(float); // Переместить адрес к байту, следующему после float 'f'.

MyObject customVar; // Переменная для хранения данных, прочитанных из EEPROM. EEPROM.get(eeAddress, customVar); Serial.println(«Read custom object from EEPROM: «); Serial.println(customVar.field1); Serial.println(customVar.field2); Serial.println(customVar.name); } void loop() { /* Пустой цикл */ }

put()

ОписаниеЗаписывает любой тип данных или объект из EEPROM.СинтаксисEEPROM.put(address, data)Параметрыaddress: адрес для записи, начинается с 0 (int).
data: данные для записи, могут быть примитивным типом (например, float) или пользовательской структурой struct.Возвращаемое значениеСсылка на переданные данные.

ПримечаниеФункция используетEEPROM.update()для реализации записи, поэтому она не перезаписывает значение, если оно не изменилось.Пример/*** Этот скетч также можно использовать для предварительной записи в EEPROM данных, используемых в примере для функции get(). Обратите внимание, что, в отличие от однобайтной версии EEPROM.

write(), функция put использует обновление. То есть байт будет записан, только если он отличается от записанных в EEPROM данных. ***/ #include struct MyObject { float field1; byte field2; char name[10]; }; void setup() { Serial.begin(9600); while (!Serial) { ; // ждать подключения последовательного порта.

Необходимо только для встроенного USB порта. } float f = 123.456f; // Переменная для записи в EEPROM. int eeAddress = 0; // Место, куда мы хотим положить данные. // Простой вызов с адресом и переменной в качестве аргументов. EEPROM.put(eeAddress, f); Serial.

println(«Written float data type!»); /** Put поддерживает и пользовательские структуры. **/ //Data to store. MyObject customVar = { 3.14f, 65, «Working!» }; eeAddress += sizeof(float); // Переместить адрес к байту, следующему после float 'f'. EEPROM.put(eeAddress, customVar); Serial.

print(«Written custom data type!

View the example sketch eeprom_get to see how you can retrieve the values!»); } void loop() { /* Пустой цикл */ }

EEPROM[]

ОписаниеДанный оператор позволяет использовать идентификатор 'EEPROM', как массив. Ячейки EEPROM могут быть прочитаны и записаны непосредственно с помощью этого оператора.СинтаксисEEPROM[address]Параметрыaddress: адрес для чтения/записи, начинается с 0 (int).

Возвращаемое значениеСсылка на ячейку EEPROM.Пример#include void setup(){ unsigned char val; // Прочитать первую ячейку EEPROM. val = EEPROM[ 0 ]; // Записать первую ячейку EEPROM. EEPROM[ 0 ] = val; // Сравнить содержимое if( val == EEPROM[ 0 ] ){ // Сделать что-то…

} } void loop(){ /* Пустой цикл */ }

Источник:

На сайте работает сервис комментирования DISQUS, который позволяет вам оставлять комментарии на множестве сайтов, имея лишь один аккаунт на Disqus.com.

Читайте также:  Ардуино через интернет: управление и контроль

Источник: https://radioprog.ru/post/117

Работа с энергонезависимой памятью в Arduino (EEPROM)

Микроконтроллеры Atmega328, работающие в Arduino UNO и NANO имеют на борту 1024 байт EEPROM – энергонезависимой памяти, в которой можно сохранять какие-либо данные, которые будут доступны после отключения питания.

Это может пригодиться для хранения каких-нибудь данных или значений.

Для работы с данной памятью в составе Arduino IDE уже есть удобная библиотека EEPROM (hardwarelibrariesEEPROM).

byte EEPROM.read(address)

Описание:

Считывает байт из энергонезависимой памяти EEPROM. Если байт до этого никогда не перезаписывался – вернёт значение 255.

Параметры:

address: порядковый номер ячейки памяти для чтения — от 0 до 511 (int)

Возвращаемое значение:

Байт, хранимый в ячейке памяти.

Пример (File-Examples-EEPROM-eeprom_read):

/* * Чтение EEPROM * * Считывает значения всех байтов энергонезависимой памяти * EEPROM и выводит их в COM-порт */ #include // начальный адрес памяти EEPROM int address = 0; byte value; void setup() {  Serial.begin(9600); } void loop() {  // считываем значение по текущему адресу EEPROM  value = EEPROM.read(address);  Serial.print(address);  Serial.print(» «);  Serial.print(value, DEC);  Serial.println();  // устанавливаем следующую ячейку памяти  address = address + 1;  // EEPROM содержит всего 512 байт: от 0 до 511, поэтому  // если адрес достиг 512, то снова переходим на 0  if (address == 512)    address = 0;  delay(500); }

void EEPROM.write(address, value)

Описание:

Записывает байт в энергонезависимую память

Параметры:

address: порядковый номер ячейки памяти для записи — от 0 до 511 (int)
value: байт для записи – от 0 до 255 (byte)

Возвращаемое значение:

ничего

Примечание:

Документация (datasheet) на микроконтроллеры Atmega8/168 говорит, что возможное количество циклов перезаписи данных в памяти ограничено 100000 раз (Write/Erase Cycles). Это следует учитывать при использовании данной памяти.

Так же документация указывает, что время, требуемое для завершения цикла записи составляет 3.3 ms.

Если в это время попытаться что-либо считать/записать в EEPROM, то такая попытка окончится неудачей 🙁
Однако, данная задержка уже учитывается библиотекой EEPROM, поэтому в дополнительном вызове delay() нет необходимости.

Пример (File-Examples-EEPROM-eeprom_write):

/*   * EEPROM Write   *   * Сохраняет в энергонезависимой памяти EEPROM значения,   * считанные с аналогового входа analog input 0.   * Данные значения останутся в памяти и после отключения питания   * от платы и в будущем могут быть доступны для   * другого скетча.  */ #include // текущее значение адреса EEPROM int addr = 0; void setup() { } void loop() {  // деление на 4 необходимо, чтобы перевести значение от  // 0-1023 к одному байту, т.к. EEPROM может хранить только  // значения от 0 до 255.  int val = analogRead(0) / 4;  // записываем значение в энергонезависимую память  EEPROM.write(addr, val);  // устанавливаем следующую ячейку памяти.  // т.к. EEPROM содержит всего 512 ячеек – при достижении  // конца памяти – возвращаемся на начало 🙂  addr = addr + 1;  if (addr == 512)    addr = 0;  delay(100); }

В примере eeprom_clear (File-Examples-EEPROM-eeprom_clear)
показано, как произвести очистку памяти – просто заполнить её нулями:

// записываем 0 во все 512 байт памяти EEPROM for (int i = 0; i > 0) & 0xFF);  byte highByte = ((p_value >> 8) & 0xFF);  EEPROM.write(p_address, lowByte);  EEPROM.write(p_address + 1, highByte); } //Эта функция прочитает 2 байта типа integer из eeprom с адресов address и address + 1 unsigned int EEPROMReadInt(int p_address) {  byte lowByte = EEPROM.read(p_address);  byte highByte = EEPROM.read(p_address + 1);  return ((lowByte

Источник: http://www.2150692.ru/faq/38-arduino-eeprom

Как хранить данные в Arduino

У плат семейства плат Arduino есть несколько видов памяти. Во-первых, это статическое ОЗУ (оперативное запоминающее устройство), которая используется для хранения переменных в процессе выполнения программы. Во-вторых, это флеш-память, в которой хранятся написанные вами скетчи.

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

Последний тип памяти – EEPROM – позволяет записывать данные, хранить их и считывать при необходимости. Эту память мы и рассмотрим сейчас.

EEPROM означает Electrically Erasable Programmable Read-Only Memory, т.е. электрически стираемое перепрограммируемое постоянное запоминающее устройство. Данные в этой памяти могут храниться десятки лет после отключения питания. Количество циклов перезаписи – порядка нескольких миллионов раз.

Количество EEPROM памяти в Arduino довольно ограничено:

  • для плат, основанных на микроконтроллере ATmega328 (например, Arduino UNO и Nano), количество памяти составляет 1 кБ,
  • для плат на ATmega168 и ATmega8 – 512 байт,
  • на ATmega2560 и ATmega1280 – 4 кБ.

2Библиотека EEPROM

Для работы с EEPROM для Arduino написана специальная библиотека, которая входит в Arduino IDE по умолчанию. Библиотека содержит следующие возможности.

ФункцияНазначение
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[address] позволяет использовать идентификатор «EEPROM» как массив, чтобы записывать данные в память и считывать их из памяти.

Чтобы задействовать библиотеку в скетче, подключаем её директивой #include EEPROM.h.

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

Давайте запишем в память EEPROM два целых числа, а затем прочитаем их из EEPROM и выведем в последовательный порт. С числами от 0 до 255 проблем нет, они занимают как раз 1 байт памяти и с помощью функции EEPROM.write() записываются в нужную ячейку.

Если число больше, чем 255, то с помощью операторов highByte() и lowByte() его нужно делить на байты и записывать каждый байт в свою ячейку. Максимальное число при этом – 65536 (или 216).

#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

Смотрите, монитор последовательного порта в ячейку 0 просто выводит число, меньшее, чем 255. В ячейках 1 и 2 хранится большое число 789. При этом ячейка 1 хранит множитель переполнения 3, а ячейка 2 – недостающее число 21 (т.е. 789 = 3×256 + 21).

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

Чтобы заново «собрать» большое число, разобранное на байты, есть функция word(): int val = word(hi, low), где «hi» и «low» – это значения старшего и младшего байтов числа «val».

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

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

Для записи чисел с плавающей запятой и строк нужно использовать метод 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[20] = «Hello, SolTau.ru!»; // создаём массив символов EEPROM.put(addr, name); // записываем массив в EEPROM Serial.begin(9600); // инициализация послед. порта } void loop() { for (int addr=0; addr

В процедуре setup() сначала запишем число с плавающей запятой «f». Затем сдвинемся на количество ячеек памяти, которое занимает тип «float», и запишем строку символов «char» ёмкостью 20 ячеек.

В процедуре loop() будем считывать все ячейки памяти и пытаться расшифровать их сначала как тип «float», а затем как тип «char», и выводить результат в последовательный порт.

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

Видно, что значение в ячейках с 0 по 3 правильно определилось как число с плавающей точкой, а начиная с 4-ой – как строка.

Появляющиеся значения ovf (переполнение) и nan (не число) говорят о том, что значение в ячейке памяти по этому адресу не может быть корректно преобразовано в число с плавающей точкой. Если вы точно знаете, какого типа данные какие ячейки памяти занимают, то у вас не будет возникать проблем.

5Работа с EEPROM как с массивом

Очень удобная возможность – обращение к ячейкам памяти как к элементам массива EEPROM. В данном скетче в процедуре setup() мы сначала запишем данные в 4 первых байта, а в процедуре loop() ежеминутно будем считывать данные из всех ячеек и выводить их в последовательный порт.

#include void setup() { EEPROM[0] = 11; // записываем 1-ю ячейку EEPROM[1] = 121; // записываем 2-ю ячейку EEPROM[2] = 141; // записываем 3-ю ячейку EEPROM[3] = 236; // записываем 4-ю ячейку Serial.begin(9600); } void loop() { for (int addr=0; addrРабота с ячейками памяти EEPROM Arduino как с элементами массива

Источник: https://soltau.ru/index.php/arduino/item/378-kak-khranit-dannye-v-arduino

Библиотеки Arduino

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

Читайте также:  Делаем собственный аналог ардуино уно своими руками

В Arduino IDE удобный интерфейс для работы с библиотеками ардуино. Прямо из меню программы вы можете скачать, установить и подключить в свой скетч множество библиотек. Для большинства библиотек Arduino можно посмотреть примеры использования. Это поможет понять принцип работы библиотеки. Примеры можно доработать под свои нужды и использовать для реализации своих устройств.

Существуют стандартные библиотеки, которые устанавливаются вместе с Arduino IDE. Некоторые из них даже автоматически подключаются в скетч (например Serial).

Скачать стандартные библиотеки Arduino

Скачать стандартные библиотеки можно на официальном сайте Arduino.

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

Ниже приведены подробные описания и примеры использования стандартных библиотек Arduino.

  • Serial — Библиотека для обмена данными через последовательный порт (UART).
  • Servo — Библиотека для легкого и точного управления сервоприводами.
  • Wire — Библиотека для работы с интерфейсами связи TWI/I2C. Упрощает обмен данными с устройствами, датчиками и сенсорами.
  • WiFi — Подключение к интернету с использованием WiFi шилда.
  • TFT — Нужна для отрисовки текста, изображений и картинок на TFT дисплее Arduino.
  • Stepper — Библиотека для управления шаговыми моторами.
  • LiquidCrystal — Для работы Arduino с жидкокристаллическими экранами (LCD)
  • Ethernet — Для подключения к интернету с использованием Arduino Ethernet shield.
  • SD — Библиотека для записи и считывания информации с SD карт памяти.
  • GSM — Библиотека для подключения Ардуино к GSM сети. Необходима для отправки и получения SMS и звонков, а так же для выхода в интернет с помощью GPRS. Используется с GSM shield.
  • EEPROM — Библиотека для чтения и записи в энергонезависимую память Arduino.

Источник: https://all-arduino.ru/biblioteki-arduino/

Работа с EEPROM

Как вы знаете, микроконтроллер используемый в модуле DINduino имеет 1 (один) килобайт EEPROM (электрически стираемое перепрограммируемое ПЗУ).

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

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

Из них необходимо отметить следующие: Arduino EEPROMex — расширяет стандартные функции работы с EEPROM и облегчает хранение различного рода структур в энергонезависимой памяти. Хранение различных типов данных и переменных. MiniPirate — библиотека-интерпретатор командной строки с возможностью доступа к энергонезависимой памяти.

Когда-нибудь мы обязательно посвятим отдельную статью этой библиотеке.

Итак, прежде всего нам необходимо подключить библиотеку EEPROM к нашему проекту на Arduino

#include

А теперь благодаря кратким примерам кода давайте разберемся с основными функциями нашей новой библиотеки.

WRITE();

Записывает значение в память

int addr = 0; // Текущий адрес в EEPROM int val = 0; // Записываемое в память значение EEPROM.write(addr, val); // Записываем значение в память // увеличиваем значение адреса до конца области EEPROM addr = addr + 1; if (addr == EEPROM.length()) addr = 0;

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

for (int i = 0 ; i < EEPROM.length() ; i++) { EEPROM.write(i, 0); }

READ();

Чтение из памяти

int address = 0; byte value; value = EEPROM.read(address)

Update();

Как вы знаете есть ограничение в 100.000 записей которые можно сделать в одну ячейку памяти. После исчерпания этого лимита возможны сбои и ошибки. Кроме того, память EEPROM является достаточно медленной. Операция записи занимает 3.3 миллисекунды времени. Именно эту проблему и пытается решить функция Update(); которая предотвращает перезапись не изменившихся данных.

EEPROM.update(address, val);

Put();

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

// Определяем структуру struct MyObject { float field1; byte field2; char name[10]; }; // Заполняем структуру данными MyObject customVar = { 3.14f, 65, «Работаем!» }; // Помещаем данные в память EEPROM.put(eeAddress, customVar);

Get();

Аналогичным образом осуществляется чтение структуры из памяти

struct MyObject { float field1; byte field2; char name[10]; }; EEPROM.get(eeAddress, customVar);

Контрольная сумма

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

unsigned long eeprom_crc(void) { const unsigned long crc_table[16] = { 0x00000000, 0x1db71064, 0x3b6e20c8, 0x26d930ac, 0x76dc4190, 0x6b6b51f4, 0x4db26158, 0x5005713c, 0xedb88320, 0xf00f9344, 0xd6d6a3e8, 0xcb61b38c, 0x9b64c2b0, 0x86d3d2d4, 0xa00ae278, 0xbdbdf21c }; unsigned long crc = ~0L; for (int index = 0 ; index < EEPROM.length() ; ++index) { crc = crc_table[(crc ^ EEPROM[index]) & 0x0f] ^ (crc >> 4); crc = crc_table[(crc ^ (EEPROM[index] >> 4)) & 0x0f] ^ (crc >> 4); crc = ~crc; } return crc; }

Прямой доступ

Последней, заслуживающей внимания, функцией библиотеки EEPROM является возможность доступа к памяти как к массиву используя цикл

for (int index = 0 ; index < EEPROM.length() ; index++) { EEPROM[ index ] += 1; // Пример, увеличиваем на единицу значение каждой ячейки памяти }

Цикл с предусловием

int index = 0; while (index < EEPROM.length()) { EEPROM[ index ] += 1; index++; }

Цикл с постусловием

int index = 0; do { EEPROM[ index ] += 1; index++; } while (index < EEPROM.length());

Источник: http://dinduino.ru/ru/specification/eeprom

Подключение внешней SRAM 512 Кбайт к Arduino Mega. Часть 1 — Теория

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

С помощью серия Arduino Mega возможно решение данной проблемы, т.к.имеются варианты исполнения данной платформы с Flash-памятью программ 128 КБайт или 256 КБайт.

А как насчет встроенной памяти SRAM? Максимальный объем в нашем случае (Arduino Mega) не превышает 8 КБайт.

К счастью, серия Mega позволяет работать с внешней SRAM, и что самое главное, программа может получать беспрепятственно доступ к ней, как если бы это была внутренняя SRAM микроконтроллера. В статье мы рассмотрим аппаратное и программное решение задачи расширения памяти на базе микроконтроллера Atmel AVR ATmega1280.

XMEM

В техническом описании на микроконтроллер ATmega1280 содержится вся информация для инженеров, необходимая для расширения памяти. В документе это 9 глава «External Memory Interface» (XMEM). Блок схема ниже поясняет, как микроконтроллер организует связь с внешней памятью.

 Рис. 1. Блок-схема организации работы с внешней памятью с помощью XMEM.  Блок в центре — высокоскоростной 8-битный регистр-защелка.

Наиболее интересная часть в этой схеме – блок в центре, который представляет собой высокоскоростную 8-разрядную защелку.

Мультиплексирование и защелка

Адресное пространство Arduino Mega позволяет подключать внешнюю память объемом до 64 КБайт при 8-битной организации. Обычно для этого требуется немалое количество линий ввода/вывода: 16 для адресной шины, 8 для шины данных и как минимум еще 2 для управления.

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

 Рис. 2. Временные диаграммы работы интерфейса внешней памяти.

Период времени, обозначенный красной линией, показывает промежуток между установкой действительного адреса (достоверные данные на линиях A0 – A15) и началом передачи данных (действительные данные на линиях D0 – D7).

Логика микроконтроллера начинает операции с внешней памятью, подтверждая действительный адрес на линиях A0 – A15. Мультиплексированные линии проходят через 8-разрядный регистр-защелку, который работает в «прозрачном» режиме (transparent mode).

Затем регистр переключается в режим хранения (Hold mode), при котором игнорируются изменения на входе и продолжается хранение последних принятых данных на выходе.

Микроконтроллер затем устанавливает действительные данные на мультиплексированных линиях (это уже будут данные D0 – D7) и, в результате, мы имеем успешно установленные все линии для работы с внешней памятью и сохранили 8 линий ввода/вывода, которые могут понадобиться при работе основного приложения.

Стоит заметить, что регистр-защелка должен успевать работать на тактовой частоте 16 МГц, поэтому серия 74HC не подойдет для нашей цели. В техническом описании на микроконтроллер рекомендуется серия 74AHC.

Адресация при объеме SRAM более 64 КБайт

Теперь, основная задача – это работа с внешней памятью объемом 512 КБайт с адресным пространством всего на 64 КБайт. Решение – разделить 512 КБайт на 8 банков памяти по 64 КБайт и сделать управление «видимостью» одного банка в каждый момент времени с использованием 3 выводов микроконтроллера.

Память объемом 512 КБайт при обращении к ней требует 19-битного адреса (адресные линии A0 – A18). Линии A0 – A15 мы подключим по интерфейсу xmem (интерфейс внешней памяти микроконтроллера) и управление 3 оставшимися (A16 – A18) осуществим с помощью цифровых линий ввода/вывода микроконтроллера.

 Рис. 3. Разделение внешней SRAM на 8 банков памяти объемом 64 КБайт.

Следующее ограничение, которое накладывает карта памяти микроконтроллеров ATmega – нижние 8 КБайт SRAM (адресное пространство для такого объема) всегда занимаются внутренней памятью микроконтроллера.

Это означает, что адресация внешней памяти осуществляется в диапазоне 0х2200 – 0хFFFF, т.е. мы теряем 69632 байта из общего объема 524288 Байт внешней SRAM.

В спецификации на микроконтроллер объясняется метод адресации этих потерянных 8 КБайт, однако автор посчитал, что в данной задаче это не актуально.

Во второй части статьи представлены принципиальная схема подключения внешней ОЗУ к микроконтроллеру, список компонентов и рисунки печатной платы.

Источник: https://www.rlocman.ru/shem/schematics.html?di=109611

Подключаем память 24LC16 к микроконтроллеру AVR :AVR devices

Иногда при разработке устройства возникает потребность сохранять какие-либо данные в энергонезависимую память.  В таких случаях обычно используют внутреннюю EEPROM микроконтроллера. Если её недостаточно, то как правило применяются внешние микросхемы EEPROM из серии 24lxx. Микросхемы этой серии очень популярны.

Читайте также:  Моргаем встроенным светодиодом ардуино - arduino+

Чаще всего их можно встретить в старых мобильных телефонах, некоторых материнских платах, картриджах от принтеров да еще много где. Цена данных микросхем тоже очень привлекательная. Например 24LC16 у нас стоит 11 рублей.
Данная микросхема выпускается в различных корпусах, самые популярные из которых это DIP и SOIC.

Микросхема имеет следующую распиновку:

Как видите выводов совсем немного. Итак попробуем разобраться для что к чему.
A0, A1, A2 — в данной микросхеме не используются. Их можно подсоединить к земле или к плюсу питания.

В некоторых других микросхемах серии  24lxx, этими выводами можно задавать адрес микросхемы, для того чтобы можно было подсоединить на одну шину i2c аж сразу 8 микрух памяти.
Vss —  земля.

SDA — линия данных
SCL — линия  тактовых импульсов
WP — Защита от записи. Когда на данном выводе логический  0, то запись в память разрешена. Если подать логическую единицу, то возможно только чтение из памяти. 
Vcc — питание микросхемы.

   Согласно даташиту питается она напряжением от 2.5 вольта  до 5.5 вольта.<\p>

Подключение к контроллеру.
Подключить память к МК очень просто. Из обвязки потребуются только пара резисторов сопротивлением около 4.7 кОм.

Программное обеспечение

Для работы с памятью была разработана библиотека реализующая следующие функции:<\p>

i2c_init — настраивает скорость тактовых импульсов идущих по линии SCL.

Микросхема 24LC16 поддерживает частоту до 400 кГц.  Рассчитать частоту можно так:

CPU Clock frequency — частота на которой работает микроконтроллер<\p>

TWBR — число записанное в одноименный регистр.<\p>

TWPS —  предделитель. Значения предделителя задаются битами TWPS1 и TWPS0 в регистре TWSR

Для  контроллера Atmega 32 справедлива такая таблица:

i2c_start — отсылает стартовую посылку

i2c_stop — отсылает стоповую посылку

i2c_send — отсылает байт

i2c_recive — принимает байт

i2c_recive_last — принимает последний байт. Отличие от предыдущей функции состоит в том, что когда байт принят, микроконтроллер не отсылает бит подтверждения. Если при приёме последнего байта использовать i2c_recive то линия SDA останется прижатой к земле.

Запись данных в микросхему памяти

Записывать данные можно как в произвольном порядке так и постранично. Поскольку на шине i2c могут быть сразу несколько устройств, то для того чтобы обратится к какому либо устройству нужно знать его семибитный адрес. Адрес микросхемы 24LC16  в двоичном виде выглядит так:

Биты A,B,C служат для выбора блока памяти. Блоков памяти в микросхеме 8 штук по 256 байт каждый. Соответственно биты  ABC принимают значения от 000 до 111.

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

  1. Инициализировать интерфейс i2c
  2. Отослать стартовую посылку
  3. Отослать адрес микросхемы+адрес блока памяти
  4. Отослать адрес ячейки памяти в которую будет производится запись
  5. Отослать байт данных
  6. Отослать стоповую посылку

Пример: Нужно записать байт 0xFA по адресу 0x101.

rcall i2c_init //Инициализируем интерфейс i2c
rcall i2c_start // Отправляем стартовую посылку
ldi temp,0b10100010//Адрес микросхемы где:
// 1010 — адрес микросхемы
//001 — адрес блока памяти (Ячейка 0x101 принадлежит блоку 1)
// — бит чтения/записи. 0 — запись , 1 — чтение rcall i2c_send

ldi temp,1  //Адрес ячейки памяти. (блок 1, ячейка 1)

rcall i2c_send

ldi temp,0xFA //Загружаем в регистр байт который нужно записать

rcall i2c_send //Записываем байт
rcall i2c_stop  //Отправляем стоповую посылку

https://www.youtube.com/watch?v=O6t-n3_fnQ0

Записывать данные в память можно не только побайтно но и постранично. Размер страницы — 16 байт.

 Постараничная запись подразумевает следующее: Отправляем адрес нулевого байта нужной страницы и после этого 16 раз отправляем нужные данные. Счётчик адреса будет увеличивать на единицу автоматически.

Если отправить данные в 17-й раз, то будет перезаписан нулевой байт, если отправить байт 18-й раз , то он затрет байт номер 1 итд.

Пример:  Требуется записать первую страницу блока 0.

rcall i2c_init //Инициализируем интерфейс i2c
rcall i2c_start // Отправляем стартовую посылку
ldi temp,0b10100000//Адрес микросхемы где:
// 1010 — адрес микросхемы
//000 — адрес блока памяти (нас интересует нулевой блок)
// — бит чтения/записи. 0 — запись , 1 — чтение rcall i2c_send

ldi temp,16  //Адрес первой страницы

rcall i2c_send

ldi temp,0x01  //Загружаем в регистр байт номер 0

rcall i2c_send //Записываем байт
ldi temp,0x02  //Загружаем в регистр байт номер 1
rcall i2c_send //Записываем байт
/// тут пишем остальные байты…..
ldi temp,0x0E  //Загружаем в регистр байт номер 14
rcall i2c_send //Записываем байт
ldi temp,0x0F  //Загружаем в регистр байт номер 15
rcall i2c_send //Записываем байт
rcall i2c_stop  //Отправляем стоповую посылку

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

  1. Инициализировать интерфейс i2c (если он не инициализировался ранее)
  2. Отправить стартовую посылку
  3. Отправить адрес микросхемы и адрес блока памяти откуда будем читать
  4. Отправить адрес ячейки памяти
  5. Отправить стартовую посылку повторно
  6. Отправить адрес микросхемы и адрес блока памяти с битом «чтение»
  7. Получить байт
  8. Отправить стоповую посылку

Пример: Нужно прочитать байт находящийся по адресу 0x341

rcall i2c_init //Инициализируем интерфейс i2c
rcall i2c_start // Отправляем стартовую посылку
ldi temp,0b10100110 //Адрес микросхемы + адрес 3-го блока памяти.
//Бит чтение/запись по прежнему 0 ! rcall i2c_send

ldi temp,0x41 //Адрес ячейки памяти

rcall i2c_send

rcall i2c_start //Повторная отправка стартовой посылки

ldi temp,0b10100111 //Адрес микросхемы+адрес блока памяти+бит чтения/записи стал 1
rcall i2c_send     //теперь можно читать данные
rcall i2c_recive_last  //Читаем байт. Первый и последний.
rcall i2c_stop   //Отправляем стоповую посылку

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

Библиотека для работы с i2c разрабатывалась и была испытана на микроконтроллере Atmega32. Я думаю что она будет работать на многих других контроллерах без каких либо изменений. Естественно в контроллере должна быть аппаратная поддержка i2c или как его еще называют TWI.

Конечно реализовать i2c можно и программно, но я не стал заморачиваться да и не было нужды. Демонстрационный пример  представляет собой программу которая записывает по первым 16 адресам байты от 0 до 15, а после записи выводит их в порт A.

Наблюдать как это работает можно не только в живую но и в Proteus’е.

Ну и напоследок прикладываю осциллограмму:

Вот так выглядит шина i2c глазами моего осциллографа 🙂
Все вопросы и предложения жду в комментариях.

P.S. для понимания работы шины рекомендую ознакомится со статьёй Di Halt’a

Скачать исходник  + демонстрационный пример

Источник: http://avrdevices.ru/podkluchaem_pamyat_24lc16_k_avr/

Энергонезависимая память AT24C02 и Arduino — Любимые видео

1 лет назад

Если необходимо сохранить значение переменных во время отключения питания, то наилучший выход — использовать EEPROM. Это енергонезависимая память, которая поможет сохранить значение переменных и настройки устройства. Подключение по I2C делает использование EEPROM AT24C128 очень простым. Библиотека и скетч: https://drive.google.

com/open?id=0Bw5SzGwQf6yzaE5Nb3lwblB0TU0 Друзья, поддержите канал! R340967932571 Z422687519909 U139735106020 4149625807630874 Приват Банк (Украина) Полезные ссылки: EEPROM 24C128: http://ali.pub/1w3yh5 Дисплей 1602 + расширитель портов: http://ali.pub/1vb6ja Дисплей 1602: http://ali.pub/1uo1ww Модуль Micro SD: http://ali.

pub/1tkx36 TFT дисплеи: http://ali.pub/1ny2rc Ардуино Мега 2560: http://ali.pub/1ny34r Самые дешевые Ардуино Про Мини для поделок: http://ali.pub/1ny2z4 Макетка: http://ali.pub/1ny3ae Перемычки: http://ali.pub/1ny3la Качественные перемычки: http://ali.pub/1ny3j5 Самый удобный Кешбек: LetyShops: https://goo.

gl/Ev5XgI Самый выгодный Кешбек на алиекспресс: Ecomerce: https://goo.gl/3dDc2w

2 месяцев назад

В этом видео я покажу подборку из трех разных схем: детектор электрического поля, генератор колебаний на реле, кодовый замок на одном транзисторе. Представленные конструкции простые, но достаточно интересные и отлично подойдут для начинающих. Схемы для начинающих: http://cxem.net/beginner/beginner.php

4 лет назад

электронный замок на arduino с самодельными ключами на еепром 24C02 // код http://arrduinolab.blogspot.com/2015/02/eeprom-24c02.html // библиотека для 24C01-02 https://github.

com/jlesech/24C01-02 // библиотека для 24C04-16 https://github.com/jlesech/24C04-08-16 // библиотека для 24C32-64 https://github.com/jlesech/24C32-64 поддержать канал материально. http://www.

donationalerts.ru/r/arduinolab

1 лет назад

Каждый в определенный момент сталкивается с проблемой низкой скорости выполнения программы на Ардуино. Но на самом ли деле Ардуино такая медленная как кажется? Попробуем разобраться в чем проблема: в слабом железе или в неоптимизированном коде? Использование Ардуино IDE накладывает определенные ограничения в скорости работы.

Это цена, которую мы платим за простоту написания команд и языка в целом. А что если попробовать написать команды, которые работают на прямую с микроконтроллером? Каков будет результат? Об этом мы увидим в видео. Библиотека CyberLib: https://istarik.ru/blog/arduino/1.html Очень полезные статьи: https://geektimes.ru/post/255744/ http://robotosha.

ru/arduino/digitalwrite-optimizing-arduino.html http://microsin.net/programming/avr/accessing-avr-ports-with-winavr-gcc.html http://4a4ik.blogspot.com/2014/05/avr.html http://easyelectronics.ru/avr-uchebnyj-kurs-ustrojstvo-i-rabota-portov-vvoda-vyvoda.html http://mkprog.ru/avr/avr-dlya-nachinayushhih-urok-3-porty-vvoda-vyvoda.

html Друзья, поддержите канал! R340967932571 Z422687519909 U139735106020 4149625807630874 Приват Банк (Украина) Полезные ссылки: Модуль Micro SD: http://ali.pub/1tkx36 TFT дисплеи: http://ali.pub/1ny2rc Ардуино Мега 2560: http://ali.pub/1ny34r Самые дешевые Ардуино Про Мини для поделок: http://ali.pub/1ny2z4 Макетка: http://ali.pub/1ny3ae Перемычки: http://ali.

pub/1ny3la Качественные перемычки: http://ali.pub/1ny3j5 Самый удобный Кешбек: LetyShops: https://goo.

gl/Ev5XgI Самый выгодный Кешбек на алиекспресс: Ecomerce: https://goo.gl/3dDc2w

6 лет назад

Источник: https://1-tube.ru/watch/ArM9e5pOPEs

Ссылка на основную публикацию