- Любовные романы
- Фантастика и фэнтези
- Ненаучная фантастика
- Ироническое фэнтези
- Научная Фантастика
- Фэнтези
- Ужасы и Мистика
- Боевая фантастика
- Альтернативная история
- Космическая фантастика
- Попаданцы
- Юмористическая фантастика
- Героическая фантастика
- Детективная фантастика
- Социально-психологическая
- Боевое фэнтези
- Русское фэнтези
- Киберпанк
- Романтическая фантастика
- Городская фантастика
- Технофэнтези
- Мистика
- Разная фантастика
- Иностранное фэнтези
- Историческое фэнтези
- LitRPG
- Эпическая фантастика
- Зарубежная фантастика
- Городское фентези
- Космоопера
- Разное фэнтези
- Книги магов
- Любовное фэнтези
- Постапокалипсис
- Бизнес
- Историческая фантастика
- Социально-философская фантастика
- Сказочная фантастика
- Стимпанк
- Романтическое фэнтези
- Ироническая фантастика
- Детективы и Триллеры
- Проза
- Юмор
- Феерия
- Новелла
- Русская классическая проза
- Современная проза
- Повести
- Контркультура
- Русская современная проза
- Историческая проза
- Проза
- Классическая проза
- Советская классическая проза
- О войне
- Зарубежная современная проза
- Рассказы
- Зарубежная классика
- Очерки
- Антисоветская литература
- Магический реализм
- Разное
- Сентиментальная проза
- Афоризмы
- Эссе
- Эпистолярная проза
- Семейный роман/Семейная сага
- Поэзия, Драматургия
- Приключения
- Детская литература
- Загадки
- Книга-игра
- Детская проза
- Детские приключения
- Сказка
- Прочая детская литература
- Детская фантастика
- Детские стихи
- Детская образовательная литература
- Детские остросюжетные
- Учебная литература
- Зарубежные детские книги
- Детский фольклор
- Буквари
- Книги для подростков
- Школьные учебники
- Внеклассное чтение
- Книги для дошкольников
- Детская познавательная и развивающая литература
- Детские детективы
- Домоводство, Дом и семья
- Юмор
- Документальные книги
- Бизнес
- Работа с клиентами
- Тайм-менеджмент
- Кадровый менеджмент
- Экономика
- Менеджмент и кадры
- Управление, подбор персонала
- О бизнесе популярно
- Интернет-бизнес
- Личные финансы
- Делопроизводство, офис
- Маркетинг, PR, реклама
- Поиск работы
- Бизнес
- Банковское дело
- Малый бизнес
- Ценные бумаги и инвестиции
- Краткое содержание
- Бухучет и аудит
- Ораторское искусство / риторика
- Корпоративная культура, бизнес
- Финансы
- Государственное и муниципальное управление
- Менеджмент
- Зарубежная деловая литература
- Продажи
- Переговоры
- Личная эффективность
- Торговля
- Научные и научно-популярные книги
- Биофизика
- География
- Экология
- Биохимия
- Рефераты
- Культурология
- Техническая литература
- История
- Психология
- Медицина
- Прочая научная литература
- Юриспруденция
- Биология
- Политика
- Литературоведение
- Религиоведение
- Научпоп
- Психология, личное
- Математика
- Психотерапия
- Социология
- Воспитание детей, педагогика
- Языкознание
- Беременность, ожидание детей
- Транспорт, военная техника
- Детская психология
- Науки: разное
- Педагогика
- Зарубежная психология
- Иностранные языки
- Филология
- Радиотехника
- Деловая литература
- Физика
- Альтернативная медицина
- Химия
- Государство и право
- Обществознание
- Образовательная литература
- Учебники
- Зоология
- Архитектура
- Науки о космосе
- Ботаника
- Астрология
- Ветеринария
- История Европы
- География
- Зарубежная публицистика
- О животных
- Шпаргалки
- Разная литература
- Зарубежная литература о культуре и искусстве
- Пословицы, поговорки
- Боевые искусства
- Прочее
- Периодические издания
- Фанфик
- Военное
- Цитаты из афоризмов
- Гиды, путеводители
- Литература 19 века
- Зарубежная образовательная литература
- Военная история
- Кино
- Современная литература
- Военная техника, оружие
- Культура и искусство
- Музыка, музыканты
- Газеты и журналы
- Современная зарубежная литература
- Визуальные искусства
- Отраслевые издания
- Шахматы
- Недвижимость
- Великолепные истории
- Музыка, танцы
- Авто и ПДД
- Изобразительное искусство, фотография
- Истории из жизни
- Готические новеллы
- Начинающие авторы
- Спецслужбы
- Подростковая литература
- Зарубежная прикладная литература
- Религия и духовность
- Старинная литература
- Справочная литература
- Компьютеры и Интернет
- Блог
Программируем Arduino. Основы работы со скетчами - Монк Саймон
Шрифт:
Интервал:
Закладка:
{
byte high = EEPROM.read(1);
byte low = EEPROM.read(2);
return (high << 8) + low;
}
Эта функция читает двухбайтный шифр типа int из байтов с адресами 1 и 2 в ЭСППЗУ (рис. 6.5).

