Микроконтроллеры AVR, на основе которых создаются платы Arduino и Genuino, обладают встроенной EEPROM: памятью, которая хранит значения переменных, пока плата выключена (подобно крошечному жесткому диску). Описываемая в данной статье библиотека позволяет считывать и записывать данные в EEPROM.
Поддерживаемые микроконтроллеры на различных платах Arduino и Genuino обладают разным размером EEPROM: 1024 байта в ATmega328, 512 байт в ATmega168 и ATmega8, 4 KB (4096 байт) в ATmega1280 и ATmega2560. Платы Arduino и Genuino 101 обладают эмуляцией EEPROM пространства размером 1024 байт.
Функции для работы с EEPROM:
read()
EEPROM.read(address)
address
: адрес ячейки для считывания, начинается с 0 (int
).byte
)./*
* EEPROM Read
*
* Считывает значение каждого байта в EEPROM и выводит его
* на компьютер.
*/
#include <EEPROM.h>
// начать чтение с первого байта (адрес 0) в EEPROM
int address = 0;
byte value;
void setup() {
// инициализировать последовательный порт и ждать,
// пока порт не будет открыт:
Serial.begin(9600);
while (!Serial) {
; // ждать подключения последовательного порта. Необходимо только для встроенного USB порта.
}
}
void loop() {
// прочитать байт из текущего адреса EEPROM
value = EEPROM.read(address);
Serial.print(address);
Serial.print("\t");
Serial.print(value, DEC);
Serial.println();
/***
Перейти к следующему адресу, или, если находимся в конце, вернуться в начало.
Большие AVR контроллеры обладают большим размером EEPROM, например:
- Arduno Duemilanove: 512b EEPROM;
- Arduino Uno: 1kb EEPROM;
- Arduino Mega: 4kb EEPROM;
Вместо жесткого прописывания размера EEPROM, лучше использовать предусмотренную
функцию определения размера.
Это сделает ваш код портируемым на все микроконтроллеры AVR.
***/
address = address + 1;
if (address == EEPROM.length()) {
address = 0;
}
/***
Поскольку размеры EEPROM являются степенями двойки, то возврат к началу EEPROM
можно было бы реализовать с помощью операции побитового И со значением (размер - 1).
++address &= EEPROM.length() - 1;
***/
delay(500);
}
write()
EEPROM.write(address, value)
address
: адрес ячейки для записи, начинается с 0 (int
).value
: значение для записи, от 0 до 255 (byte
)./*
* EEPROM Write
*
* Записывает значения, считанные с аналогового входа 0, в EEPROM.
* Эти значения будут оставаться в EEPROM, когда плата будет
* выключена, и могут быть извлечены позже при следующем запуске.
*/
#include <EEPROM.h>
/** текущий адрес в EEPROM (т.е. какой байт мы собираемся записать следующим) **/
int addr = 0;
void setup() {
/** Нет никаких начальных настроек. **/
}
void loop() {
/***
Необходимо делить на 4, так как диапазон значений на аналоговых входах
составляет от 0 до 1023, а каждый байт EEPROM может хранить значения
только от 0 до 255.
***/
int val = analogRead(0) / 4;
/***
Записать значение в соответствующий байт EEPROM.
Эти значения останутся там, когда плата будет выключена.
***/
EEPROM.write(addr, val);
/***
Перейти к следующему адресу, или, если находимся в конце, вернуться в начало.
Большие AVR контроллеры обладают большим размером EEPROM, например:
- Arduno Duemilanove: 512b EEPROM;
- Arduino Uno: 1kb EEPROM;
- Arduino Mega: 4kb EEPROM;
Вместо жесткого прописывания размера EEPROM, лучше использовать предусмотренную
функцию определения размера.
Это сделает ваш код портируемым на все микроконтроллеры AVR.
***/
addr = addr + 1;
if (addr == EEPROM.length()) {
addr = 0;
}
/***
Поскольку размеры EEPROM являются степенями двойки, то возврат к началу EEPROM
можно было бы реализовать с помощью операции побитового И со значением (размер - 1).
++addr &= EEPROM.length() - 1;
***/
delay(100);
}
update()
EEPROM.update(address, value)
address
: адрес ячейки для записи, начинается с 0 (int
).value
: значение для записи, от 0 до 255 (byte
).write()
, может сохранить время, если записываемые данные часто не меняются./***
EEPROM Update
Сохраняет значения, считанные с аналогового входа 0, в EEPROM.
Эти значения будут оставаться в EEPROM, когда плата будет
выключена, и могут быть извлечены позже при следующем запуске.
Если значение не изменилось, то EEPROM не перезаписывается,
что поможет без необходимости не сокращать срок службы EEPROM.
***/
#include <EEPROM.h>
/** текущий адрес в EEPROM (т.е. какой байт мы собираемся записать следующим) **/
int address = 0;
void setup() {
/** EMpty setup **/
}
void loop() {
/***
Необходимо делить на 4, так как диапазон значений на аналоговых входах
составляет от 0 до 1023, а каждый байт EEPROM может хранить значения
только от 0 до 255.
***/
int val = analogRead(0) / 4;
/***
Обновить конкретную ячейку EEPROM.
Эти значения останутся там при выключении платы.
***/
EEPROM.update(address, val);
/***
Функция EEPROM.update(address, val) эквивалентна следующему:
if( EEPROM.read(address) != val ){
EEPROM.write(address, val);
}
***/
/***
Перейти к следующему адресу, или, если находимся в конце, вернуться в начало.
Большие AVR контроллеры обладают большим размером EEPROM, например:
- Arduno Duemilanove: 512b EEPROM;
- Arduino Uno: 1kb EEPROM;
- Arduino Mega: 4kb EEPROM;
Вместо жесткого прописывания размера EEPROM, лучше использовать предусмотренную
функцию определения размера.
Это сделает ваш код портируемым на все микроконтроллеры AVR.
***/
address = address + 1;
if (address == EEPROM.length()) {
address = 0;
}
/***
Поскольку размеры EEPROM являются степенями двойки, то возврат к началу EEPROM
можно было бы реализовать с помощью операции побитового И со значением (размер - 1).
++addr &= EEPROM.length() - 1;
***/
delay(100);
}
get()
EEPROM.get(address, data)
address
: адрес для чтения, начинается с 0 (int
).data
: данные для чтения, могут быть примитивным типом (например, float
) или пользовательской структурой struct
./***
Чтобы предварительно записать данные в EEPROM, используйте
пример для функции put().
Можно обойтись и без этого, но значения, выводимые этим скетчем,
зависят от того, что содержится в EEPROM. Это может заставить
объект последовательного порта вывести на печать длинную строку
мусора, если в загруженной строке не будет найден нулевой символ.
***/
#include <EEPROM.h>
void setup() {
float f = 0.00f; // Переменная для хранения данных, прочитанных из EEPROM.
int eeAddress = 0; // Адрес EEPROM, откуда следует начать чтение.
Serial.begin(9600);
while (!Serial) {
; // ждать подключения последовательного порта. Необходимо только для встроенного USB порта.
}
Serial.print("Read float from EEPROM: ");
// Получить данные типа float из EEPROM в месте 'eeAddress'
EEPROM.get(eeAddress, f);
Serial.println(f, 3); // Это может напечатать 'ovf, nan', если данные в EEPROM
// не корректны для float.
/***
Так как get возвращает ссылку на 'f', вы можете использовать ее в качестве аргумента
То есть: Serial.print( EEPROM.get( eeAddress, f ) );
***/
/***
Get может использоваться и с пользовательскими структурами.
Пример с ними выделен в отдельную функцию.
***/
secondTest(); // Запустить следующий тест.
}
struct MyObject {
float field1;
byte field2;
char name[10];
};
void secondTest() {
int eeAddress = sizeof(float); // Переместить адрес к байту, следующему после float 'f'.
MyObject customVar; // Переменная для хранения данных, прочитанных из EEPROM.
EEPROM.get(eeAddress, customVar);
Serial.println("Read custom object from EEPROM: ");
Serial.println(customVar.field1);
Serial.println(customVar.field2);
Serial.println(customVar.name);
}
void loop() {
/* Пустой цикл */
}
put()
EEPROM.put(address, data)
address
: адрес для записи, начинается с 0 (int
).data
: данные для записи, могут быть примитивным типом (например, float
) или пользовательской структурой struct
. EEPROM.update()
для реализации записи, поэтому она не перезаписывает значение, если оно не изменилось./***
Этот скетч также можно использовать для предварительной
записи в EEPROM данных, используемых в примере для функции get().
Обратите внимание, что, в отличие от однобайтной версии EEPROM.write(),
функция put использует обновление. То есть байт будет записан, только
если он отличается от записанных в EEPROM данных.
***/
#include <EEPROM.h>
struct MyObject {
float field1;
byte field2;
char name[10];
};
void setup() {
Serial.begin(9600);
while (!Serial) {
; // ждать подключения последовательного порта. Необходимо только для встроенного USB порта.
}
float f = 123.456f; // Переменная для записи в EEPROM.
int eeAddress = 0; // Место, куда мы хотим положить данные.
// Простой вызов с адресом и переменной в качестве аргументов.
EEPROM.put(eeAddress, f);
Serial.println("Written float data type!");
/** Put поддерживает и пользовательские структуры. **/
//Data to store.
MyObject customVar = {
3.14f,
65,
"Working!"
};
eeAddress += sizeof(float); // Переместить адрес к байту, следующему после float 'f'.
EEPROM.put(eeAddress, customVar);
Serial.print("Written custom data type! \n\nView the example sketch eeprom_get to see how you can retrieve the values!");
}
void loop() {
/* Пустой цикл */
}
EEPROM[]
EEPROM
', как массив. Ячейки EEPROM могут быть прочитаны и записаны непосредственно с помощью этого оператора.EEPROM[address]
address
: адрес для чтения/записи, начинается с 0 (int
).#include <EEPROM.h>
void setup(){
unsigned char val;
// Прочитать первую ячейку EEPROM.
val = EEPROM[ 0 ];
// Записать первую ячейку EEPROM.
EEPROM[ 0 ] = val;
// Сравнить содержимое
if( val == EEPROM[ 0 ] ){
// Сделать что-то...
}
}
void loop(){ /* Пустой цикл */ }
Понравилась статья? Поделитесь ею с друзьями:
Вернуться в раздел: Описание функций справочника Дата публикации 21 марта , 2020
Читайте также
Комментарии
Войдите или Зарегистрируйтесь И Вы сможете общаться на форуме и оставлять комментарии без капчи.