Как eeprom изменить

Блог пользователя super-fake на DRIVE2. Всем привет, в это раз хочу осветить саму распространенную хитрость перекупов а это сматывание пробега электронных одометров. В периуд высоких технологий все сложные электроприборы у которых есть процессоры имеют внешнюу энергонезависимую память. За частую это небольшие микросхемы память EEPROM (анг…

Всем привет, в это раз хочу осветить саму распространенную хитрость перекупов а это сматывание пробега электронных одометров. В периуд высоких технологий все сложные электроприборы у которых есть процессоры имеют внешнюу энергонезависимую память. За частую это небольшие микросхемы память EEPROM (англ. Electrically Erasable Programmable Read-Only Memory) — электрически стираемое перепрограммируемое ПЗУ (ЭСППЗУ). EEPROM разного назначения имеет разные объемы памяти, и различные интерфейсы передачи данных. Но нас интересует память с нашим пробегом, что бы узнать что за память хранит наш пробег разбираем приборку, ищем процессор (микросхема у которой очень много ножек) рядом микруха памяти имеет 8 ног . В моем случае это 93С56 объем памяти 256 байт.

EEPROM Находится рядом с процессором

Аккуратно ее выпеваем.
Теперь нужно считать ее прошивку, для этого нужен программатор.

Программатор EEPROM из дружественного Китая

Если по чистой случайности у вас его нет, то собираем с нуля.
Для сбора простейшего программатора вам потребуется COM порт (RS-232) если на задней панели компьютера его нет то вам потребуется переходник USB-COM (RS-232)

COM порт персонального компьютера

Переходник USB-COM

Дальше нужно собрать простейшую цепь для подключения память к разъему com порта.

Схема подключения памяти к com

Проверяйте по 10 раз как вы все подключили перед подключением к ПК!
У меня получилась вот такая ЗАЛИПУХА :)

Только ХАРДКОР!

Далее дело за программной частью
Незабываем устанавливливать драйвера на переходник USB-COM
Качаем с просторв интернет программулину PonyProg
Ну я по старинке пользовался IC-PROG (только для ОС XP)
Не забывайте о разрядности вашей ОС ищите программы для вашей ОС.

Если программы скачены и даже работают, настройте адаптер у PonyProg вкладка setup ->interface Setup
Выберите ваш COM порт назначенный системой вашему USB-com переходнику.

вкладка

interface Setup»>
Далее, выбираем в правом верхнем углу тип памяти и название,

Настройка

Ну и пытайтесь считать прошивку.
Должно считать примерно так

Считанная прошивка в IC-prog

Далее сохраняем прошивку в качестве гарантии, что бы можно было вернуть прошивку в первоначальном виде.
Теперь нам понадобиться программа калькулятор пробега, программа под названием carculator V-1.07

Программа carculator v1.07

Находим в программе свое авто, (моего авто не было, по анологии понял куда вписывать новые данные).
Вбиваем в программу нужный пробег, и нажимаем Calculate он выдает преобразованный пробег в шестнадцатеричном виде, далее ставим галочку swap и опять нажимаем Calculate, мы получили набор символов который нужно вставить в определенную область памяти. Программа carculator v1.07 при выборе авто показывает в какие строки и ячейки нужно вставить новые данные с примером.

пример выделен желтым

Далее меняем в программе редактора памяти значения на новые, и программируем контроллер.
Ворачиваем его в приборку, для удобства в приборку припаял сокет 8 ног, что бы постоянно не выпаивать микруху а просто вставлять.
Метаморфозы моего пробега ))

Началось все с этого

УПС накрутил малость

УЖЕ ЛУЧШЕ

Всем добра, надеюсь кому нибудь пригодиться.

Форум РадиоКот • Просмотр темы — Как вручную изменить содержание EEPROM?

Сообщения без ответов | Активные темы

ПРЯМО СЕЙЧАС:

Автор Сообщение

Не в сети

Заголовок сообщения: Как вручную изменить содержание EEPROM?

СообщениеДобавлено: Вс ноя 24, 2013 16:49:18 

Потрогал лапой паяльник

Зарегистрирован: Сб май 25, 2013 11:52:14
Сообщений: 364

Рейтинг сообщения: 0

Суть вот в чем. Мне необходимо заранее прошить EEPROM Attiny13. То есть, чтобы при включении устройства памяти уже было необходимое значение (либо 255, либо 180 по адресу 1).
Работаю в AVR Studio на ассемблере. Я так понимаю, что мне необходимо создать hex-файл EEPROM и зашить его в МК.
Как его создать и как внести туда то, что мне нужно?
Спасибо

Вернуться наверх
 

ПрофильПрофиль

 

Реклама

akl

Не в сети

Заголовок сообщения: Re: Как вручную изменить содержание EEPROM?

СообщениеДобавлено: Вс ноя 24, 2013 16:57:01 

Карма: 63

Рейтинг сообщений: 943

Зарегистрирован: Пт мар 07, 2008 06:54:43
Сообщений: 4143
Откуда: Ижевск

Рейтинг сообщения: 0

Директива .ESEG поможет.

Код:

.ESEG
.org $00
.DB 255,180

После ассемблирования появится файл с расширением .eep

Добавил. В студии для отображения в окне памяти выбираете DEBAG->UP/DOWNLOAD MEMORY->EEPROM->путь->загрузить из файла.

Вернуться наверх
Реклама

Кто сейчас на форуме

Сейчас этот форум просматривают: нет зарегистрированных пользователей и гости: 10

Вы не можете начинать темы
Вы не можете отвечать на сообщения
Вы не можете редактировать свои сообщения
Вы не можете удалять свои сообщения
Вы не можете добавлять вложения

Вот и добрались мы до третьего типа памяти, доступного на Arduino: EEPROM (англ. Electrically Erasable Programmable Read-Only Memory – электрически стираемое перепрограммируемое постоянное запоминающее устройство (ЭСППЗУ)), она же энергонезависимая память. Вспомним остальные типы памяти, Flash и SRAM, и их возможности по хранению данных:

Тип Чтение из программы Запись из программы Очистка при перезагрузке
Flash Да, PROGMEM Можно, но сложно Нет
SRAM Да Да Да
EEPROM Да Да Нет

Простыми словами: EEPROM – память, к которой мы имеем полный доступ из выполняющейся программы, т.е. можем во время выполнения читать и писать туда данные, и эти данные не сбрасываются при перезагрузке МК. Круто? Круто. Зачем?

  • Хранение настроек, изменяющихся “из меню” устройства, без перепрошивки;
  • Калибровка, сохранение калибровочных данных;
  • Использование как дополнительной SRAM памяти в случае её нехватки;
  • “Чёрный ящик” – постоянная запись показаний с датчиков для дальнейшей расшифровки сбоев;
  • Запись состояния рабочего процесса для восстановления работы после внезапной перезагрузки.

Единственный важный момент: EEPROM имеет ресурс по количеству перезаписи ячеек. Производитель гарантирует 100 000 циклов записи каждой ячейки (AVR Arduino), по факту это количество зависит от конкретного чипа и температурных условий, независимые тесты показали 3-6 миллионов циклов перезаписи при комнатной температуре до появления первой ошибки, т.е. заявленные 100 000 взяты с очень большим запасом. Но есть небольшое уточнение – при заявленных 100 000 циклах перезаписи гарантируется сохранность записанных данных в течение 100 лет при температуре 24°C, если перезаписывать по миллиону – данные испортятся быстрее. В то же время количество чтений каждой ячейки неограниченно.

У МК esp8266/esp32 EEPROM эмулируется из Flash памяти, а её ресурс сильно меньше – производитель гарантирует всего 10 000 циклов записи!

