- Библиотеки
- Операторы
- Sketch
- Управляющие операторы
- Синтаксис
- Арифметические операторы
- Операторы сравнения
- Логические операторы
- Указатели доступа
- Битовые операторы
- Составные операторы
- Данные
- Типы данных
- Преобразование типов данных
- Область видимости переменных и квалификаторы
- Утилиты
- PROGMEM
- Функции
- Цифровой ввод/вывод
- Аналоговый вход/выход
- Расширенный ввод/вывод
- Время
- Математические функции
- Тригонометрические функции
- Символы
- Случайные числа
- Биты и байты
- Внешние Прерывания
- Прерывания
- Функции передачи данных
- Функции
PROGMEM
Описание
Храните данные во флэш-памяти вместо SRAM. Есть описание различных типов памяти, доступных на плате Arduino.
Ключевое слово PROGMEM - это модификатор переменной, его следует использовать только с типами данных, определенными в pgmspace.h. Он сообщает компилятору: «Поместите эту информацию во флэш-память», а не в SRAM, куда она обычно помещается.
PROGMEM является частью библиотеки pgmspace.h. Он автоматически включается в современные версии IDE. Однако, если вы используете версию IDE ниже 1.0 (2011 г.), вам сначала нужно включить библиотеку в верхней части скетча, например:
#include <avr/pgmspace.h>
Хотя PROGMEM можно использовать с одной переменной, на самом деле это стоит суеты только в том случае, если у вас есть большой блок данных, который необходимо сохранить, что обычно проще всего в массиве (или другой структуре данных C++, выходящей за рамки нашего настоящего обсуждения).
Использование PROGMEM также представляет собой двухэтапную процедуру. После загрузки данных во флэш-память требуются специальные методы (функции), также определенные в библиотеке pgmspace.h, для чтения данных из программной памяти обратно в SRAM, чтобы мы могли сделать с ними что-нибудь полезное.
Синтаксис
const dataType variableName[] PROGMEM = {data0, data1, data3…};
Обратите внимание, что, поскольку PROGMEM является модификатором переменной, нет жесткого и быстрого правила о том, куда он должен разместиться, поэтому компилятор Arduino принимает все определения ниже, которые также являются синонимами. Однако эксперименты показали, что в различных версиях Arduino (связанных с версией GCC) PROGMEM может работать в одном месте, а не в другом. Приведенный ниже пример «таблицы строк» был протестирован для работы с Arduino 13. Более ранние версии IDE могут работать лучше, если PROGMEM будет добавлен после имени переменной.
const dataType variableName[] PROGMEM = {}; // используйте эту форму
const PROGMEM dataType variableName[] = {}; // или эту
const dataType PROGMEM variableName[] = {}; // но не эту
Пример
Следующие фрагменты кода показывают, как читать и записывать беззнаковые символы (байты) и целые числа (2 байта) в PROGMEM.
const PROGMEM uint16_t charSet[] = { 65000, 32796, 16843, 10, 11234};
const char signMessage[] PROGMEM = {"I AM PREDATOR, UNSEEN COMBATANT. CREATED BY THE UNITED STATES DEPART"};
unsigned int displayInt;
char myChar;
void setup() {
Serial.begin(9600);
while (!Serial); // wait for serial port to connect. Needed for native USB
// put your setup code here, to run once:
// read back a 2-byte int
for (byte k = 0; k < 5; k++) {
displayInt = pgm_read_word_near(charSet + k);
Serial.println(displayInt);
}
Serial.println();
// read back a char
for (byte k = 0; k < strlen_P(signMessage); k++) {
myChar = pgm_read_byte_near(signMessage + k);
Serial.print(myChar);
}
Serial.println();
}
void loop() {
// put your main code here, to run repeatedly:
}
Массивы строк
При работе с большими объемами текста, например проектом с ЖК-дисплеем, часто бывает удобно настроить массив строк. Поскольку сами строки являются массивами, это фактически пример двумерного массива.
Это, как правило, большие оператора, поэтому часто желательно поместить их в программную память. Код ниже иллюстрирует пример.
/*Демонстрация PROGMEM
Как сохранить таблицу строк в флеш память,
и получить их.
Информация взята из:
Настройка таблицы (массива) строк в памяти программы немного сложна, но
вот хороший шаблон для повторения.
Настройка строк - это двухэтапный процесс. Сначала определите строки.
*/
#include
const char string_0[] PROGMEM = "String 0"; // "String 0" и т.д. - строки для текста.
const char string_1[] PROGMEM = "String 1";
const char string_2[] PROGMEM = "String 2";
const char string_3[] PROGMEM = "String 3";
const char string_4[] PROGMEM = "String 4";
const char string_5[] PROGMEM = "String 5";
// Затем создайте таблицу, чтобы ссылаться на ваши строки.
const char *const string_table[] PROGMEM = {string_0, string_1, string_2, string_3, string_4, string_5};
char buffer[30]; // убедитесь, что достаточно для самой большой строки
void setup() {
Serial.begin(9600);
while (!Serial); // дождитесь подключения последовательного порта
Serial.println("OK");
}
void loop() {
/* Использование таблицы строк в флеш памятим требует использования специальных функций для извлечения данных.
Функция strcpy_P копирует строку из области программы в строку в ОЗУ («буфер»).
Убедитесь, что ваша строка в ОЗУ достаточно велика, чтобы вместить все,
что вы получаете из памяти. */
for (int i = 0; i < 6; i++) {
strcpy_P(buffer, (char *)pgm_read_word(&(string_table[i])));
Serial.println(buffer);
delay(500);
}
}
Примечания и предупреждения
Обратите внимание, что для работы с PROGMEM переменные должны быть определены либо глобально, либо с помощью ключевого слова static. Следующий код НЕ будет работать внутри функции:
const char long_str[] PROGMEM = "Hi, I would like to tell you a bit about myself.\n";
Следующий код БУДЕТ работать, даже если он определен локально в функции:
const static char long_str[] PROGMEM = "Hi, I would like to tell you a bit about myself.\n"
Макрос F()
Инструкция типа:
Serial.print("Write something on the Serial Monitor");
Печатаемая строка обычно сохраняется в ОЗУ. Если ваш скетч печатает много чего чарез последовательный порт, вы можете легко заполнить оперативную память. Если у вас есть свободное место во флэш-памяти, вы можете легко указать, что строка должна быть сохранена во флэш-памяти, используя синтаксис:
Serial.print(F("Write something on the Serial Monitor that is stored in FLASH"));