Що таке eeprom контролера. Внутрішня незалежна пам'ять EEPROM. Приклади проектів та скетчів

Головна / Захист

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()і записувати кожен байт у свій осередок. Максимальне число при цьому – 65 536 (або 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); .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); (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. Для певних проектів варто використати лише цей вид пам'яті. Він має свої плюси, так і свої недоліки. Для освоєння методів запису та читання краще почати з простих завдань.

  • Tutorial

Резюме: Якщо ви періодично оновлюєте деяке значення в EEPROM кожні кілька хвилин (або кілька секунд), ви можете зіткнутися з проблемою зносу осередків EEPROM. Щоб уникнути цього, потрібно знижувати частоту записів у комірку. Для деяких типів EEPROM навіть частота запису частіше, ніж один раз на годину, може бути проблемою.

Коли ви записуєте дані, час летить швидко

EEPROM повсюдно використовується для збереження параметрів налаштування та журналу роботи у вбудовуваних системах. Наприклад, ви можете хотіти функцію «чорної скриньки», для запису останніх даних на момент аварії або втрати харчування. Я бачив специфікації з вимогою записувати такі дані кожні кілька секунд.

Але проблема полягає в тому, що EEPROM має обмежений ресурс кількості записів. Після 100,000 або мільйона записів (залежить від конкретного чіпа), деякі ваші системи почнуть відчувати проблеми з відмовою EEPROM. (Погляньте в даташит, щоб дізнатися конкретну цифру. Якщо ви хочете випустити велику кількість пристроїв, "найгірший випадок", ймовірно, важливіший за "типовий"). Мільйон записів здається великою цифрою, але насправді він закінчиться дуже швидко. Давайте подивимося на прикладі, припустивши, що нам потрібно зберігати виміряну напругу в один осередок кожні 15 секунд.

1,000,000 записів при одному записі за 15 секунд дають записи за хвилину:
1,000,000/(4 * 60 хвилин/годину * 24 години/день) = 173.6 днів.
Іншими словами, ваша EEPROM вичерпає резерв у мільйон записів менш ніж за 6 місяців.

Нижче наведено графік, що показує час до зношування (у роках), заснований на періоді оновлення конкретного осередку EEPROM. Обмежувальна лінія для продукту із тривалістю життя 10 років становить одне оновлення кожні 5 хвилин 15 секунд для мікросхеми з ресурсом 1 мільйон записів. Для EEPROM з ресурсом 100К можна оновлювати конкретну комірку не частіше ніж один раз на 52 хвилини. Це означає, що не варто і сподіватися оновлювати комірку кожні кілька секунд, якщо ви хочете, щоб ваш продукт працював роки, а не місяці. Вищесказане масштабується лінійно, щоправда, у цьому приладі є ще й вторинні фактори, такі як температура та режим доступу.

Зменшити частоту

Самий безболісний спосіб вирішити проблему-це просто записувати дані рідше. У деяких випадках вимоги до системи дозволяють. Або можна записувати лише за будь-яких великих змін. Однак, із записом, прив'язаним до подій, пам'ятайте про можливий сценарій, при якому значення буде постійно коливатися, і викличе потік подій, які призведуть до зносу EEPROM.
(Буде непогано, якщо ви зможете визначити, скільки разів проводився запис в EEPROM. Але це вимагатиме лічильника, який буде зберігатися в EEPROM… при цьому проблема перетворюється на проблему зносу лічильника.)

Переривання щодо зниження рівня харчування

У деяких процесорах є переривання за низьким рівнем живлення, яке можна використовувати для запису одного останнього значення EEPROM, в той час як система вимикається по втраті живлення. У загальному випадку, ви зберігаєте значення в ОЗУ, і зберігаєте його в EEPROM тільки при вимкненні живлення. Або, можливо, ви записуєте EEPROM час від часу, і записуєте іншу копію в EEPROM як частину процедури вимкнення, щоб переконатися, що останні дані запишуться.
Важливо переконатися, що є великий конденсатор живлення, який буде підтримувати напругу, достатню для програмування EEPROM досить тривалий час. Це може спрацювати, якщо потрібно записати одне або два значення, але не великий блок даних. Обережно, тут є великий простір для помилки!

Кільцевий буфер

Класичне вирішення проблеми зносу-використовувати кільцевий буфер FIFO, що містить N останніх записів значення. Також потрібно зберігати покажчик на кінець буфера в EEPROM. Це зменшує знос EEPROM на величину, пропорційну кількості копій у цьому буфері. Наприклад, якщо буфер проходить через 10 різних адрес для збереження одного значення, кожен конкретний осередок модифікується в 10 разів рідше, і ресурс запису зростає в 10 разів. Вам також знадобиться окремий лічильник або позначка часу для кожної з 10 копій, щоб можна було визначити, яка їх остання на момент вимкнення. Іншими словами, знадобиться два буфери, один для значення, і один для лічильника. (Якщо зберігати лічильник по одному й тому ж адресою, це призведе до його зносу, тому що він повинен збільшуватися при кожному циклі запису.) Нестача цього методу в тому, що потрібно в 10 разів більше місця, щоб отримати в 10 разів більшу тривалість життя. Можна виявити кмітливість, і запакувати лічильник разом з даними. Якщо ви записуєте велику кількість даних, додавання кількох байт для лічильника - не така вже й велика проблема. Але в будь-якому випадку знадобиться багато EEPROM.
Atmel приготував апноут, що містить усі криваві подробиці:
AVR-101: High Endurance EEPROM Storage: www.atmel.com/images/doc2526.pdf

Особливий випадок для лічильника числа записів

Іноді треба зберегти лічильник, а чи не самі значення. Наприклад, ви можете хотіти знати кількість включень приладу або час роботи вашого пристрою. Найгірше в лічильниках, це те, що у них постійно змінюється молодший біт, зношуючи молодші осередки EEPROM швидше. Але і тут можна застосувати деякі трюки. В аппноуті від Microchip є кілька розумних ідей, таких як використання коду Грея, щоб тільки один біт з багатобайтового лічильника змінювався при зміні значення лічильника. Також вони рекомендують використовувати коригувальні коди для компенсації зношування. (Я не знаю, наскільки ефективно буде застосування таких кодів, тому що це залежатиме від того, наскільки незалежними будуть помилки в бітах у байтах лічильника, використовуйте на свій страх і ризик, прим. авт.). Дивись апноут: ww1.microchip.com/downloads/en/AppNotes/01449A.pdf

Примітка: для тих, хто хотів би дізнатися більше, Microchip підготував документ, що містить детальну інформацію про пристрій осередків EEPROM та їх знос з діаграмами:
ftp.microchip.com/tools/memory/total50/tutorial.html

Дайте мені знати, якщо у вас є якісь цікаві ідеї щодо боротьби зі зносом EEPROM.

Джерело: Phil Koopman, "Better Embedded System SW"
betterembsw.blogspot.ru/2015/07/avoiding-eeprom-wearout.html

Примітка перекладача: в останні роки з'явилися мікросхеми EEPROM зі сторінковою організацією стирання (подібної до мікросхем FLASH), де логічно можна адресувати осередки (читати, записувати і стирати) побайтно, але при цьому мікросхема невидимо для користувача стирає всю сторінку повністю і перезаписує новими даними. Тобто. стерши комірки за адресою 0, ми фактично стерли і перезаписали комірки з адресами 0 ... 255 (при розмірі сторінки 256 байт), тому трюк з буфером у цьому випадку не допоможе. При вичерпанні ресурс записів у такої мікросхеми виходить з ладу не один осередок, а вся сторінка цілком. У датаситах для таких мікросхем ресурс запису вказано для сторінки, а не для конкретного осередку. Дивись, наприклад, датує на 25LC1024 від Microchip.

Теги: Додати теги

Наш контролер печі майже готовий - проте поки що він залишається контролером-«золотою рибкою», який пам'ятає всі налаштування лише п'ять хвилин до першого вимикання харчування. Щоб запам'ятати наші налаштування, значення заданої температури та точки калібрування навіть після вимкнення живлення, потрібно використовувати енергонезалежну пам'ять – EEPROM.
Дуже добре про роботу з EEPROM написано у наших товаришів та .

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

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

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

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

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

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

Eeprom uint16_t EEP_MinTemperature;

Ще кілька загальних слів: і хоча вказівники на eeprom-змінні у нас не передбачаються, потрібно пам'ятати, що eeprom – окремий адресний простір, і щоб створити вказівник на eeprom (і це дозволяє нам зробити компілятор), необхідно вказувати, що це вказівник на адресу в eeprom:

Uint16_t __eeprom *EEP_MinTemperatureAdr;

Повертаємося до контролера печі та EEPROM. У нашому випадку, для EEPROM жодної віртуальної машини, звичайно, не передбачається; більше того, варто подумати, чи потрібна окрема бібліотека для роботи з енергонезалежною пам'яттю – надто вже «розкидані» за програмою запису важливих налаштувань; якщо намагатись зробити окрему бібліотеку, то доведеться робити перехресні посилання: у бібліотеці для EEPROM підключати бібліотеки АЦП, нагрівального елемента, глобальних налаштувань; а в цих бібліотеках периферії підключати бібліотеку EEPROM – такий підхід не дуже добрий.
Інший варіант – дописати до кожної бібліотеки, де потрібно зберігати налаштування, eeprom-змінну, та зберігати відповідні налаштування прямо у віртуальних машинах. Ми реалізуємо цей варіант.
Спочатку перерахуємо, які змінні потрібно зберігати в EEPROM:

  1. точки калібрування
  2. значення максимальної-мінімальної температури, що задається, і кроку налаштування температури
  3. значення заданої температури
  4. коефіцієнти ПІД-регулятора

Значення кухонного таймера не зберігаємо - вважатимемо, що користувач після вимкнення живлення повинен сам налаштовувати таймер пічки.
Всі ці налаштування задаються користувачем за допомогою поворотів енкодера і подальшого короткого натискання на кнопку користувача. При цьому пам'ятаємо, що кількість циклів читання-запису EEPROM все-таки обмежена, тому зайвий раз одну й ту саму інформацію (наприклад, якщо користувач вибрав те саме значення якоїсь настройки, що й було) не перезаписувати. Тому перед кожною зміною __eeprom-змінною перевіряємо, а чи потрібно її переписувати:

//якщо значення змінилося - перезаписуємо в енергонезалежній пам'яті if (ADCTemperature.atMinTemperatureValue != (uint16_t)VMEncoderCounter.ecntValue) ( ​​ADCTemperature.atMinTemperatureValue = (uint16_t)VMEncoderMuture

З читанням налаштувань з EEPROM теж все просто - при ініціалізації "поточних" налаштувань ми просто зчитуємо значення з енергонезалежної пам'яті:

ADCTemperature.atMinTemperatureValue = EEP_MinTemperature;

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

Eeprom uint16_t EEP_MinTemperature = 20; … // масив для зберігання точок калібрування в незалежній пам'яті __eeprom TCalibrationData EEP_CalibrationData = ((20, 1300), (300, 4092));

У цьому випадку компілятор ініціалізує змінні __eeprom до початку роботи з основною функцією. Щоб отримати файл з незалежною пам'яттю (.eep), потрібно залізти в наступні налаштування:
Project->Options..->Linker->Extra Options
Якщо галочка "Use command line options" не варто, поставте її та додайте рядок
-Ointel-standard,(XDATA)=.eep
Компілюємо спочатку проект з ініціалізованими змінними, зберігаємо eep-файл окремо; потім прибираємо ініціалізацію під час створення змінних.

Ось і все – наша пічка готова!

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

Як 3D-принтер використовує EEPROM?
Розглянемо на прикладі Marlin"а. У Marlin Firmware "з коробки" EEPROM не використовується. Параметри конфігуратора (Configuration.h), які включають можливість його використання, за замовчуванням, закоментовані.

#define EEPROM_SETTINGS
#define EEPROM_CHITCHAT

Якщо увімкнено використання EEPROM, то принтер може зберігати та використовувати наступні налаштування (підглянуто у буржуїв):

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

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

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

Цією командою проводиться читання даних EEPROM"а файл "printer_eeprom.eep". У разі успіху, на екрані ви побачите приблизно наступне.

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

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

У разі успіху на екрані ви побачите приблизно наступне повідомлення.

Як і навіщо прати EEPROM?
Для початку, "навіщо це робити?". Прати EEPROM потрібно в тому випадку, якщо попередня прошивка теж його використала, і в пам'яті могло залишитися сміття. Десь я вже натикався на людей з проблемами, що після переходу з однієї прошивки на іншу (з Marlin на Repitier ЕМНІП), у них принтер починав поводитись, скажімо так, "творчо". Це пов'язано з тим, що різні прошивки зберігають дані під різними адресами. І при спробі читати дані з невірної адреси починається свистопляска.
Затерти EEPROM можна тільки програмно з прошивки, але для цього доведеться - на якийсь час залити в контролер спеціальний скетч. Докладно про це можна прочитати в офіційній документації Arduino .
Якщо ж стирається EEPROM над Arduino платі, а якомусь абстрактному контролері, то код скетча треба буде змінити з урахуванням розміру EEPROM у конкретному контролері на платі. Для цього необхідно буде змінити умову закінчення в циклі "For". Наприклад, для ATmega328, яка має 1kb пам'яті EEPROM, цикл буде виглядати так:
Висновок.
Я досить довго розпинався, а все для чого? Для того, щоб підвести до висновку про те, що при бекапі прошивки, EEPROM теж можна зберегти, але якщо вам потрібні збережені в ньому налаштування. Якщо ж ви готові пожертвувати ними, то вбийте на це. Також, якщо ви змінюєте одну прошивку на іншу, або переходите з версії не версію, не полінуйтеся очистити EEPROM перед заливкою нової прошивки. Ну і заразом ми дізналися багато нового.

Електрично стираються програмовані мікросхеми постійної пам'яті (EEPROM) є металевими напівпровідниковими оксидними комп'ютерними мікросхемами, які використовуються на друкованій платі. Цей тип чіпа можна стерти і перепрограмувати за допомогою сильного електронного сигналу. Оскільки це можна зробити, не видаляючи чіп з пристрою, якого він підключений, чіпи EEPROM використовуються у багатьох галузях.
Мікросхема EEPROM містить енергонезалежну пам'ять, тому її дані не втрачаються при порушенні живлення чипа. Мікросхема такого типу може бути запрограмована вибірково, що означає, що частина пам'яті може бути змінена за допомогою нового перезапису, не зачіпаючи решту пам'яті. Інформація, що зберігається всередині мікросхеми EEPROM, є постійною, поки вона буде стерта або перепрограмована, що робить її цінним компонентом у комп'ютерах та інших електронних пристроях.

Мікросхеми EEPROM створені на основі транзисторів із плаваючим затвором. Мікросхема EEPROM запрограмована шляхом примусової програмованої інформації як електронів через оксид затвора. Потім плаваючий затвор забезпечує зберігання цих електронів. Осередок пам'яті вважається запрограмованою, коли вона заряджається електронами, і це є нулем. Якщо осередок пам'яті не заряджений, він не запрограмований, і він представлений одиницею.

Для широкого спектру пристроїв потрібна пам'ять, тому чіпи EEPROM мають безліч застосувань в галузі побутової електроніки. Вони використовуються в ігрових системах, телевізорах та комп'ютерних моніторах. Слухові апарати, цифрові камери, технологія Bluetooth та ігрові системи також використовують чіпи EEPROM. Вони використовуються в телекомунікаційній, медичній та обробній промисловості. Персональні та бізнес-комп'ютери містять ЕСППЗП.

Чіп EEPROM також має широкий спектр застосувань в автомобільній галузі. Він використовується в антиблокувальних системах, подушках безпеки, електронних засобах контролю стійкості, трансмісіях та блоках керування двигуном. Чіпи EEPROM також використовуються в кондиціонерах, дисплеях панелі приладів, модулях управління корпусом і системах введення без ключа. Ці чіпи допомагають контролювати витрати пального, а також використовуються в різних діагностичних системах.

Існує обмеження кількості повторень, яке може бути перезаписано чіпом EEPROM. Шар усередині чіпа поступово ушкоджується численними переписуваннями. Це не велика проблема, тому що деякі чіпи EEPROM можуть бути змінені до мільйона разів. Подальші успіхи в галузі технологій, швидше за все, вплинуть на те, на що можуть розраховувати мікросхеми пам'яті в майбутньому.

© 2022 androidas.ru - Все про Android