EEPROM представляет собой область памяти, состоящую из элементарных ячеек с размером в один байт (как SRAM). Объём EEPROM разный у разных моделей МК:

  • ATmega328 (Arduino UNO, Nano, Pro Mini): 1 кБ
  • ATmega2560 (Arduino Mega): 4 кБ
  • ATtiny85 (Digispark): 512 Б
  • ESP8266 / ESP32: 4096 Б

Основная задача при работе с EEPROM – не напутать с адресами, потому что каждый байт имеет свой адрес. Если вы пишете двухбайтные данные, то они займут два байта, и следующие данные нужно будет писать по адресу как минимум +2 к предыдущему, иначе они “перемешаются”. Рассмотрим пример хранения набора данных разного типа, расположенных в памяти последовательно друг за другом (в скобках я пишу размер текущего типа данных, на размер которого увеличится адрес для следующего “блока”):

  • byte – адрес 0 (+1)
  • byte – адрес 1 (+1)
  • int – адрес 2 (+2) (+4 для esp8266)
  • byte – адрес 4 (+1)
  • float – адрес 5 (+4)
  • int – адрес 9 (+2)
  • и так далее

Важный момент: все ячейки имеют значение по умолчанию (у нового чипа) 255.

Скорость работы с EEPROM (время не зависит от частоты системного клока):

  • Запись одного байта занимает ~3.3 мс (миллисекунды)
  • Чтение одного байта занимает ~0.4 мкс (микросекунды)

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

При использовании внутреннего тактового генератора на 8 МГц, его отклонение не должно быть выше 10% (7.2-8.8 МГц), иначе запись в EEPROM или FLASH скорее всего будет производиться с ошибками. Соответственно все разгоны внутреннего клока недопустимы при записи EEPROM или FLASH.

Для работы с EEPROM в среде Arduino у нас есть целых две библиотеки, вторая является более удобной “оболочкой” для первой. Рассмотрим их обе, потому что в “чужом скетче” может встретиться всё что угодно, да и совместное использование этих двух библиотек делает работу с EEPROM невероятно удобной.

Библиотека avr/eeprom.h


Описание к этой библиотеке я спрятал под спойлер, потому что она не очень актуальна и знать о ней необязательно. Также она не работает на esp8266/32 по понятным причинам.

avr/eeprom.h

Стандартная библиотека eeprom.h идёт в комплекте с компилятором avr-gcc, который компилирует наши скетчи из под Arduino IDE. Полную документацию можно почитать здесь. Для подключения библиотеки в скетч пишем #include <avr/eeprom.h> Библиотека имеет набор функций для работы с целочисленными типами данных (byte – 1 байт, word – 2 байта, dword – 4 байта), float, и block “блоков” – наборов данных любого формата (структуры, массивы, и т.д.). Под работой подразумевается запись, чтение и обновление. Обновление – крайне важный инструмент, позволяющий избежать лишних перезаписей ячеек памяти. Обновление делает запись, если записываемое значение отличается от текущего в этой ячейке. Чтение:

  • eeprom_read_byte(адрес) – вернёт значение
  • eeprom_read_word(адрес) – вернёт значение
  • eeprom_read_dword(адрес) – вернёт значение
  • eeprom_read_float(адрес) – вернёт значение
  • eeprom_read_block(адрес в SRAM, адрес в EEPROM, размер) – прочитает содержимое по адрес в EEPROM в адрес в SRAM

Запись:

  • eeprom_write_byte(адрес, значение)
  • eeprom_write_word(адрес, значение)
  • eeprom_write_dword(адрес, значение)
  • eeprom_write_float(адрес, значение)
  • eeprom_write_block(адрес в SRAM, адрес в EEPROM, размер) – запишет содержимое по адрес в SRAM в адрес в EEPROM

Обновление:

  • eeprom_update_byte(адрес, значение)
  • eeprom_update_word(адрес, значение)
  • eeprom_update_dword(адрес, значение)
  • eeprom_update_float(адрес, значение)
  • eeprom_update_block(адрес в SRAM, адрес в EEPROM, размер) – обновит содержимое по адрес в SRAM в адрес в EEPROM

Макросы:

  • _EEPUT(addr, val) – записывает (write) байт val по адресу addr. Приведение типов не требуется (оно сделано в макросе)
  • _EEGET(val, addr) – читает байт по адресу addr и записывает его в переменную val. Приведение типов не требуется (оно сделано в макросе)

Рассмотрим простой пример, в котором происходит запись и чтение единичных типов данных в разные ячейки:

#include <avr/eeprom.h>

void setup() {
  Serial.begin(9600);
  
  // объявляем данные разных типов
  byte dataB = 120;
  float dataF = 3.14;
  int16_t dataI = -634;  

  // пишем друг за другом
  eeprom_write_byte(0, dataB);  // 1 байт
  eeprom_write_float(1, dataF);  // 4 байта

  // для разнообразия "обновим"
  eeprom_update_word(5, dataI);

  // объявляем переменные, куда будем читать
  byte dataB_read = 0;
  float dataF_read = 0;
  int16_t dataI_read = 0;

  // читаем
  dataB_read = eeprom_read_byte(0);
  dataF_read = eeprom_read_float(1);
  dataI_read = eeprom_read_word(5);

  // выведет 120 3.14 -634
  Serial.println(dataB_read);
  Serial.println(dataF_read);
  Serial.println(dataI_read);
}

void loop() {}

Хранить данные таким образом не очень удобно, потому что менеджмент адресов приходится проводить вручную, считать количество байт в каждом типе и “сдвигать” адрес на нужное количество. Гораздо удобнее хранить разношёрстные данные в структурах, про них мы подробнее говорили в уроке про типы данных. Мы должны передать функции адрес данных в памяти (оператор &), по сути – указатель, а также преобразовать его к типу void*, потому что функция чтения/записи блока принимает именно такой тип. Подробнее про указатели мы говорили в отдельном уроке. Также функции чтения/записи блока нужно передать размер блока данных в количестве байт. Это можно сделать вручную (числом), но лучше использовать sizeof(), которая посчитает этот размер и передаст в функцию.

#include <avr/eeprom.h>

void setup() {
  Serial.begin(9600);

  // объявляем структуру
  struct MyStruct {
    byte a;
    int b;
    float c;
  };

  // создаём и заполняем структуру
  MyStruct myStruct;
  myStruct.a = 10;
  myStruct.b = 1000;
  myStruct.c = 3.14;

  // записываем по адресу 10, указав размер структуры и приведя к void*
  eeprom_write_block((void*)&myStruct, 10, sizeof(myStruct));

  // создаём новую пустую структуру
  MyStruct newStruct;

  // читаем из адреса 10
  eeprom_read_block((void*)&newStruct, 10, sizeof(newStruct));

  // проверяем
  // выведет 10 1000 3.14
  Serial.println(newStruct.a);
  Serial.println(newStruct.b);
  Serial.println(newStruct.c);
}

void loop() {}

Точно так же можно хранить массивы:

#include <avr/eeprom.h>

void setup() {
  Serial.begin(9600);

  // создаём массив
  float dataF[] = {3.14, 60.25, 9132.5, -654.3};

  // записываем по адресу 20, указав размер
  eeprom_write_block((void*)&dataF, 20, sizeof(dataF));

  // создаём новую пустой массив такого же типа и размера!
  float dataF_read[4];

  // читаем из адреса 20
  eeprom_read_block((void*)&dataF_read, 20, sizeof(dataF_read));

  // проверяем
  // выведет 3.14 60.25 9132.5 -654.3
  for (byte i = 0; i < 4; i++)
    Serial.println(dataF_read[i]);
}

void loop() {}

В библиотеке avr/eeprom.h есть ещё один очень полезный инструмент – EEMEM, он позволяет сделать автоматическую адресацию данных путём создания указателей, значение которым присвоит компилятор. Рассмотрим пример, в котором запишем в EEPROM несколько переменных, структуру и массив, раздав им автоматически адреса. Важный момент! Адреса задаются снизу вверх по порядку объявления EEMEM, я подпишу их в примере:

#include <avr/eeprom.h>
struct MyStruct {
  byte val1;
  int val2;
  float int3;
};

uint8_t EEMEM byteAddr;     // 27
uint16_t EEMEM intAddr;     // 25
uint32_t EEMEM longAddr;    // 21
MyStruct EEMEM myStructAddr;// 14
int EEMEM intArrayAddr[5];  // 4
float EEMEM floatAddr;      // 0

EEMEM сам раздаёт адреса, основываясь на размере данных. Важный момент: данный подход не занимает дополнительного места в памяти, т.е. нумерация адресов вручную цифрами, без создания EEMEM “переменных”, не занимает меньше памяти! Давайте вернёмся к нашему первому примеру и перепишем его с EEMEM. При указании адреса через EEMEM нужно использовать оператор взятия адреса &

#include <avr/eeprom.h>
byte EEMEM dataB_addr;
float EEMEM dataF_addr;
int16_t EEMEM dataI_addr;

void setup() {
  Serial.begin(9600);

  // объявляем данные разных типов
  byte dataB = 120;
  float dataF = 3.14;
  int16_t dataI = -634;

  // пишем друг за другом
  eeprom_write_byte(&dataB_addr, dataB);
  eeprom_write_float(&dataF_addr, dataF);

  // для разнообразия "обновим"
  eeprom_update_word(&dataI_addr, dataI);

  // объявляем переменные, куда будем читать
  byte dataB_read = 0;
  float dataF_read = 0;
  int16_t dataI_read = 0;

  // читаем
  dataB_read = eeprom_read_byte(&dataB_addr);
  dataF_read = eeprom_read_float(&dataF_addr);
  dataI_read = eeprom_read_word(&dataI_addr);

  // выведет 120 3.14 -634
  Serial.println(dataB_read);
  Serial.println(dataF_read);
  Serial.println(dataI_read);
}

void loop() {}

Ну и напоследок, запись и чтение блока через EEMEM. Адрес придётся преобразовать в (const void*) вручную:

#include <avr/eeprom.h>
// получим адрес (тут будет 0)
int EEMEM intArrayAddr[5];

void setup() {
  Serial.begin(9600);

  // создаём массив
  int intArrayWrite[5] = {10, 20, 30, 40, 50};

  // пишем по адресу intArrayAddr
  eeprom_write_block((void*)&intArrayWrite, (const void*)&intArrayAddr, sizeof(intArrayWrite));

  // создаём новый массив для чтения
  int intArrayRead[5];

  // читаем по адресу intArrayAddr
  eeprom_read_block((void*)&intArrayRead, (const void*)&intArrayAddr, sizeof(intArrayRead));

  // проверим
  for (byte i = 0; i < 5; i++)
    Serial.println(intArrayRead[i]);
}

void loop() {}

Таким образом можно добавлять “данные” для хранения в EEPROM прямо по ходу разработки программы, не думая об адресах. Рекомендую добавлять новые данные над старыми, чтобы адресация не сбивалась (напомню, адресация идёт снизу вверх, начиная с нуля).

Библиотека EEPROM.h


Библиотека EEPROM.h идёт в комплекте с ядром Arduino и является стандартной библиотекой. По сути EEPROM.h – это удобная оболочка для avr/eeprom.h, чуть расширяющая её возможности и упрощающая использование.

Для AVR Arduino: подключая в скетч EEPROM.h мы автоматически подключаем avr/eeprom.h и можем пользоваться её фишками, такими как EEMEM.

Рассмотрим инструменты, которые нам предлагает библиотека:

  • EEPROM.write(адрес, данные) – пишет данные (только byte!) по адресу
  • EEPROM.update(адрес, данные) – обновляет (та же запись, но лучше) байт данных, находящийся по адресу. Не реализована для esp8266/32!
  • EEPROM.read(адрес) – читает и возвращает байт данных, находящийся по адресу
  • EEPROM.put(адрес, данные) – записывает (по факту – обновляет, update) данные любого типа (типа переданной переменной) по адресу
  • EEPROM.get(адрес, данные) – читает данные по адресу и сам записывает их в данные – указанную переменную
  • EEPROM[] – библиотека позволяет работать с EEPROM памятью как с обычным массивом типа byte (uint8_t)

У esp8266 и esp32 есть отличия:

  • Перед началом работы нужно вызвать EEPROM.begin(размер) с указанием максимального объёма памяти: 4.. 4096 Байт.
  • Для применения записи нужно вызвать EEPROM.commit(): например несколько раз делается write(), put(), и в завершение – commit()
  • В некоторых версиях SDK отсутствует EEPROM.update()

В отличие от avr/eeprom.h у нас нет отдельных инструментов для работы с конкретными типами данных, отличными от byte, и сделать write/update/read для float/long/int мы не можем. Но зато у нас есть всеядные put и get, которые очень удобно использовать! Рассмотрим пример с чтением/записью байтов:

#include <EEPROM.h>

void setup() {
  Serial.begin(9600);
  //EEPROM.begin(100);   // для esp8266/esp32
  
  // пишем 200 по адресу 10
  EEPROM.update(10, 200);
  //EEPROM.commit();     // для esp8266/esp32
  Serial.println(EEPROM.read(10));  // выведет 200
  Serial.println(EEPROM[10]);       // выведет 200
}

void loop() {}

Логика работы с адресами такая же, как в предыдущем пункте урока! Обратите внимание на работу с EEPROM как с массивом, можно читать, писать, сравнивать, и даже использовать составные операторы, например EEPROM[0] += 10 , но это работает только для элементарных ячеек, байтов.

Теперь посмотрим, как работает put() и get():

#include <EEPROM.h>

void setup() {
  Serial.begin(9600);
  //EEPROM.begin(100);   // для esp8266/esp32

  // объявляем переменные, которые будем писать
  float dataF = 3.14;
  int16_t dataI = -634;
  byte dataArray[] = {10, 20, 30, 40};

  EEPROM.put(0, dataF);
  EEPROM.put(4, dataI);
  EEPROM.put(6, dataArray);
  //EEPROM.commit();     // для esp8266/esp32

  // объявляем переменные, куда будем читать
  float dataF_read = 0;
  int16_t dataI_read = 0;
  byte dataArray_read[4];

  // читаем точно так же, как писали
  EEPROM.get(0, dataF_read);
  EEPROM.get(4, dataI_read);
  EEPROM.get(6, dataArray_read);

  // проверяем
  Serial.println(dataF_read);
  Serial.println(dataI_read);
  Serial.println(dataArray_read[0]);
  Serial.println(dataArray_read[1]);
  Serial.println(dataArray_read[2]);
  Serial.println(dataArray_read[3]);
}

void loop() {}

put() и get() сами определяют тип данных и считают размер блока данных, использовать их очень приятно. Они работают как с массивами, так и со структурами.

EEPROM.h + структуры


Самый удобный хранить набор данных в EEPROM – структура (разбирали в уроке про типы данных). Структура позволяет объединить любые данные под одним именем, и одной строчкой загонять их в EEPROM и так же читать обратно. А также не придётся думать об адресации! Пример:

#include <EEPROM.h>

struct Data {
  byte bright = 0;
  int counter = 0;
  float fvalue = 0;
};

// глобальный экземпляр для личного использования
Data data;

void setup() {
  EEPROM.get(0, data);   // прочитать из адреса 0
  // меняем
  data.bright = 10;
  data.counter = 1234;
  data.fvalue = 3.14;
  EEPROM.put(0, data);   // поместить в EEPROM по адресу 0
}

void loop() {}

EEPROM.h + avr/eeprom.h


Пример не очень актуален, используй EEPROM + структуры

EEPROM.h + avr/eeprom.h

