PROGMEM
Справка Язык | Библиотеки | Сравнение | Изменения
PROGMEM
Описание
Указывает, что содержимое переменной должны быть размещено в памяти программ (flash), а не в оперативной памяти данных SRAM.
Ключевое слово PROGMEM - модификатор объявления переменной и может использоваться только для типов из pgmspace.h. Оно указывает компилятору, что переменная будет расположена в постоянной памяти программ (flash), а не как обычно - в оперативной памяти SRAM.
PROGMEM - часть библиотеки pgmspace.h. Поэтому, сначала надо подключить ее к скетчу, добавив в самом начале директиву include:
#include <avr/pgmspace.h>
Синтаксис
const dataType variableName[] PROGMEM = {data0, data1, data3...};
где:
- dataType - тип переменной
- variableName - имя переменной с массивом данных
Помните, что поскольку PROGMEM является лишь модификатором, нет жесткого правила, где именно его указывать в объявлении переменной, и поэтому компилятор воспримет все нижеперечисленные варианты как синонимы. Однако экспериментальным путем выявлено, что в разных версиях ArduinoIDE (в зависимости от версии GCC), PROGMEM может работать в одном месте и не работать в другом. Пример "таблица строк" был протестирован с Arduino 13. Более ранние версии IDE могут потребовать указания PROGMEM после имени переменной.
const dataType variableName[] PROGMEM = {}; const PROGMEM dataType variableName[] = {}; const dataType PROGMEM variableName[] = {};
Действие PROGMEM распространяется только на одну переменную, поэтому часто к ней прибегают для объявления больших блоков данных, которые наиболее удобно представлять в виде массива.
Использование PROGMEM предполагает также, что для обращения к таким переменным также требуются специальные функции (также определены в pgmspace.h).
Примеры
Этот код иллюстрирует как читать и выводить символы (байты) и целые (2-х байтные) из PROGMEM.
#include <avr/pgmspace.h> // сохранить несколько беззнаковых целых 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; int k; // переменная-счетчик char myChar; void setup() { Serial.begin(9600); while (!Serial); // чтение 2-байтных целых for (k = 0; k < 5; k++) { displayInt = pgm_read_word_near(charSet + k); Serial.println(displayInt); } Serial.println(); // чтение символов for (k = 0; k < strlen(signMessage); k++) { myChar = pgm_read_byte_near(signMessage + k); Serial.print(myChar); } Serial.println(); } void loop() { }
Массивы строк
При работе с большими объемами текста, например в проектах с LCD-дисплеями, часто бывает удобно применять массивы строк. Поскольку строка сама по себе является массивом, в приведенном ниже примере используется двумерный массив символов.
Поскольку размер памяти SRAM весьма ограничен, желательно размещать любые большие объемы констант в памяти программ, что также иллюстрирует этот код.
/* Пример PROGMEM string Показывает, как разместить таблицу строк в памяти программ (flash), а затем прочитать её. Информация получена на основе: http://www.nongnu.org/avr-libc/user-manual/pgmspace.html Размещение таблиц (массивов) строк в памяти программ немного усложнено, но это хороший шаблон для применения. Первый шаг: определение строк. */ #include <avr/pgmspace.h> 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 копирует строку из памяти программ в память данных (буфер в RAM). Убедитесь, что принимаемая в буфер строка никогда не превысит размер самого буфера! */ for (int i = 0; i < 6; i++) { strcpy_P(buffer, (char*)pgm_read_word(&(string_table[i]))); // Необходимые преобразования типов для корректного разыменовывания. Просто скопируйте. Serial.println(buffer); delay( 500 ); } }
Смотри также
Исправления, пожелания и новые статьи должны быть опубликованы через Форум.
Оригинальные тексты руководств и переводы распространяются Arduino и MK90 на условиях лицензии Creative Commons Attribution-ShareAlike 3.0 License. Примеры исходных кодов и ссылки являются общественным достоянием.