Запись и чтение EEPROM
- Войдите на сайт для отправки комментариев
Ср, 06/04/2016 - 12:46
Добрый всем день. Начинаю потихоньку осваивать ардуино. Делаю управление на сварку и возникла небходимость в начале работы считать данные о настройках из энергонезависимой памяти (6 переменных - int, одна float). Во время работы из меню настройки эти же переменные должны быть записаны в память. Посмотрел примеры и такое наваял...
В сетапе
PRE_FLOW_M = EEPROM.read(0); OVER_FLOW_M = EEPROM.read(1); PRE_FLOW_T = EEPROM.read(2); OVER_FLOW_T = EEPROM.read(3); PRE_FLOW_P = EEPROM.read(4); OVER_FLOW_P = EEPROM.read(5); Time_Weld = EEPROM.read(6);
Действие по нажатию кнопки записи
for (int i = 0; i < 512; i++)
EEPROM.write(i, 0);
EEPROM.write(0,PRE_FLOW_M);
EEPROM.write(1,OVER_FLOW_M);
EEPROM.write(2,PRE_FLOW_T);
EEPROM.write(3,OVER_FLOW_T);
EEPROM.write(4,PRE_FLOW_P);
EEPROM.write(5,OVER_FLOW_P);
EEPROM.write(6,Time_Weld);
Данные пишет, но "левые", не те что в настройках. Где я неправ?
int - это 2 байта.... вот пример как работать:
//************************************************************************************************* // процедура читает из энерго независимой памяти двухбйтовое число // num - идентификатор памяти (номер двухбайтного слова) //************************************************************************************************* int ReadInt(int num) { byte a; byte b; int result; a = int(EEPROM.read(num * 2)); b = int(EEPROM.read(num * 2 + 1)); result = a * 255 + b; return result; } //************************************************************************************************* // процедура записывает в энерго независимую память двухбйтовое число // num - идентификатор памяти (номер двухбайтного слова) // value - записываемое значение //************************************************************************************************* void WriteInt(int num, int value) { byte a; byte b; b = value % 255; a = (value - b) / 255; EEPROM.write(num * 2, a); EEPROM.write(num * 2 + 1, b); Beep(4); // сделано для выявления безконтрольной записи и снижения ресурса EEPROM } //************************************************************************************************* // процедуры, для записи и получении всех данных EEPROM // собраны здесь для единообразного адресного хранения и визуализации карты использования EEPROM, // адреса в двух байтовом виде (1 - это два байта с физическим адресом 2 и 3) //************************************************************************************************* // ------------------- чтение ------------------- int Get_signature() { return ReadInt(0); } // 0 - сигнатура int Get_term_set() { return ReadInt(1); } // 1 - установленая температура // 2...9 - резерв int Get_temp(int Num) { return ReadInt(Num+10); } // 10..19 - массив калибровочных температур int Get_pow(int Num) { return ReadInt(Num+20); } // 20..29 - массив мощности поддержания температуры int Get_tep(int Num) { return ReadInt(Num+30); } // 30..39 - массив температур инерционности int Get_dt(int Num) { return ReadInt(Num+40); } // 40..49 - массив времени цикла on/off int Get_step(int Num) { return ReadInt(Num+50); } // 50..59 - массив времени инерционности int Get_setup(int Num){ return ReadInt(Num+60); } // 60..69 - массив флагов калибровки // 70..99 - резерв // 100..511 - свободно // ------------------- запись ------------------- int Set_signature(int value) { WriteInt(0, value); } // 0 - сигнатура int Set_term_set(int value) { WriteInt(1, value); } // 1 - установленая температура // 2...9 - резерв void Set_temp(int Num, int value) { WriteInt(Num+10, value); } // 10..19 - массив калибровочных температур void Set_pow(int Num, int value) { WriteInt(Num+20, value); } // 20..29 - массив мощности поддержания температуры void Set_tep(int Num, int value) { WriteInt(Num+30, value); } // 30..39 - массив температур инерционности void Set_dt(int Num, int value) { WriteInt(Num+40, value); } // 40..49 - массив времени цикла on/off void Set_step(int Num, int value) { WriteInt(Num+50, value); } // 50..59 - массив времени инерционности void Set_setup(int Num, int value) { WriteInt(Num+60, value); } // 60..69 - массив флагов калибровки // 70..99 - резерв // 100..511 - свободнопопробуйте так:
В сетапе
Действие по нажатию кнопки записи
for (int i = 0; i < 512; i++) {EEPROM.write(i, 0);} EEPROM.put(0,PRE_FLOW_M); EEPROM.put(2,OVER_FLOW_M); EEPROM.put(4,PRE_FLOW_T); EEPROM.put(6,OVER_FLOW_T); EEPROM.put(8,PRE_FLOW_P); EEPROM.put(10,OVER_FLOW_P); EEPROM.put(12,Time_Weld);for (int i = 0; i < 512; i++) {EEPROM.write(i, 0);}это, кстати, не обязательно и можно убрать
попробуйте так:
В сетапе
Действие по нажатию кнопки записи
for (int i = 0; i < 512; i++) {EEPROM.write(i, 0);} EEPROM.put(0,PRE_FLOW_M); EEPROM.put(2,OVER_FLOW_M); EEPROM.put(4,PRE_FLOW_T); EEPROM.put(6,OVER_FLOW_T); EEPROM.put(8,PRE_FLOW_P); EEPROM.put(10,OVER_FLOW_P); EEPROM.put(12,Time_Weld);Пишет error: 'class EEPROMClass' has no member named 'get'
Сорри, запарился... так должно работать
В сетапе
sivanko , прочитай внимательно http://arduino.ru/forum/programmirovanie/zapis-i-chtenie-eeprom-peremennykh-tipa-float-unsigned-long-long-unsigned-int
и дай размерности 7-ми переменных , которые 6 интовых и 1 флоатная :)
не парся - там всё просто....
Не понимаю, зачем все эти хитрожопости?
Ну есть же высокоуровневые макросы put и get. Так и пользуйтесь на здоровье.
нафига лезть во внутренне представление чисел, особенно если его не знаешь?
// чтение PRE_FLOW_M = EEPROM.read(0); OVER_FLOW_M = EEPROM.read(1); PRE_FLOW_T = EEPROM.read(2); OVER_FLOW_T = EEPROM.read(3); PRE_FLOW_P = EEPROM.read(4); OVER_FLOW_P = EEPROM.read(5); Time_Weld = EEPROM.read(6); // запись for (int i = 0; i < 512; i++) // не получится - разная длина полей для переменных !!!!!!!!! EEPROM.write(i, 0); EEPROM.write(0,PRE_FLOW_M); EEPROM.write(1,OVER_FLOW_M); EEPROM.write(2,PRE_FLOW_T); EEPROM.write(3,OVER_FLOW_T); EEPROM.write(4,PRE_FLOW_P); EEPROM.write(5,OVER_FLOW_P); EEPROM.write(6,Time_Weld); // покажи какие переменные интовые и какая флоатная ?Не понимаю, зачем все эти хитрожопости?
Ну есть же высокоуровневые макросы put и get. Так и пользуйтесь на здоровье.
нафига лезть во внутренне представление чисел, особенно если его не знаешь?
а не лучше ли именно изучить внутренне представление чисел и писать-читать что нам угодно ?
моя искренне удивлён Вашему посту :)-
// чтение PRE_FLOW_M = EEPROM.read(0); OVER_FLOW_M = EEPROM.read(1); PRE_FLOW_T = EEPROM.read(2); OVER_FLOW_T = EEPROM.read(3); PRE_FLOW_P = EEPROM.read(4); OVER_FLOW_P = EEPROM.read(5); Time_Weld = EEPROM.read(6); // запись for (int i = 0; i < 512; i++) // не получится - разная длина полей для переменных !!!!!!!!! EEPROM.write(i, 0); EEPROM.write(0,PRE_FLOW_M); EEPROM.write(1,OVER_FLOW_M); EEPROM.write(2,PRE_FLOW_T); EEPROM.write(3,OVER_FLOW_T); EEPROM.write(4,PRE_FLOW_P); EEPROM.write(5,OVER_FLOW_P); EEPROM.write(6,Time_Weld); // покажи какие переменные интовые и какая флоатная ?Последняя - флоат
ЕвгенийП , извини , но я не знаю .get и .put , к сожалению.....
эти методы умееют сами вычислять смещение в зависимости от типа переменной ?
мне проще всё рассчитать - где что - потом читать-записывать....
в чём преимущество .get и .put ?
спасибо :)
// чтение PRE_FLOW_M = EEPROM.read(0); OVER_FLOW_M = EEPROM.read(1); PRE_FLOW_T = EEPROM.read(2); OVER_FLOW_T = EEPROM.read(3); PRE_FLOW_P = EEPROM.read(4); OVER_FLOW_P = EEPROM.read(5); Time_Weld = EEPROM.read(6); // запись for (int i = 0; i < 512; i++) // не получится - разная длина полей для переменных !!!!!!!!! EEPROM.write(i, 0); EEPROM.write(0,PRE_FLOW_M); EEPROM.write(1,OVER_FLOW_M); EEPROM.write(2,PRE_FLOW_T); EEPROM.write(3,OVER_FLOW_T); EEPROM.write(4,PRE_FLOW_P); EEPROM.write(5,OVER_FLOW_P); EEPROM.write(6,Time_Weld); // покажи какие переменные интовые и какая флоатная ?Последняя - флоат
ты не учёл смещение адресов в зависимости от типа переменной....
...и не прочитал ссылку , скорее всего
пока советовать не буду....
...жду решения сэнсея :)
а не лучше ли именно изучить внутренне представление чисел и писать-читать что нам угодно ?
А какова цель? Изучить внутренне представление чисел? Тогда, конечно лучше. А если цель - сделать проект, так лучше пользовать эти макросы и писать/читать всё, что нам угодно - они понимают любые типы данных, включая стуктуры и классы. Единствееное, что надо помнить, если тип - указатель, то они указатель и запишут, а вовсе не содержимое.
по идее они кросс платформеные, то есть не зависящие от физической длины типов... все это в теории и на ПК хорошо, но на узкозаточеном софте только накладные расходы....
я вообще рекомендую для каждой конекретной переменной делать отделную функцию получения и записи, и в них прописывать смещение (такой пример я привел выше) это вполне оправдано в иделогии ООП где физические данные спрятаны за "свойствами" и вполне оправдано для небольшого количества данных, это повышает и читабельность и уменьшает вероятность ошибок...
МНЕ ПРОЩЕ И ПОНЯТНЕЕ ТАК :
это если у тебя чтение и запись только в одном месте... а попробуй сделай чтение в 5 разных местах... вот тут и задумаешся...
а не лучше ли именно изучить внутренне представление чисел и писать-читать что нам угодно ?
А какова цель? Изучить внутренне представление чисел? Тогда, конечно лучше. А если цель - сделать проект, так лучше пользовать эти макросы и писать/читать всё, что нам угодно - они понимают любые типы данных, включая стуктуры и классы. Единствееное, что надо помнить, если тип - указатель, то они указатель и запишут, а вовсе не содержимое.
Спасибо !
в #16 мой код....
твой можно ?
посредством .get и .put - для сравнения-понимания ?
я вовсе не спорщик :)
это если у тебя чтение и запись только в одном месте... а попробуй сделай чтение в 5 разных местах... вот тут и задумаешся...
дык , примером можешьминя убить ?
шутка.... пока не изучил эти методы - я тупой !
спасибо
а не лучше ли именно изучить внутренне представление чисел и писать-читать что нам угодно ?
А какова цель? Изучить внутренне представление чисел? Тогда, конечно лучше. А если цель - сделать проект, так лучше пользовать эти макросы и писать/читать всё, что нам угодно - они понимают любые типы данных, включая стуктуры и классы. Единствееное, что надо помнить, если тип - указатель, то они указатель и запишут, а вовсе не содержимое.
Спасибо !
в #16 мой код....
твой можно ?
посредством .get и .put - для сравнения-понимания ?
я вовсе не спорщик :)
мой код http://arduino.ru/forum/programmirovanie/zapis-i-chtenie-eeprom#comment-184477
это если у тебя чтение и запись только в одном месте... а попробуй сделай чтение в 5 разных местах... вот тут и задумаешся...
согласен..... до таких задач ещё не дошёл.....
но ведь можно для каждой переменной прописать адрес через #define и использовать ?
ЕвгенийП , извини , но я не знаю .get и .put , к сожалению.....
эти методы умееют сами вычислять смещение в зависимости от типа переменной ?
мне проще всё рассчитать - где что - потом читать-записывать....
в чём преимущество .get и .put ?
спасибо :)
Смещение не умеют. Адреса надо задавть самому.
Преимущество их в том, что они единообразно работают с любыми типами данных.
Например:
#include <EEPROM.h> // // имеем конфигурацию нашей супер-пупер программы // struct MySuperPuperProgramConfig { double voltage; int amount; char IPAddr[15]; uint8_t pin_Number; } my_config; // // Кроме конфигурации в EEPROM ещё сидит // 1) какая-фигня 64-битная целая // 2) какая-то хрень типа double // long long figna; double hren; // // Задаём адреса в EEPROM // #define START_ADDRESS 4 #define CONFIG_ADDRESS START_ADDRESS #define FIGNA_ADDRESS (CONFIG_ADDRESS + sizeof(my_config)) #define HREN_ADDRESS (FIGNA_ADDRESS + sizeof(figna)) // // Вот так читаем // void readAll(void) { EEPROM.get(CONFIG_ADDRESS, my_config); EEPROM.get(FIGNA_ADDRESS, figna); EEPROM.get(HREN_ADDRESS, hren); } // // Вот так пишем // void storeAll(void) { EEPROM.put(CONFIG_ADDRESS, my_config); EEPROM.put(FIGNA_ADDRESS, figna); EEPROM.put(HREN_ADDRESS, hren); }Заметьте, мы пишем и читаем одинаково, независимо от того, что там - сверхдлинное целое, плавающее или разлапистая структура. И в этом и есть ценность метода!
Да, кстати, а если читать/писать надо побайтно, то почему не использовать EEPROM как массив? Вот так:
Разве это не читабельнее, чем использовать отдельные функции,
это если у тебя чтение и запись только в одном месте... а попробуй сделай чтение в 5 разных местах... вот тут и задумаешся...
согласен..... до таких задач ещё не дошёл.....
но ведь можно для каждой переменной прописать адрес через #define и использовать ?
это вопросы архитектора, именно он должен закладывать масштабируемость решений в будущем. То есть сейчас вроде и не нужно, но все равно делаем с прицелом, что через 3 года будем расширять, и вот тогда все будет просто и понятно....
опытные программисты сами так делают, новичкам обычно такие вещи возвращают на переделку....
ЕвгенийП , извини , но я не знаю .get и .put , к сожалению.....
эти методы умееют сами вычислять смещение в зависимости от типа переменной ?
мне проще всё рассчитать - где что - потом читать-записывать....
в чём преимущество .get и .put ?
спасибо :)
Смещение не умеют. Адреса надо задавть самому.
Преимущество их в том, что они единообразно работают с любыми типами данных.
Например:
#include <EEPROM.h> // // имеем конфигурацию нашей супер-пупер программы // struct MySuperPuperProgramConfig { double voltage; int amount; char IPAddr[15]; uint8_t pin_Number; } my_config; // // Кроме конфигурации в EEPROM ещё сидит // 1) какая-фигня 64-битная целая // 2) какая-то хрень типа double // long long figna; double hren; // // Задаём адреса в EEPROM // #define START_ADDRESS 4 #define CONFIG_ADDRESS START_ADDRESS #define FIGNA_ADDRESS (CONFIG_ADDRESS + sizeof(my_config)) #define HREN_ADDRESS (FIGNA_ADDRESS + sizeof(figna)) // // Вот так читаем // void readAll(void) { EEPROM.get(CONFIG_ADDRESS, my_config); EEPROM.get(FIGNA_ADDRESS, figna); EEPROM.get(HREN_ADDRESS, hren); } // // Вот так пишем // void storeAll(void) { EEPROM.put(CONFIG_ADDRESS, my_config); EEPROM.put(FIGNA_ADDRESS, figna); EEPROM.put(HREN_ADDRESS, hren); }Заметьте, мы пишем и читаем одинаково, независимо от того, что там - сверхдлинное целое, плавающее или разлапистая структура.
Да, кстати, а если читать/писать надо побайтно, то почему не использовать EEPROM как массив? Вот так:
Разве это не читабельнее, чем использовать отдельные функции,
согласен....
но ты же в дефайнах прописал смещение !
по моему - это тоже самое что прописать каждой переменной свой адрес дефайново,
а смещение можно задать всегда....
...это я сам с собом - тибя надо вдумчиво читать.....
не согласен - figna...... не читается....
fignja или fu....ja - тибе виднее , твои переменные.....
спасибо обоим !!!!!! пойду "курить"
Заметьте, мы пишем и читаем одинаково, независимо от того, что там - сверхдлинное целое, плавающее или разлапистая структура. И в этом и есть ценность метода!
воооооот , сформулировал вопрос - а ты уже и отвечал.....
метод пишет-читает любой тип !
а следующий свободный адрес он не вычисляет же ? надопросчитать ручками ? так ?
Пробовал с get и put.... Ругается на get
это если у тебя чтение и запись только в одном месте... а попробуй сделай чтение в 5 разных местах... вот тут и задумаешся...
согласен..... до таких задач ещё не дошёл.....
но ведь можно для каждой переменной прописать адрес через #define и использовать ?
это вопросы архитектора, именно он должен закладывать масштабируемость решений в будущем. То есть сейчас вроде и не нужно, но все равно делаем с прицелом, что через 3 года будем расширять, и вот тогда все будет просто и понятно....
опытные программисты сами так делают, новичкам обычно такие вещи возвращают на переделку....
спасибо :)
мине переделывать-то нечего :(
так - для знакомых чёта кодю....
Пробовал с get и put.... Ругается на get
молодец что вернулся , а то подумал что я как слон в посудной лавке :)
та тута я
Пробовал с get и put.... Ругается на get
Версия IDE? Это появилось не так давно. В 1.6.5 точно есть
вот и я истчЮ....
http://arduino.ru/Reference/Library/EEPROM
нету там такого :(
вычисляет же ? надопросчитать ручками ? так ?
Нет, не вычисляет. Можно присобачить самому, только зачем?
Упрщение здесь не за счёт адреса, а за счёт того, не надо побайтово читать числа или там масивы - сам прочитает.
1.0.5
Щас попробую поновее
вот и я истчЮ....
http://arduino.ru/Reference/Library/EEPROM
нету там такого :(
Ну, Вы нашли где искать. Здесь со времён всемирного потопа ничего не менялось.
Смотрите на официальном сайте - https://www.arduino.cc/en/Reference/EEPROM
вычисляет же ? надопросчитать ручками ? так ?
Нет, не вычисляет. Можно присобачить самому, только зачем?
Упрщение здесь не за счёт адреса, а за счёт того, не надо побайтово читать числа или там масивы - сам прочитает.
твоя экспертная оценка - мой код имеет место быть ? ( так , для самоуспокоения )
главный вопрос :
ведь можно же прописать функцию записи в EEPROM , например структуры , со входными параметрами
адрес ( куда писать ) и ссылка на структуру ( что писать ) ?
CPP могуч же ?
спасибо
вот и я истчЮ....
http://arduino.ru/Reference/Library/EEPROM
нету там такого :(
Ну, Вы нашли где искать. Здесь со времён всемирного потопа ничего не менялось.
Смотрите на официальном сайте - https://www.arduino.cc/en/Reference/EEPROM
пардон ! вроде бы пэнсионеры договаривались на ТЫ ?
извините....
там не был - спасибо ! :)
твоя экспертная оценка - мой код имеет место быть ? ( так , для самоуспокоения )
Конечно имеет, а чего не имеет-то?
главный вопрос :
ведь можно же прописать функцию записи в EEPROM , например структуры , со входными параметрами
адрес ( куда писать ) и ссылка на структуру ( что писать ) ?
CPP могуч же ?
спасибо
Можно, конечно, но это не соответсвуюет духу языка. Для структуры (как и для любого другого класса) правильнее написать не внешнюю функцию, а метод. Тогда параметром будет только адрес. Что писать - и так понятно.
Такой подход более универсальный, чем тот макрос, который я тут рекламировал потому, что он определяет не только что и куда писать, а заодно и "как писать".
Последнее важно. Помните мой пример с указателем? Так вот в методе можно это отрабоать, чтобы писалось именно то, что реально нужно. Ну и вообще, половина полей структуры, возможно, не нуждается в постоянном хранении. Т.е. методы чтения/записи в структуре/классе как раз бы и определелил что и как надо записывать или считывать.
P.S. Вы меня с кем-то путаете, я никогда ни с кем не договаривался о переходе на ты. Я этого никогда не делаю. На ты я называю своих родственников и ближайших друзей (таковой у меня ровно один) и больше никого.
твоя экспертная оценка - мой код имеет место быть ? ( так , для самоуспокоения )
Конечно имеет, а чего не имеет-то?
главный вопрос :
ведь можно же прописать функцию записи в EEPROM , например структуры , со входными параметрами
адрес ( куда писать ) и ссылка на структуру ( что писать ) ?
CPP могуч же ?
спасибо
Можно, конечно, но это не соответсвуюет духу языка. Для структуры (как и для любого другого класса) правильнее написать не внешнюю функцию, а метод. Тогда параметром будет только адрес. Что писать - и так понятно.
Такой подход более универсальный, чем тот макрос, который я тут рекламировал потому, что он определяет не только что и куда писать, а заодно и "как писать".
Последнее важно. Помните мой пример с указателем? Так вот в методе можно это отрабоать, чтобы писалось именно то, что реально нужно. Ну и вообще, половина полей структуры, возможно, не нуждается в постоянном хранении. Т.е. методы чтения/записи в структуре/классе как раз бы и определелил что и как надо записывать или считывать.
P.S. Вы меня с кем-то путаете, я никогда ни с кем не договаривался о переходе на ты. Я этого никогда не делаю. На ты я называю своих родственников и ближайших друзей (таковой у меня ровно один) и больше никого.
спасибо и извините....
Последнее важно. Помните мой пример с указателем? Так вот в методе можно это отрабоать, чтобы писалось именно то, что реально нужно. Ну и вообще, половина полей структуры, возможно, не нуждается в постоянном хранении. Т.е. методы чтения/записи в структуре/классе как раз бы и определелил что и как надо записывать или считывать.
Тут понятно.... спасибо Вашим урокам !
Пока крайний вопрос :
если пишем предельное кол-во раз в адрес 10 , например....
то откажет память по адресу 10 или ВСЯ EEPROM ?
если пишем предельное кол-во раз в адрес 10 , например....
то откажет память по адресу 10 или ВСЯ EEPROM ?
Сам бы хотел знать. Но я не электронщик ни разу, а только программист :(
Надеюсь, кто-нибудь ответит. А если нет, завтра буду на работе, там есть у кого спросить - отпишусь.
если пишем предельное кол-во раз в адрес 10 , например....
то откажет память по адресу 10 или ВСЯ EEPROM ?
Сам бы хотел знать. Но я не электронщик ни разу, а только программист :(
Надеюсь, кто-нибудь ответит. А если нет, завтра буду на работе, там есть у кого спросить - отпишусь.
зависит от реализации флеша, в ардуинке скорее всего вся память прейдет в режим Read-Only...
Ура, я победил проблему. Обновил ИДЕ, дал адреса 10, 20,30... чтобы с запасом. Использовал get и put. И все заработало!!! Спасибо всем откликнувшимся.
П.С. Почему я не знал про ардуино 3 года назад, когда делал сварку-полуавтомат. Теперь будет 4 в 1 (MMA, MIG, TIG и плазморез в одном флаконе) под управлением ардуинки.
если пишем предельное кол-во раз в адрес 10 , например....
то откажет память по адресу 10 или ВСЯ EEPROM ?
Сам бы хотел знать. Но я не электронщик ни разу, а только программист :(
Надеюсь, кто-нибудь ответит. А если нет, завтра буду на работе, там есть у кого спросить - отпишусь.
зависит от реализации флеша, в ардуинке скорее всего вся память прейдет в режим Read-Only...
Не. Одна ячейка глючить начнет.
С ЕЕПРОМ работаю так.
В проекте есть структура данных для ЕЕПРОМ, наприме (из живого проекта выдрано) Она глобальная, в проекте одна и имя фиксированое, описывает весь ЕЕПРОМ, который использован.
typedef struct EEPROM_STUCT { OneWareDevID DevID[EEPROM_STUCT_DEV_ID_NUMBER]; TimerInterval TimerIntervals[EEPROM_STUCT_TIMER_INTERVALS_NUMBER]; byte ExtOutValueON[EEPROM_STUCT_EXT_OUT_NUMBER]; //уровень ШИМ при включенном состоянии byte ExtOutTimersMask[EEPROM_STUCT_EXT_OUT_NUMBER]; byte ExtOutOptions[EEPROM_STUCT_EXT_OUT_NUMBER]; //набор флагов, определяющих специфику устройства } ;В библиотеках макросы и функции
#define offsetof(st, m) ((size_t)(&((st *)0)->m)) #define EEPROM(a) ((byte)offsetof(EEPROM_STUCT,a)) #define EEPROM_WRITE(adr,val) WriteBlockToEEPROM(EEPROM(adr), &val, sizeof(val)); #define EEPROM_READ(adr,val) ReadBlockFromEEPROM(EEPROM(adr), &val, sizeof(val)); //******************************************************************************************* // Блочная работа с EEPROM boolean ReadBlockFromEEPROM(byte adr, void* d, byte l) { byte t; byte res=true; for(byte i=0;i<l;i++,adr++) { t=EEPROM.read(adr); if(d) ((byte*)d)[i]=t; if (t!=0xff) res= false; } return res; } void WriteBlockToEEPROM(byte adr, void* d, byte l) { for(byte i=0;i<l;i++,adr++) { if(EEPROM.read(adr)!=((byte*)d)[i]) EEPROM.write(adr,((byte*)d)[i]); } }Обратите внимание, что чтение возвращает true если вся переменная в 0xff. Это означает что переменная не инициализирована или свободн, соответственно имеем заодно и поиск незанятой записи. Запись с проверкой необходимости её, это достаточно быстро и позволяет не парится с износом памяти при частом перезаписывании.
Ну и работа типа
byte opt; EEPROM_READ(ExtOutOptions[SelectOutDevID], opt); opt&=~EXT_OUT_OPT_SMOOTHLY; EEPROM_WRITE(ExtOutOptions[SelectOutDevID], opt);О, кстати спрошу тоже: EEPROM имеет ограничение типа в 100тыс. записей .. Флеш, по сути такая же "еепром", но в ТТХ на микросхемы почему-то прописано только 10тыс. циклов, что несколько напрягает (меня конкретно, ибо обучение и заливок много).
Это "перестраховка" производителя и на самом деле теже 100тыс (как и на отдельных микросхемах флеш-памяти) или таки на порядок меньше по каким-то причинам? Уже год задаюсь этим вопросом и не могу найти ответ .. может подскажете?
А, если флеш память дунек тоже держит 100тыщ .. то почему её тоже не пользовать как еепром? Команды чтения-записи есть .. можно же писать "самомодифицирующийся код" по идее .. не?
Это "перестраховка" производителя и на самом деле теже 100тыс
Представитель Atmel в России ответил, что нет, действительно: с гарантией 10 тыс.
Другое дело, что если в среднем по заливке в день, то это 27 лет! А оно ведь так и бывает в какой-то день 10 заливок, а какие-то ни одной.
Упс..
Это "перестраховка" производителя и на самом деле теже 100тыс
Представитель Atmel в России ответил, что нет, действительно: с гарантией 10 тыс.
Другое дело, что если в среднем по заливке в день, то это 27 лет! А оно ведь так и бывает в какой-то день 10 заливок, а какие-то ни одной.
Не так уж и много. Если активно отлаживается то и десяток заливок в час да на 5 часов и каждый день и сдохнет за полгода. Дабы не допускать такого периодически любымый отладочный отправляется в изделие а его место новый занимает.
Если активно отлаживается то и десяток заливок в час да на 5 часов
А думать когда? Или "не наш метод"? :)))))))
я ж написал отлаживать 5 часов! Дольше нельзя и не получится. Думать 24-5=19 часов. "Элементарно Ватсон" ;))
я ж написал отлаживать 5 часов! Дольше нельзя и не получится. Думать 24-5=19 часов. "Элементарно Ватсон" ;))
Понято, значит 5 часов дрыганий в стиле "чё думать, трясти надо!", а потом на диван и думатель включать! :)))))
Именно так. Идеи рождаются не за компом. За компом они оформляются в код и 5 часов на то чтоб добится соответствия реализации и замысла как раз. Вобще реально рабочий день разработчика ПО 4-5 часов, это уже сто раз обсуждалось. А думать он не перестает все 19 часов. )))