Ну и конечно же, можно использовать одновременно все преимущества обеих библиотек, например автоматическую адресацию EEMEM и put/get. Рассмотрим на предыдущем примере, вместо ручного задания адресов используем EEMEM, но величину придётся привести к целочисленному типу, сначала взяв от него адрес, т.е. (int)&адрес_еемем

#include <EEPROM.h>
float EEMEM dataF_addr;
int16_t EEMEM dataI_addr;
byte EEMEM dataArray_addr[5];

void setup() {
  Serial.begin(9600);

  // объявляем переменные, которые будем писать
  float dataF = 3.14;
  int16_t dataI = -634;
  byte dataArray[] = {10, 20, 30, 40};

  EEPROM.put((int)&dataF_addr, dataF);
  EEPROM.put((int)&dataI_addr, dataI);
  EEPROM.put((int)&dataArray_addr, dataArray);

  // объявляем переменные, куда будем читать
  float dataF_read = 0;
  int16_t dataI_read = 0;
  byte dataArray_read[4];

  // читаем точно так же, как писали
  EEPROM.get((int)&dataF_addr, dataF_read);
  EEPROM.get((int)&dataI_addr, dataI_read);
  EEPROM.get((int)&dataArray_addr, dataArray_read);
  EEPROM[0] += 10;

  // проверяем
  Serial.println(dataF_read);
  Serial.println(dataI_read);
  Serial.println(dataArray_read[0]);
  Serial.println(dataArray_read[1]);
  Serial.println(dataArray_read[2]);
  Serial.println(dataArray_read[3]);
}

void loop() {}

С возможностями библиотек разобрались, перейдём к практике.

Реальный пример


Рассмотрим пример, в котором происходит следующее: две кнопки управляют яркостью светодиода, подключенного к ШИМ пину. Установленная яркость сохраняется в EEPROM, т.е. при перезапуске устройства будет включена яркость, установленная последний раз. Для опроса кнопок используется библиотека GyverButton. Для начала посмотрите на первоначальную программу, где установленная яркость не сохраняется. Программу можно чуть оптимизировать, но это не является целью данного урока.

Меняем яркость кнопками

#define BTN_UP_PIN 3    // пин кнопки вверх
#define BTN_DOWN_PIN 4  // пин кнопки вниз
#define LED_PIN 5       // пин светодиода

#include <GyverButton.h>

GButton btnUP(BTN_UP_PIN); // кнопка "яркость вверх"
GButton btnDOWN(BTN_DOWN_PIN); // кнопка "яркость вниз"

int LEDbright = 0;

void setup() {
  pinMode(LED_PIN, OUTPUT); // пин светодиода как выход
}

void loop() {
  // опрос кнопок
  btnUP.tick();
  btnDOWN.tick();

  if (btnUP.isClick()) {
    // увеличение по клику
    LEDbright += 5;
    setBright();
  }

  if (btnDOWN.isClick()) {
    // уменьшение по клику
    LEDbright -= 5;
    setBright();
  }
}

void setBright() {
  LEDbright = constrain(LEDbright, 0, 255); // ограничили
  analogWrite(LED_PIN, LEDbright);    // изменили яркость
}

В этот код нам нужно добавить:

  • Подключить библиотеку EEPROM.h
  • При запуске: чтение яркости из EEPROM и включение светодиода
  • При клике: запись актуального значения в EEPROM

Сохранение яркости

#define BTN_UP_PIN 3    // пин кнопки вверх
#define BTN_DOWN_PIN 4  // пин кнопки вниз
#define LED_PIN 5       // пин светодиода

#include <EEPROM.h>
#include <GyverButton.h>

GButton btnUP(BTN_UP_PIN); // кнопка "яркость вверх"
GButton btnDOWN(BTN_DOWN_PIN); // кнопка "яркость вниз"

int LEDbright = 0;

void setup() {
  pinMode(LED_PIN, OUTPUT); // пин светодиода как выход
  EEPROM.get(0, LEDbright); // прочитали яркость из адреса 0
  analogWrite(LED_PIN, LEDbright);  // включили
}

void loop() {
  // опрос кнопок
  btnUP.tick();
  btnDOWN.tick();

  if (btnUP.isClick()) {
    // увеличение по клику
    LEDbright += 5;
    setBright();
  }

  if (btnDOWN.isClick()) {
    // уменьшение по клику
    LEDbright -= 5;
    setBright();
  }
}

void setBright() {
  LEDbright = constrain(LEDbright, 0, 255); // ограничили
  EEPROM.put(0, LEDbright);           // записали по адресу 0
  analogWrite(LED_PIN, LEDbright);    // изменили яркость
}

Итак, теперь при запуске у нас восстанавливается последняя настроенная яркость, и при изменении она записывается. Напомню, что EEPROM изнашивается от перезаписи. Конечно для того, чтобы “накликать” яркость несколько миллионов раз и убить ячейку, у вас уйдёт очень много времени, но процесс записи нового значения можно и нужно оптимизировать, особенно в более серьёзных проектах, ниже поговорим об этом подробнее. Также в нашем коде есть ещё один неприятный момент: при самом первом запуске после прошивки EEPROM не инициализирована, каждая ячейка хранит в себе число 255, и именно такое значение примет переменная LEDbright после первого запуска, при так называемом “первом чтении”. Здесь это не имеет значения, но в более серьёзном устройстве нужно будет задать нужные значения по умолчанию в EEPROM при первом запуске, об этом мы тоже поговорим ниже. Иначе представьте, какие “настройки по умолчанию” получит ваше устройство для яркости/скорости/громкости/номера режима/прочее!

Запись и чтение строк


У нас есть два типа строк: массивы символов и String-строки. С массивом символов всё более-менее понятно: это массив, он имеет фиксированный размер, его можно записать при помощи put() и прочитать при помощи get(). Также такая строка может входить в структуру, что очень удобно. В этом случае нужно объявить структуру с указанием максимальной длины строки, которая может там храниться. Например для какого-нибудь проекта с WiFi нам хочется хранить логин и пароль от роутера и режим работы:

struct Cfg {
  char ssid[16];
  char pass[16];
  byte mode;
};

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

А как записать и прочитать динамические данные, такие как String-строки? Можно рассмотреть два способа: с массивом ограниченной длины (как в примере выше) и полностью динамическое хранение.

Будем считать, что максимальная длина строки – 20 символов. Простой пример:

#include <EEPROM.h>
#define STR_ADDR 0  // адрес хранения строки в EEPROM


void setup() {
  Serial.begin(115200);

  // читаем
  char str[20];
  EEPROM.get(STR_ADDR, str);

  // выводим
  Serial.print("Read text: ");
  Serial.println(str);
}

void loop() {
  // читаем строку из порта
  if (Serial.available()) {
    char str[20];
    int len = Serial.readBytes(str, 20);

    // завершающий символ, добавляем вручную
    str[len] = 0;

    // записываем
    EEPROM.put(STR_ADDR, str);
    
    Serial.print("Save text: ");
    Serial.println(str);
  }
}

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

#include <EEPROM.h>

#define STR_ADDR 0  // адрес хранения строки в EEPROM

void setup() {
  Serial.begin(115200);
  
  String str;
  int len = EEPROM.read(STR_ADDR);  // читаем длину строки
  str.reserve(len);    // резервируем место (для оптимальности)

  // читаем
  for (int i = 0; i < len; i++) {
    str += (char)EEPROM.read(STR_ADDR + 1 + i);
  }
  
  // выводим
  Serial.print("Read text: ");
  Serial.println(str);
}

void loop() {
  // читаем строку из порта
  if (Serial.available()) {
    String inc = Serial.readString();
    Serial.print("Save text: ");
    Serial.println(inc);
    
    int len = inc.length();   // длина строки
    EEPROM.write(STR_ADDR, len);  // записываем её
    // и далее саму строку посимвольно
    for (int i = 0; i < len; i++) {
      EEPROM.write(STR_ADDR + 1 + i, inc[i]);
    }
  }
}

