void saveSecretCodeToEEPROM()
{
EEPROM.write(0, codeSetMarkerValue);
EEPROM.write(1, highByte(code));
EEPROM.write(2, lowByte(code));
}
Она записывает признак в ячейку ЭСППЗУ с адресом 0, указывающим, что в ЭСППЗУ хранится действительный шифр, и затем записывает два байта шифра. Для получения старшего и младшего байтов шифра типа int используются вспомогательные функции highByte и lowByte из стандартной библиотеки Arduino.
Использование библиотеки avr/eeprom.h
Библиотека EEPROM позволяет писать и читать данные только по одному байту. В предыдущем разделе мы обошли это ограничение, разбивая значение int на два байта перед сохранением и объединяя два байта в значение int после чтения. В качестве альтернативы, однако, можно использовать библиотеку EEPROM, предоставляемую компанией AVR, производящей микроконтроллеры. Она обладает более широкими возможностями, включая чтение и запись целых слов (16 бит) и даже блоков памяти произвольного размера.
Следующий скетч использует эту библиотеку для сохранения и чтения значения int непосредственно, увеличивая его при каждом перезапуске Arduino:
// sketch_06_07_avr_eeprom_int
#include
void setup()
{
int i = eeprom_read_word((uint16_t*)10);
i++;
eeprom_write_word((uint16_t*)10, i);
Serial.begin(9600);
Serial.println(i);
}
void loop()
{
}
Аргумент в вызове eeprom_read_word (10) и первый аргумент в вызове eeprom_write_word — это начальный адрес слова. Обратите внимание на то, что слово состоит из двух байтов, поэтому, если понадобится записать еще одно значение int, нужно будет указать адрес 12, а не 11. Конструкция (uint16_t*) перед 10 необходима, чтобы привести адрес (или индекс) к типу, ожидаемому библиотечной функцией.
Еще одна полезная пара функций в этой библиотеке — eeprom_read_block и eeprom_write_block. Эти функции позволяют сохранять и извлекать произвольные структуры данных (допустимого размера).
Например, далее приводится скетч, записывающий строку символов в ЭСППЗУ, начиная с адреса 100:
// sketch_06_07_avr_eeprom_string
#include
void setup()
{
char message[] = "I am written in EEPROM";
eeprom_write_block(message, (void *)100,
strlen(message) + 1);
}
void loop()
{
}
В первом аргументе функции eeprom_write_block передается указатель на массив символов, подлежащий записи, во втором — адрес первой ячейки в ЭСППЗУ (100). В последнем аргументе передается число байтов, которые требуется записать. Здесь это число вычисляется как длина строки плюс один байт для завершающего нулевого символа.
Ниже демонстрируется скетч, который читает строку из ЭСППЗУ и выводит ее в монитор последовательного порта вместе с числом, обозначающим длину строки:
// sketch_06_07_avr_eeprom_string_read
#include
void setup()
{
char message[50]; // буфер достаточно большого размера
eeprom_read_block(&message, (void *)100, 50);
Serial.begin(9600);
Serial.println(message);
Serial.println(strlen(message));
}
void loop()
{
}
Для чтения строки создается массив емкостью 50 символов. Затем вызывается функция eeprom_read_block, которая читает 50 символов в message. Знак & перед message указывает, что функции передается адрес массива message в ОЗУ.
Так как текст завершается нулевым символом, в монитор последовательного порта выводится только ожидаемый текст, а не все 50 символов.
Ограничения ЭСППЗУ
Операции чтения/записи с памятью ЭСППЗУ выполняются очень медленно — около 3 мс. Кроме того, надежность хранения гарантируется только для 100 000 циклов записи, после чего появляется вероятность искажения записанных данных. По этой причине старайтесь не выполнять запись в цикле.
Использование флеш-памяти
Объем флеш-памяти в Arduino намного больше, чем объем любой другой памяти. В Arduino Uno, например, объем флеш-памяти составляет 32 Кбайт против 2 Кбайт ОЗУ. Это делает флеш-память привлекательным местом для хранения данных, особенно если учесть, что она сохраняет данные после выключения питания.
Однако есть несколько препятствий, мешающих использованию флеш-памяти для хранения данных.
• Флеш-память в Arduino гарантирует сохранность данных только для 100 000 циклов записи, после чего она становится бесполезной.
• Флеш-память хранит программу, поэтому, если в расчеты вкрадется ошибка и часть программы окажется затертой данными, в скетче могут произойти невероятные события.
• Флеш-память содержит также загрузчик, уничтожение или искажение которого может превратить плату Arduino в «кирпич», после чего восстановить ее можно будет только с помощью аппаратного программатора (как описывалось в главе 2).
• Записывать данные во флеш-память можно только блоками по 64 байта.
Несмотря на все сказанное, в целом довольно безопасно использовать флеш-память для хранения постоянных данных, не изменяющихся в процессе выполнения скетча.
Читать дальше