Получить доступ к EEPROM ATtiny с помощью кода Arduino?
Я пытаюсь уменьшить объем оперативной памяти, используемой моей программой, записывая некоторые значения в EEPROM моего микроконтроллера. В настоящее время я программирую на ATtiny85, который имеет 512 байт EEPROM. Согласно документации, вот как вы записываете данные в EEPROM:
#include <EEPROM.h>
void setup() {
EEPROM.write(0, 1);
EEPROM.write(1, 0);
EEPROM.write(2, 3);
EEPROM.write(3, 2);
EEPROM.write(4, 1);
}
По какой-то причине это не работает у меня, и я, похоже, не могу найти ошибку. Я программирую это неправильно, или к EEPROM ATtiny просто НЕВОЗМОЖНО получить доступ с помощью кода Arduino?
Вот таблица данных: http://www.atmel.com/Images/Atmel-2586-AVR-8-bit-Microcontroller-ATtiny25-ATtiny45-ATtiny85_Datasheet-Summary.pdf
Вот второй набросок, который я использую для тестирования EEPROM:
#include <EEPROM.h>
void setup() {
EEPROM.write(0, 1);
EEPROM.write(1, 0);
EEPROM.write(2, A3);
EEPROM.write(3, A2);
EEPROM.write(4, A1);
byte CLK = EEPROM.read(0);
}
void loop() {
if(CLK == 1)
{
for(int i = 0; i < 3; i++)
{
digitalWrite(0, HIGH);
delay(1000);
digitalWrite(0, LOW);
delay(1000);
}
exit(0);
}
else
{
for(int i = 0; i < 100; i++)
{
digitalWrite(0, HIGH);
delay(1000);
digitalWrite(0, LOW);
delay(1000);
}
exit(0);
}
exit(0);
}
@Isabel Alphonse, 👍7
Обсуждение4 ответа
Лучший ответ:
Библиотека Arduino EEPROM совместима с линейкой микроконтроллеров ATtiny AVR, поскольку сама библиотека построена на стандартной библиотеке Atmel AVR avr / eeprom.h, поэтому она совместима со всеми микроконтроллерами AVR.
EEPROM также не требует частой записи или чтения, поскольку EEPROM может изнашиваться очень быстро. Чтение, однако, не наносит большого ущерба.
Также обратите внимание, что использование exit(0);
остановит ATtiny от выполнения чего-либо еще после его вызова, поэтому я надеюсь, что ваше намерение состоит в том, чтобы запустить цикл только один раз, если нет, то это приведет либо к тому, что вы ничего не увидите, либо к тому, что цикл мигания выполняется только один раз.
Чтобы ответить на ваш последующий вопрос. Да, вы можете запустить один скетч, чтобы задать свои значения в EEPROM, а затем использовать другой скетч для их чтения. То, что мы обычно используем в EEPROM, - это тип памяти, который "сохраняет свое значение при отсутствии питания".
Также вам необходимо убедиться, что ATtiny настроен на сохранение EEPROM во время загрузки через ISP, это делается с помощью настроек fuse. Вам нужно поискать учебное пособие по калькуляторам предохранителей для AVR. Чтобы установить EESAVE
, вам нужно установить высокий предохранитель на 0xD7
, вы можете изменить это в boards.txt
досье. Вот калькулятор предохранителей.
Если используется код, который в данный момент находится в вашем вопросе, вы ничего не увидите, так как для этого нужно, чтобы выхода были установлены с помощью pinMode
. Это примечание для других, которые видят это.
Следующее, что вы можете сделать, это запустить базовый тестовый код, который мигает светодиодом без каких-либо других действий.
В основном:
void setup(){
pinMode(0, OUTPUT);
}
void loop(){
digitalWrite(0, HIGH);
delay(1000);
digitalWrite(0, LOW);
delay(1000);
}
Ниже приведен код, который вы написали, он работает, он работает у меня перед глазами. Я прокомментировал это и изменил несколько вещей, чтобы заставить его работать так, как задумано, хотя намерение неясно.
#include <EEPROM.h>
byte CLK = 0; //Это глобальная переменная с начальным значением
void setup() {
// поместите сюда свой установочный код, чтобы запустить его один раз:
EEPROM.write(0, 1); //установите PIN
delay(5);
//считывание с адреса EEPROM 0
//это устанавливает значение глобальной переменной CLK
CLK = EEPROM.read(0); //поместите это внутри функции
// просто чтобы привести пример...
byte PIN = CLK; // Переменная PIN - это локальная переменная
pinMode(PIN ,OUTPUT); //используя эту локальную переменную
}
void loop() {
// поместите сюда свой основной код для повторного запуска:
// Примечание: приведенный ниже if() всегда будет иметь значение true в качестве значения
// of CLK никогда не меняется и не должен быть изменен как
// это изменит выход вывода
if (CLK == 1) {
for (int a = 0; a < 3; a++) {
digitalWrite(CLK, HIGH); //при этом используется глобальная переменная
delay(1000);
digitalWrite(CLK, LOW);
delay(1000);
}
//ввод exit(0); фактически остановит программу
//удалить его
// выход(0);
}
else {
for (int a = 0; a < 100; a++) {
digitalWrite(0, HIGH); //для этого задан номер pin.
delay(500);
digitalWrite(0, LOW); //для этого задан номер контакта.
delay(500);
}
//ввод exit(0); фактически остановит программу
//удалить его
// выход(0);
}
}
Спасибо, это работает. Моя проблема сейчас в том, что я могу использовать только EEPROM.write();
внутри функции, и это мешает мне создать глобальную переменную, которую могут использовать все мои функции., @Isabel Alphonse
@IsabelAlphonse ??. EEPROM.write ()
является функцией и должна использоваться внутри функции. Я думаю, вам нужно начать с основ TBH. Я также думаю, что вы имеете в виду часть чтения. Я отредактировал свой ответ, чтобы включить написанный вами код, который ** работает **., @RSM
@IsabelAlphonse пожалуйста, не могли бы вы отметить один из ответов как принятый, чтобы система StackExchange не обнаружила его через несколько недель, а также чтобы другим было легче найти его при поиске той же проблемы., @RSM
Извини, я забыл., @Isabel Alphonse
Вы сказали: "EEPROM также не требует частой записи или чтения, поскольку EEPROM может изнашиваться очень быстро ". В техническом описании указано: Срок службы флэш-памяти: 10 000 циклов записи / стирания, EEPROM: 100 000 циклов записи / стирания. Таким образом, EEPROM может записываться в десять раз чаще, чем флэш-память., @needfulthing
@needfulthing В листе данных действительно говорится об этом (я должен быть исправлен, но я верю, что это для каждого адреса, следовательно, улучшение срока службы eprom достигается за счет выравнивания износа), но когда большинство людей сходят с ума, записывая на _one_ адрес eeprom, он изнашивается быстрее, чем вы изнашиваете вспышка. Большинство использует его скорее как динамическое хранилище во время работы устройства или для настройки. В то время как вспышка может никогда не достичь количества циклов чтения/стирания, когда-то выполненных вспышкой. Я просто учитываю этот факт, когда что-то делаю., @RSM
@RSM Ах, конечно, абсолютно верно в этом аспекте., @needfulthing
Когда вы загружаете новый скетч с настройками по умолчанию, EEPROM будет очищен.
"Опция -e предписывает avrdude выполнить стирание чипа перед программированием; это почти всегда необходимо перед программированием флэш-памяти".
Если вы используете Arduino IDE, опция -e включена по умолчанию. Вероятно, именно поэтому у вас это не работает.
Смотрите также вопрос, есть ли способ сохранить содержимое EEPROM в AVR Atmega при записи новой прошивки для прошивки с помощью avrdude?
Тогда, по крайней мере, мой тестовый код должен работать. Я записываю данные в EEPROM в методе настройки и после этого устанавливаю переменную CLK
. Но когда я вхожу в метод loop ()
, я все еще не могу заставить свой индикатор мигать., @Isabel Alphonse
Не уверен, что все так существенно изменилось с тех пор, как вопрос был задан изначально, но я отвечу, используя библиотеки Atmel AVR.
Не присваивайте значение EEPROM переменной, так как тогда вы снова тратите драгоценную память SRAM впустую. EEPROM имеет неограниченное количество циклов чтения.
Я не могу найти никаких текущих ссылок на EEPROM.read()
в качестве макроса или функции в Arduino IDE. Вместо этого существует библиотека AVR EEPROM, которая использует eeprom_read_byte()
, как показано ниже.
#include <avr/eeprom.h>
// процедура настройки запускается один раз, когда вы нажимаете сброс:
void setup() {
/* The "131" value is used to prevent damaging excess EEPROM writes on every restart.
If you want to try setting a different GPIO pin for LED blink change the test value in
both the read and following write to EEPROM address 511 */
if (eeprom_read_byte((uint8_t*)511) != 131) {
eeprom_write_byte((uint8_t*)511,131);
// Сохраните контакт GPIO в адресе EEPROM 1
eeprom_write_byte((uint8_t*)1,1);
};
// инициализируйте цифровой вывод в качестве выходного сигнала.
pinMode(eeprom_read_byte((uint8_t*)1), OUTPUT); // Значение вывода светодиода, сохраненное в адресе EEPROM 1
}
// процедура цикла выполняется снова и снова вечно:
void loop() {
digitalWrite(eeprom_read_byte((uint8_t*)1), HIGH);
delay(1000); // дождитесь второй
digitalWrite(eeprom_read_byte((uint8_t*)1), LOW);
delay(1000); // подождите секунду
}
Для справки, Arduino имеет библиотеку EEPROM как часть своей экосистемы. https://www.arduino.cc/en/Reference/EEPROM, @sa_leinad
возможно, ссылка есть, но в Arduino IDE 1.8.5, которую я использую здесь, если я попытаюсь использовать #include<EEPROM.H>, я получу ошибку компиляции, поэтому я опубликовал рабочий исходный код, который я сделал. C:\Windows\Users1\Users\WINDOWS\AppData\Local\Temp\arduino_modified_sketch_177973\sketch_oct24a.ino:1:20 : неустранимая ошибка: EEPROM.h: нет такого файла или каталога, @tech-head-uk
В настоящее время очень часто считывается из EEPROM в ATtiny, особенно значение OSCCAL. Кроме того, некоторые встроенные устройства выполняли избыточную запись и считывали данные во внешнюю EEPROM во время отправки. Каждый ботинок.
> ---snip---
> current tick:1 sec
> EEPROM Init...
> Write EE_TEST ==0x7cf u8EEData1=0xaa
> Read EE_TEST ==0x7cf u8EEData1=0xaa
> [EEPROM 24c16 found!]
> EEPROM: Data valid
> Restore Configuration from EEPROM to Device...
> Show MY MAC Address(from 24c16): (0x00:92:58:01:45:4d)
> _24c16_eeprom_word_read: EE_DHCPEN: (01)
> --- end snip ---
Кроме того, доступные ядра включают в себя опции для подавления стирания EEPROM при программировании, это можно использовать.
В древние времена AVRDUDE записывал количество вспышек в четыре байта, завершающихся E2END. (вариант -y).
Вам нужно включить заголовок. Вы можете проверять, просматривать и просматривать содержимое с помощью скетча или с помощью avrdude в режиме терминала (-t) с "dump ee".
И да, для Arduino Work нормально иметь выделенный временный скетч для загрузки данных EEPROM. Так что SRAM (или FLASH) не имеет значения, ФЛЭШ-памяти много по сравнению с EEPROM.
Сделайте это просто и проверьте свои результаты. В зависимости от библиотеки или ядра, лучше избегать пересечения границ страницы, поскольку адресация может обернуться вокруг начала страницы из-за 6-битного усечения, как для внешнего EEPROM I2C. Не доверяйте, проверяйте.
Предназначена ли эта запись во время загрузки для запланированного устаревания или просто для плохой практики кодирования. Если вы хотите проверить функцию хранилища, вы могли бы оставить пару байтовых подписей, которые вы считываете, вместо того, чтобы загружать EEPROM (внутренний или внешний) обычными бессмысленными записями., @KalleMP
Это было плохое кодирование. Я думаю, что это было просто оставлено в сценарии с момента разработки. Netgear, если это поможет., @mckenzm
- Альтернатива SoftwareSerial с низким объемом памяти?
- Выделение строковой памяти Arduino
- Spiffs против Eeprom на esp8266
- Как очистить кучу памяти в esp32
- Есть ли способ подключить оперативную память компьютера к Arduino?
- Последовательная печать из флэш-памяти (F() macro, PROGMEM, sprintf_P, SPTR)
- Постоянное хранилище Adafruit Trinket M0 ?
- Энергонезависимое хранение nRF52/возврат переменной-есть ли простое решение?
Хотел бы я, чтобы у меня был ATtiny, который у вас есть с ** 512 МБ ** EEPROM, он должен быть новым. Пожалуйста, взгляните на это http://arduino.stackexchange.com/help/how-to-ask, @RSM
Что не так с моим вопросом?, @Isabel Alphonse
ATtiny имеет 512 байт EEPROM, и вы также задавали аналогичный вопрос ранее. Вам нужно добавить, что вы пытались получить эти значения и как вы узнаете, что они были получены правильно. Значения eeprom были записаны правильно в приведенном выше "фрагменте". И в этом проблема, что вы не предоставили весь свой код., @RSM
Я не писал другой вопрос EEPROM. Я увидел, что вопрос остался без ответа, и решил задать свой собственный. Кроме того, мой вопрос касается способности ATtiny EEPROM программироваться с помощью Arduino. Как я уже сказал, мой код работал нормально, пока я не переключил значение на
EEPROM.read (0)
, что привело к тому, что код просто перестал работать., @Isabel AlphonseATtiny можно использовать с библиотекой EEPROM из arduino ide, по сути, это оболочка avr / eeprom.h. То, что также может убить вашу первую ячейку в EEPROM, - это многократное чтение ее в цикле. Это убивает ячейки EEPROM, они имеют ограниченные циклы чтения-записи. Кроме того, почему у вас есть
exit (0)
, @RSMСпасибо, это отличная информация. Последующий вопрос: Если я пишу в sketch с помощью команд записи, могу ли я затем получить доступ к этим значениям с помощью другого скетча? Другими словами, могу ли я разделить свою программу так, как я только что сделал в своем вопросе?, @Isabel Alphonse
пожалуйста, не могли бы вы прекратить изменять код в вопросе., @RSM
Извините, я пытался улучшить его, основываясь на ваших отзывах. Тем не менее, я понимаю, что вы пытаетесь сказать, так что спасибо, я думаю, что смогу разобраться с этим дальше., @Isabel Alphonse
ладно. Я редактирую свой ответ, добавляя немного больше материала, пожалуйста, взгляните на него., @RSM
Переместите определение
byte CLK = 0;
за пределы void setup, а затем сделайте это в void setup:CLK = EEPROM.read (0);
, @RSMПроблема в том, что если я установлю значение
CLK
внутри метода функции, я не смогу получить к нему доступ ни в одной из других функций., @Isabel Alphonse* Вот второй набросок, который я использую для тестирования EEPROM: * - нет, это не потому, что он не компилируется:
sketch_jun22a:16: ошибка: 'CLK' не был объявлен в этой области
, @Nick Gammon