Полезные трюки


Инициализация


Под инициализацией я имею в виду установку значений ячеек в EEPROM “по умолчанию” во время первого запуска устройства. В рассмотренном выше примере мы действовали в таком порядке:

  1. Чтение из EEPROM в переменную
  2. Использование переменной по назначению

При первом запуске кода (и при всех дальнейших, в которых в ячейку ничего нового не пишется) переменная получит значение, которое было в EEPROM по умолчанию. В большинстве случаев это значение не подойдёт устройству, например ячейка хранит номер режима, по задумке разработчика – от 0 до 5, а из EEPROM мы прочитаем 255. Непорядок! При первом запуске нужно инициализировать EEPROM так, чтобы устройство работало корректно, для этого нужно определить этот самый первый запуск. Можно сделать это вручную, прошив программу, которая забьёт EEPROM нужными данными. Далее прошить уже рабочую программу. При разработке программы это очень неудобно, ведь количество сохраняемых данных может меняться в процессе разработки, поэтому можно использовать следующий алгоритм:

  1. Резервируем какую-нибудь ячейку (например, последнюю) под хранение “ключа” первого запуска
  2. Читаем ячейку, если её содержимое не совпадает с ключом – это первый запуск!
  3. В обработчике первого запуска пишем в ячейку нужный ключ
  4. Пишем в остальные ячейки необходимые значения по умолчанию
  5. И после этого уже читаем данные во все нужные переменные

Рассмотрим на всё том же примере со светодиодом и кнопками:

Сохранение яркости

#define INIT_ADDR 1023  // номер резервной ячейки
#define INIT_KEY 50     // ключ первого запуска. 0-254, на выбор

#define BTN_UP_PIN 3    // пин кнопки вверх
#define BTN_DOWN_PIN 4  // пин кнопки вниз
#define LED_PIN 5       // пин светодиода

#include <EEPROM.h>
#include <GyverButton.h>

GButton btnUP(BTN_UP_PIN); // кнопка "яркость вверх"
GButton btnDOWN(BTN_DOWN_PIN); // кнопка "яркость вниз"

int LEDbright = 0;

void setup() {
  pinMode(LED_PIN, OUTPUT); // пин светодиода как выход

  if (EEPROM.read(INIT_ADDR) != INIT_KEY) { // первый запуск
    EEPROM.write(INIT_ADDR, INIT_KEY);    // записали ключ

    // записали стандартное значение яркости
    // в данном случае это значение переменной, объявленное выше
    EEPROM.put(0, LEDbright);
  }
  EEPROM.get(0, LEDbright); // прочитали яркость
  analogWrite(LED_PIN, LEDbright);  // включили
}

void loop() {
  // опрос кнопок
  btnUP.tick();
  btnDOWN.tick();

  if (btnUP.isClick()) {
    // увеличение по клику
    LEDbright += 5;
    setBright();
  }

  if (btnDOWN.isClick()) {
    // уменьшение по клику
    LEDbright -= 5;
    setBright();
  }
}

void setBright() {
  LEDbright = constrain(LEDbright, 0, 255); // ограничили
  EEPROM.put(0, LEDbright);           // записали
  analogWrite(LED_PIN, LEDbright);    // изменили яркость
}

Теперь при первом запуске мы получим инициализацию нужных ячеек. Если нужно переинициализировать EEPROM, например в случае добавления новых данных, достаточно изменить наш ключ на любое другое значение в пределах одного байта (0-254). Я пишу именно до 254, потому что 255 является значением ячейки по умолчанию и наш трюк не сработает.

Сброс до “заводских”


Чтобы вернуть настройки к изначально заданным в программе, нужно “спровоцировать” инициализацию. Очевидный способ сделать это – изменить ключ инициализации, который мы назвали INIT_KEY. Либо можно просто вызвать EEPROM.put(адрес, базовые настройки) в нужном месте программы.

Скорость


Как я писал выше, скорость работы с EEPROM составляет:

  • Запись/обновление одного байта занимает ~3.3 мс (миллисекунды)
  • Чтение одного байта занимает ~0.4 мкс (микросекунды)

При большом желании можно использовать ячейку вместо переменной, т.е. выше мы с вами рассматривали пример, в котором EEPROM читался в переменную в программе, и дальнейшая работа происходила уже с ней. При сильной нехватке оперативной памяти можно читать значение напрямую из EEPROM, ведь это занимает ничтожно мало времени. А вот с записью всё гораздо хуже, там целых 3.3 мс. Например так:

analogWrite(LED_PIN, EEPROM.read(0));   // изменили яркость

Для изменения значения придётся прочитать ячейку, выполнить нужные операции, и снова в неё записать. Ещё один удобный хак: можно ввести макросы на чтение и запись определённых значений, например:

#define GET_MODE EEPROM.read(0)     // получить номер режима
#define GET_BRIGHT EEPROM.read(1)   // получить яркость
#define SET_MODE(x) EEPROM.write(0, (x))  // запомнить режим
#define SET_BRIGHT(x) EEPROM.put(1, (x))  // запомнить яркость

Получим удобные макросы, с которыми писать код будет чуть быстрее и удобнее, т.е. строка SET_MODE(3) запишет 3 в ячейку 0

Уменьшение износа


Важная тема: уменьшение износа ячеек частыми перезаписями. Ситуаций может быть много, интересных решений для них – тоже. Рассмотрим простейший пример – всё тот же код со светодиодом и кнопкой. Делать будем следующее: записывать новое значение будем только в том случае, если после последнего нажатия на кнопку прошло какое-то время. То есть нам понадобится таймер (воспользуемся таймером на millis), при нажатии на кнопку таймер будет сбрасываться, а при срабатывании таймера будем писать актуальное значение в EEPROM. Также понадобится флаг, который будет сигнализировать о записи и позволит записать именно один раз. Алгоритм такой:

  • При нажатии на кнопку:
    • Если флаг опущен – поднять флаг
    • Сбросить таймер
  • Если сработал таймер и флаг поднят:
    • Опустить флаг
    • Записать значения в EEPROM

Посмотрим на всё том же примере:

Сохранение яркости

#define INIT_ADDR 1023  // номер резервной ячейки
#define INIT_KEY 50     // ключ первого запуска. 0-254, на выбор

#define BTN_UP_PIN 3    // пин кнопки вверх
#define BTN_DOWN_PIN 4  // пин кнопки вниз
#define LED_PIN 5       // пин светодиода

#include <EEPROM.h>
#include <GyverButton.h>

GButton btnUP(BTN_UP_PIN); // кнопка "яркость вверх"
GButton btnDOWN(BTN_DOWN_PIN); // кнопка "яркость вниз"

int LEDbright = 0;
uint32_t eepromTimer = 0;
boolean eepromFlag = false;

void setup() {
  pinMode(LED_PIN, OUTPUT); // пин светодиода как выход

  if (EEPROM.read(INIT_ADDR) != INIT_KEY) { // первый запуск
    EEPROM.write(INIT_ADDR, INIT_KEY);    // записали ключ

    // записали стандартное значение яркости
    // в данном случае это значение переменной, объявленное выше
    EEPROM.put(0, LEDbright);
  }
  EEPROM.get(0, LEDbright); // прочитали яркость
  analogWrite(LED_PIN, LEDbright);  // включили
}

void loop() {
  // проверка EEPROM
  checkEEPROM();

  // опрос кнопок
  btnUP.tick();
  btnDOWN.tick();

  if (btnUP.isClick()) {
    // увеличение по клику
    LEDbright += 5;
    setBright();
  }

  if (btnDOWN.isClick()) {
    // уменьшение по клику
    LEDbright -= 5;
    setBright();
  }
}