Рис. 6.5. Хранение значения типа int в ЭСППЗУ
Чтобы из двух отдельных байтов получить одно значение int, нужно сдвинуть старший байт влево на 8 двоичных разрядов (high << 8) и затем прибавить младший байт.
Чтение хранимого кода из ЭСППЗУ выполняется только в случае сброса платы Arduino. Но запись шифра в ЭСППЗУ должна выполняться при каждом его изменении, чтобы после выключения или сброса Arduino шифр сохранился в ЭСППЗУ и мог быть прочитан в момент запуска скетча.
За запись отвечает функция saveSecretCodeToEEPROM:
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 <avr/eeprom.h>
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 <avr/eeprom.h>
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 <avr/eeprom.h>
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 байта.
Несмотря на все сказанное, в целом довольно безопасно использовать флеш-память для хранения постоянных данных, не изменяющихся в процессе выполнения скетча.
Для платы Arduino Due была создана сторонняя библиотека, позволяющая выполнять операции чтения/записи с флеш-памятью, чтобы компенсировать отсутствие ЭСППЗУ в этой модели. Более полную информацию об этом проекте можно получить по адресу http://pansenti.wordpress.com/2013/04/19/simple-flash-library-for-arduino-due/.
Самый простой способ создать строковую константу, хранящуюся во флеш-памяти, — использовать функцию F, упоминавшуюся в одном из предыдущих разделов. Напомню ее синтаксис:
Serial.println(F("Program Started"));
Этот прием работает только при использовании строковых констант непосредственно в вызове функции вывода. Нельзя, например, присвоить результат указателю на тип char.
Более гибкий, но более сложный способ заключается в использовании директивы PROGMEM (Program Memory — память программы) для сохранения любых структур данных. Однако данные должны быть постоянными — они не могут изменяться в процессе выполнения сценария.
Следующий пример иллюстрирует, как можно определить массив целых чисел (int), хранящийся во флеш-памяти:
// sketch_06_10_PROGMEM_array
#include <avr/pgmspace.h>
PROGMEM int value[] = {10, 20, 25, 25, 20, 10};
void setup()
{
Serial.begin(9600);
for (int i = 0; i < 6; i++)
{
int x = pgm_read_word(&value[i]);
Serial.println(x);
}
}
void loop()
{
}
Директива PROGMEM перед объявлением массива гарантирует, что он будет храниться только во флеш-памяти. Но прочитать значение элемента из такого массива можно только с помощью функции pgm_read_word из библиотеки avr/pgmspace:
int x = pgm_read_word(&value[i]);
Символ & перед именем массива в параметре указывает, что функции передается адрес данного элемента массива во флеш-памяти, а не его значение.