void setBright() {
  LEDbright = constrain(LEDbright, 0, 255); // ограничили
  analogWrite(LED_PIN, LEDbright);          // изменили яркость
  eepromFlag = true;                        // поднять флаг
  eepromTimer = millis();                   // сбросить таймер
}

void checkEEPROM() {
  // если флаг поднят и с последнего нажатия прошло 10 секунд (10 000 мс)
  if (eepromFlag && (millis() - eepromTimer >= 10000) ) {
    eepromFlag = false;           // опустили флаг
    EEPROM.put(0, LEDbright);     // записали в EEPROM
  }
}

Вот таким нехитрым способом мы многократно снизили износ EEPROM, я очень часто использую этот “алгоритм” работы с настройками в своих устройствах. Есть другие задачи, в которых данные в EEPROM пишутся не когда пользователь что-то изменит, а постоянно, т.е. память работает в режиме чёрного ящика и постоянно записывает значения. Это может быть например контроллер печи, который держит температурный режим по специальному закону, и после внезапной перезагрузки должен вернуться к тому месту в процессе, на котором прервался. Тут есть глобально два варианта:

  • Ёмкий конденсатор по питанию микроконтроллера, позволяющий сохранить работу МК после отключения питания на время, достаточное для записи в EEPROM (~3.3 мс). Также МК должен знать о том, что общее питание отключилось: если это высокое напряжение (выше 5 Вольт), то это может быть делитель напряжения на аналоговый пин. Если это 5 Вольт – можно измерять напряжение МК, и момент отключения (разрядка конденсатора) тоже можно отловить и записать нужные данные. Можно взвести прерывание, которое сработает при падении напряжения питания ниже опасного уровня. Можно 5 Вольт завести напрямую на цифровой пин, а сам МК питать через диод и поставить конденсатор – тогда напряжение на измеряющем пине пропадёт до того, как отключится МК, он будет работать от конденсатора. Вот схема:
  • blank
  • Можно писать данные (необязательно один байт, можно целую структуру) хитро, размазывая их по всему EEPROM. Тут глобально два варианта:
    • Писать данные каждый раз в следующую ячейку, и закольцевать переход на первую. Также понадобится хранить где-то счётчик, указывающий на адрес текущей ячейки, и этот счётчик тоже придётся хранить хитро, чтобы он не износил ячейку. Например счётчик – это структура, состоящая из счётчика перезаписей этой структуры и счётчика адреса для большой структуры.
    • Писать данные, пока не достигнут лимит количества перезаписей, количество текущих перезаписей хранить например в этой же структуре. Скажем структура занимает 30 байт, то есть в перспективе мы можем найти эту структуру по адресу, кратному 30. Программа работает, счётчик считает количество перезаписей, при достижении опасного количества вся структура “переезжает” на следующие 30 адресов.

Вариантов уменьшения износа ячеек EEPROM можно придумать много, уникально под свою ситуацию. Есть даже библиотеки готовые, например EEPROMWearLevel. Есть очень интересная статья на Хабре, там рассмотрено ещё несколько хороших алгоритмов и даны ссылки на ещё большее их количество.

Библиотека EEManager


Я часто использую EEPROM в своих проектах, поэтому обернул все рассмотренные выше конструкции в библиотеку, изучить и скачать можно здесь. Библиотека подходит для всех архитектур, в которых есть стандартная EEPROM.h. В библиотеке реализовано:

  • Работа с данными любого типа
  • Чтение и запись в указанную переменную
  • Функция “ключа первого запуска” для задания начальных значений
  • Отложенное обновление по тайм-ауту для уменьшения износа

Я надеюсь вы полностью разобрались с самым последним примером с кнопкой и светодиодом, поэтому покажу работу EEManager на его основе:

EEManager, кнопка и светодиод

#define INIT_KEY 50     // ключ первого запуска. 0-254, на выбор

#define BTN_UP_PIN 3    // пин кнопки вверх
#define BTN_DOWN_PIN 4  // пин кнопки вниз
#define LED_PIN 5       // пин светодиода

#include <GyverButton.h>
GButton btnUP(BTN_UP_PIN); // кнопка "яркость вверх"
GButton btnDOWN(BTN_DOWN_PIN); // кнопка "яркость вниз"

#include <EEManager.h>
int LEDbright = 0;
EEManager memory(LEDbright); // передаём переменную в менеджер

void setup() {
  pinMode(LED_PIN, OUTPUT); // пин светодиода как выход

  // запускаем менеджер, указав адрес и ключ запуска
  // он сам проверит ключ, а также прочитает данные
  // из EEPROM и запишет в переменную
  memory.begin(0, INIT_KEY);

  analogWrite(LED_PIN, LEDbright);  // включили
}

void loop() {
  // здесь произойдёт запись по встроенному таймеру
  memory.tick();

  // опрос кнопок
  btnUP.tick();
  btnDOWN.tick();

  if (btnUP.isClick()) {
    // увеличение по клику
    LEDbright += 5;
    setBright();
  }

  if (btnDOWN.isClick()) {
    // уменьшение по клику
    LEDbright -= 5;
    setBright();
  }
}

void setBright() {
  LEDbright = constrain(LEDbright, 0, 255); // ограничили
  analogWrite(LED_PIN, LEDbright);          // изменили яркость
  memory.update();                          // сообщаем, что данные нужно обновить
}

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

Видео


Полезные страницы


  • Набор GyverKIT – большой стартовый набор Arduino моей разработки, продаётся в России
  • Каталог ссылок на дешёвые Ардуины, датчики, модули и прочие железки с AliExpress у проверенных продавцов
  • Подборка библиотек для Arduino, самых интересных и полезных, официальных и не очень
  • Полная документация по языку Ардуино, все встроенные функции и макросы, все доступные типы данных
  • Сборник полезных алгоритмов для написания скетчей: структура кода, таймеры, фильтры, парсинг данных
  • Видео уроки по программированию Arduino с канала “Заметки Ардуинщика” – одни из самых подробных в рунете
  • Поддержать автора за работу над уроками
  • Обратная связь – сообщить об ошибке в уроке или предложить дополнение по тексту ([email protected])

В последнее время, снова как и раньше, мне пришлось частично вернуться к самозанятости по ремонтам электроники. Получив на основном месте работы избыток свободного времени, правда немного в ущерб стабильности дохода, получил взамен хорошую возможность развиваться как  мастер-ремонтник. Сотрудничаю параллельно с маленькой мастерской по ремонту электроники, находящейся в проходном месте, как совместитель, плюс выкупаю технику на Авито и Юле, привожу в норму и реализую там же. Через мои руки проходит много материнских плат, блоков питания АТХ, ЖК мониторов и ТВ, и другой электронной техники. 

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

ПЕРЕПРОШИВКА FLASH И EEPROM

EEPROM память

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

ПЕРЕПРОШИВКА FLASH И EEPROM

Микросхема EEPROM SMD

Зачастую нам даже не приходится браться за паяльник для того чтобы совершить перепрошивку, достаточно просто использовать специальную клипсу для прошивания, подключающуюся к программатору. Но здесь есть один важный нюанс, который касается перепрошивки микросхем 24 и 25 серии, соответственно EEPROM и Flash памяти. 

ПЕРЕПРОШИВКА FLASH И EEPROM

Первая (моя) версия программатора

Flash память 25 серия, часто используется для хранения прошивки BIOS устройств, таких как материнские платы, видеокарты, цифровые приставки, недорогие ЖК ТВ и современные мониторы. Так вот, особенность прошивания микросхем без выпаивания заключается в том, что иногда прошиваемое устройство у нас запитывается по линии 3.3 вольта через клипсу для прошивания. И если материнские платы можно шить обычно без выпаивания микросхемы, за редким исключением, то роутеры, на которых кстати установлена точно такая же микросхема памяти, в большинстве случаев, по крайней мере на современных моделях, таким способом прошить уже проблематично. 

ПЕРЕПРОШИВКА FLASH И EEPROM

Микросхема BIOS

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

ПЕРЕПРОШИВКА FLASH И EEPROM

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

ПЕРЕПРОШИВКА FLASH И EEPROM

Вторая версия программатора

Про худшее, короткое замыкание в USB порту, с последующим возможным выходом подгоранием Южного моста, я стараюсь не думать. Которое все же очень маловероятно, так как в программаторе используется буферная микросхема и в случае форс-мажора, скорее всего все ограничится только ее сгоранием. Причем даже если вы захотите использовать этот способ, у вас не будет 100 процентной уверенности в правильности сохранения Бекапа прошивки перед перепрошивкой устройства, так как во включенном устройстве на выводах микросхемы в момент сохранения прошивки может быть какая-то активность. 

ПЕРЕПРОШИВКА FLASH И EEPROM

роутер микросхема с прошивкой

Предпочитаю пользоваться другим способом, тогда, когда это реально необходимо, перепрошивкой микросхемы с выпаиванием, то есть уже демонтированной микросхемы и последующим запаиванием обратно. На самом деле при наличии опыта все эти операции можно провести максимум за 30-40 минут. 

Но как быть если у вас в мастерской нет паяльного фена? В таком случае сплав Вуда или Розе нанесенный на все ножки, с целью снижения температуры плавления припоя, с обоих сторон микросхемы, и обычный паяльник типа ЭПСН 40 ватт, помогут вам. Микросхема буквально отлетает от платы в два касания паяльника, попеременно прогревая обе стороны микросхемы. 

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

ПЕРЕПРОШИВКА FLASH И EEPROM

Интерфейс программы

Если же по каким-то причинам сохраненный ранее кем-то дамп найти не удалось, встречал в интернете на специализированных сайтах по ремонту электроники рекомендацию сохранить родной дамп EEPROM памяти, очистить микросхему и затем залить снова родной дамп. Не совсем понятно в чем смысл этой процедуры, но видимо раз люди пишут, это все таки имеет смысл. 

ПЕРЕПРОШИВКА FLASH И EEPROM

Цифровая приставка – микросхема с прошивкой

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

ПЕРЕПРОШИВКА FLASH И EEPROM

Стоимость микросхем EEPROM памяти

Это касается как микросхем Flash, так и EEPROM памяти. Причем микросхемы EEPROM памяти, так как имеют очень небольшой объем, стоят новые в радиомагазине копейки. Большинство микросхем как 24, так и 25 серии, имеющие одинаковые объем и напряжение питания, являются взаимозаменяемыми. То есть теоретически вы можете демонтировать микросхему Flash 25 серии объемом 4 МБ с нерабочего роутера и восстановить с ее помощью цифровую DVB-T2 приставку с микросхемой, например, погоревшей из-за грозы. 

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

Подведём итог

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

ПЕРЕПРОШИВКА FLASH И EEPROM

Прошивки мониторов на сайте

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

Автор Сообщение
 

СообщениеДобавлено: 07.07.2020 11:11 

[профиль]

Member

Статус: Не в сети
Регистрация: 10.06.2009

В связи с неадекватностью куратора ветки

Поиск SPD и перепрошивка ППЗУ модулей ОЗУ

, дальнейшее обсуждение предлагаю продолжить здесь.
И так. Блуждая по сети наткнулся на очень не плохой бесплатный редактор таймингов для DDR4 модулей, который автоматически правит CRC в случае их изменения. Поставляется вместе с японским программатором SPD для DDR4 DIMM:

http://www.century-micro.co.jp/download

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

Реклама

Партнер
 
Mordoc

Member

Статус: Не в сети
Регистрация: 19.06.2015

Propretor писал(а):

Блуждая по сети наткнулся на очень не плохой бесплатный редактор таймингов для DDR4 модулей, который автоматически правит CRC в случае их изменения

а если вот это

https://aliexpress.ru/item/400009436592 … web201603_

на адаптере чикнуть две дорожки, и припаять корзину под епромку, и играться можно до потери пульса не мучая SPD модуля

 
Propretor

Member

Статус: Не в сети
Регистрация: 10.06.2009

Mordoc как один из вариантов.
Но мне для тех, кто не хочет мучиться с приобретением программатора, более практичным видится купить адаптер DIMM-SoDIMM к адаптеру припаять например этот переходник (использовать только те контакты, что идут на SPD) и совершенно безопасно на загруженном компьютере вставлять димы и перепрошивать программно. Ничего при этом не сможет сгореть в принципе. Делюсь бесплатно лайфхаком :)
Но мне милее перепрошивка без мучания слотов рабочей матери + возможность прошивать любые модули (от SDR до DDR4) без вскрытия корпуса или поиска нужной матери под нужный тип памяти.

 
Headman

Member

Статус: Не в сети
Регистрация: 15.08.2007
Откуда: Midway

Отличная тема!
В ветке толи про кофемод толи про ддр4(интел) один человек писал что менял создал ХМР профиль на обычные зеленые самсунги,
тоесть протестил что может память, и все зашил в СПД
Это для любых модулей справедливо?(ддр3-ддр4)
Или там могут быть ограничения на количество профилей СПД


_________________
<<ATI OverClan>>

 
Propretor

Member

Статус: Не в сети
Регистрация: 10.06.2009

Headman писал(а):

то для любых модулей справедливо?(ддр3-ддр4)

Конечно.
Более того, для ноутбуков особенно актуально (в связи с отсутствием расширенных настроек как в десктопе), когда XMP профиль нет возможности задействовать (а напряжения у SO-DIMM в XMP обычно те же, что и в основном блоке) и возникает единственный способ задействовать то, за что клиент заплатил — прошить тайминги XMP в основной блок.
Есть еще другая ситуация — производители модулей «забывают» прошить не только в основной блок частоты и тайминги, которые присутствуют в описании товара, на странице производителя или даже стикере, что наклеен на модуль, но и XMP профиль. Не часто, но такое также встречал. Для ноутбуков это опять очень критично, но и для десктопов не очень удобно, поскольку приходится настраивать каждый раз при сносе настроек CMOS SETUP, переезде на новую платформу и т.д. то, что, в принципе нет желания настраивать так часто.

 
Propretor

Member

Статус: Не в сети
Регистрация: 10.06.2009

До SPD PROGRAMMER 2 для DDR4 была версия SPD PROGRAMMER для DDR1-DDR2-DDR3.
Есть подозрение, что софт также работал без наличия программатора. Не могу найти на страницах интернета.
Может плохо ищу. А было бы не плохо иметь и такой редактор в коллекции мастера. Кто-то поможет с поиском?

 
Mordoc

Member

Статус: Не в сети
Регистрация: 19.06.2015

Propretor писал(а):

Есть подозрение, что софт также работал без наличия программатора

Ну так на плате программатора распаян FT232RL, нет порта нет и музыки, софт не работает через шину материнки он общается по USB UART

 
Propretor

Member

Статус: Не в сети
Регистрация: 10.06.2009

Mordoc писал(а):

нет порта нет и музыки, софт не работает через шину материнки он общается по USB UART

Не понял меня. Софт не для прошивки использовать, а как редактор SPD без вытаскивания денег у пользователя.

 
Mordoc

Member

Статус: Не в сети
Регистрация: 19.06.2015

Propretor писал(а):

редактор SPD без вытаскивания денег у пользователя

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

 
RevolverOcelott

Junior

Статус: Не в сети
Регистрация: 24.06.2020

Вопрос с выбором прошивальщика. Если у меня есть память SO-DIMM DDR4 убитая кривыми руками через Тайфун (вшили профиль от чужой памяти, но по крайней мере дамп человек догадался снять тем же тайфуном).
Восстановить её через кинга (

https://gd4.alicdn.com/imgextra/i4/6302 … 026099.png

) реально без перепайки и танцев над чипом?
P.S. Дамп тайфуноский вроде можно в бинарник перегнать без проблем?

 
Propretor

Member

Статус: Не в сети
Регистрация: 10.06.2009

RevolverOcelott у меня есть версия кинга предыдущего поколения, для DDR1-DDR2-DDR3 памяти. Девайс не очень удобный, но данную простую функцию выполняет очень легко.
Однако я рекомендую собрать самому девайс, который не только универсальный, под любую память, но и обойдется много дешевле.
Единственная просьба — отблагодарить автора софта, софт донатный, потому как труда человек вложил реально много, я занимался лишь тестированием и подачей идей и советов, и то потратил кучу времени и сил.
Что уж про него говорить. Полагаю 10$ от каждого пользователя — уже было бы здорово для поддержки автора.
Вот ссылка:

https://forums.evga.com/My-Arduinobased … 53544.aspx

 
Mordoc

Member

Статус: Не в сети
Регистрация: 19.06.2015

Propretor
Что серьезно! канадец сделал приблуду которая пишет DDR4 с нулевого байта, просто нет времени погружаться в тему, да еще с нуля ардуинку изучать, кстати недавно попалась 24C02C даже не смог прочитать, оказалось надо A0 A1 A2 посадить на землю, странно но уже для полтысячи хватало VCC VSS SCL SDA

 
Propretor

Member

Статус: Не в сети
Регистрация: 10.06.2009

Mordoc Кому нужен универсальный прибор, тот погружается. Хотя погружаться то уже и смысла нет. Все уже вылизано и сделано. Требуется только купить ардуину, лучше 3-х вольтовую, тогда схема будет проще чем у «канадца» и отблагодарить автора, потому как софт для винды круче всяких китайских поделок!

 
Dmitrui

Member

Статус: Не в сети
Регистрация: 22.12.2018

Mordoc писал(а):

кстати не вздумайте обновлять базы,

Почему нельзя базы обновлять ? Я демо версией не пользуюсь, если есть полнофункциональная и нахаляву. Там тоже нельзя базы обновлять ?
Я спалил мплату втыкая на горячую, теперь начал делать переходник. Можно конечно купить по ссылке, но я решил сделать бюджетно. Взял планку на 256 DDR2 и отпилил её до ключа, потом отрезал все дорожки кроме тех что на SPD идут. Дальше зависло, лень. Потом доделаю, припаяю провода и надо ещё отрезать слот с м платы. Короче буду шить прямо с компа. Для ноутбучной у меня уже есть куда вставлять, с платы ножницами по металлу вырезал слот и припаял контакты для программатора, но через разъём, чтобы можно было к другим устройствам подключать.

 
Mordoc

Member

Статус: Не в сети
Регистрация: 19.06.2015

Dmitrui писал(а):

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

Автор в последнем обновлении прописал в тело софта код мести :D , после обновления нет старта, на счет ломаного, антивирус бесится

Dmitrui писал(а):

Я спалил мплату втыкая на горячую, теперь начал делать переходник. Можно конечно купить по ссылке, но я решил сделать бюджетно. Взял планку на 256 DDR2 и отпилил её до ключа, потом отрезал все дорожки кроме тех что на SPD идут. Дальше зависло, лень. Потом доделаю, припаяю провода и надо ещё отрезать слот с м платы. Короче буду шить прямо с компа. Для ноутбучной у меня уже есть куда вставлять, с платы ножницами по металлу вырезал слот и припаял контакты для программатора, но через разъём, чтобы можно было к другим устройствам подключать.

Вообще не въехал в техническую сторону, какие-то костыли пряники и каска :shock: , покупаешь за фантик слот DDR3 DDR4 или выпаиваешь из доски, и копеечный программатор для епромок, а! точно, с DDR4 такое не прокатит, дальше рассказывать не буду, кто в теме сами догадаются как подкинуть свой паспорт

 
Dmitrui

Member

Статус: Не в сети
Регистрация: 22.12.2018

Техническая сторона такая: метод знаешь когда скотчем контакты заклеивают. Вот примерно то же, только совать буду не в слот м платы, а в съёмный на проводках, редактировать и шить сразу в программе. Но и под программатор переходник будет. Ещё в компе можно будет ноутбучную подключать и шить. Сейчас приходиться не определяющиеся планки на горячую втыкать. И бывает не той стороной сую.
Это для DDR3 делаю, с DDR4 вообще не работаю. Для DDR2 плат не жалко, можно и на горячую втыкать.

 
Dmitrui

Member

Статус: Не в сети
Регистрация: 22.12.2018

Я посткарту купил и смотрю теперь на неё когда планки проверяю. Некоторые например планки в постоянном рестарте на С7, некоторые его проходят и дальше стопориться.
На 2А уже спикер пищит, что прошла инициализация, но всё равно может на каком то коде зависнуть.
На 78 уже загрузка идёт.
С7 думал прошивку не может считать, но потом после прогрева или ребола запускается, значит не прошивка.
Что то определить не может по объёму чипов наверное.
Кто то интересно с посткартой работает ?

 
Propretor

Member

Статус: Не в сети
Регистрация: 10.06.2009

Dmitrui
Пост карта есть. Там как бы 2 типа кодов. Стандартный и кугуан что-ли. Для китайских кодов софт есть для расшифровки. Стандартные коды они как бы не совсем стандартные, для ами они одни, для феникса — другие.
Не скажу, чтобы мне карта когда-то принципиально помогла…

Вы не можете начинать темы
Вы не можете отвечать на сообщения
Вы не можете редактировать свои сообщения
Вы не можете удалять свои сообщения
Вы не можете добавлять вложения

Лаборатория

Новости

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

EEPROM. Avrdude. Снова про работу с контроллерами

Что такое 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’. В случае успеха, на экране вы увидите примерно следующее.

EEPROM. Avrdude. Снова про работу с контроллерами

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

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

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

EEPROM. Avrdude. Снова про работу с контроллерами

Как и зачем стирать EEPROM?

Для начала,- ‘зачем это делать?’. Стирать EEPROM нужно в том случае, если предыдущая прошивка тоже его использовала, и в памяти мог остаться мусор. Где-то я уже натыкался на людей с проблемами, что после перехода с одной прошивки на другую (с Marlin на Repitier ЕМНИП), у них принтер начинал вести себя, скажем так, ‘творчески’. Это связанно с тем, что разные прошивки хранят свои данные под разными адресами. И при попытке читать данные из неверного адреса начинается свистопляска.

Затереть EEPROM можно только программно из прошивки, но для этого придётся — на время залить в контроллер специальный скетч. Подробно об этом можно прочитать в официальной документации по Arduino.

Если же стирается EEPROM не в Arduino плате, а в каком-то абстрактном контроллере, то код скетча нужно будет изменить с учётом размера EEPROM в конкретном контроллере на плате. Для этого нужно будет поменять условие окончания в цикле ‘For’. Например, для ATmega328, у которой 1kb памяти EEPROM, цикл будет выглядеть так:

for (int i = 0 ; i < 1024; i++) {…}

Вывод.

Я довольно долго распинался, а всё для чего? Для того, чтобы подвести к заключению о том, что при бэкапе прошивки, EEPROM тоже можно сохранить, но только в том случае если вам нужны сохранённые в нём настройки. Если же вы готовы ими пожертвовать, то забейте на это. Так же, если вы меняете одну прошивку на другую, или переходите с версии не версию, не поленитесь очистить EEPROM перед заливкой новой прошивки. Ну и заодно мы узнали много нового.

Like this post? Please share to your friends:
  • Как android изменить на iphone
  • Как abbyy finereader исправить текст
  • Как 404 ошибка влияет на позицию сайта
  • Кайрон ошибка р0600
  • Кайрон ошибка р0344