PROGMEM

Документація

PROGMEM


Зберігайте дані у флеш-пам’яті (програмній) замість SRAM. Опис типів пам’яті, що використовується платами Arduino, на сторінці типи пам’яті.

Ключове слово PROGMEM — це модифікатор змінної, який має використовуватися лише з типами даних, визначеними командою pgmspace.h. Вона каже компілятору “помістити цю інформацію у флеш-пам’ять” замість SRAM, куди вона була б спрямована за звичайних умов.

PROGMEM є частиною бібліотеки pgmspace.h, яка доступна лише в архітектурі AVR. Тому спершу слід включити бібліотеки на початку скетчу:

#include <avr/pgmspace.h>

Синтаксис

const dataType variableName[] PROGMEM = {data0, data1, data3...};


dataType — будь-який тип змінної

variableName — ім’я масиву даних

Зверніть увагу, що оскільки PROGMEM є модифікатором змінної, нема жорстких і швидких правил щодо того, куди він повинен спрямовуватися, тому компілятор Arduino приймає всі визначення нижче, які також є синонімами. Але, як показали експерименти, у різних версіях Arduino PROGMEM може працювати в одному місці і не працювати в іншому. Приклад “таблиці рядків” нижче був протестований, щоб працювати з Arduino 13. Більш ранні версії IDE можуть працювати краще, якщо PROGMEM буде включена після імені змінної.

const dataType variableName[] PROGMEM = {};   // використовуйте цю форму
const PROGMEM  dataType  variableName[] = {}; // або цю
const dataType PROGMEM variableName[] = {};   // але не цю


Хоча PROGMEM може бути використана як одинична змінна, справді варто метушитися з нею лише коли Ви маєте великі блоки даних, які повинні бути збережені, що зазвичай легше в масиві (або інша структура даних в C поза нашим обговоренням).

Використання PROGMEM — це також двокрокова процедура. Після поміщення даних у флеш-пам'ять вона вимагає спеціальних методів (функцій), також визначених у бібліотеці pgmspace.h, щоб зчитувати дані з програмної пам’яті назад у SRAM, щоб могти робити щось корисне з ними.

Приклад

Наступні фрагменти коду показують, як читати і писати символи (байти) та цілі числа (2 байти) до PROGMEM.

#include <avr/pgmspace.h>
 
 
// збережіть деякі unsigned ints
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-байтовий int
  for (k = 0; k < 5; k++)
  {
    displayInt = pgm_read_word_near(charSet + k);
    Serial.println(displayInt);
 }
  Serial.println();
 
  // зчитайте символ
  int len = strlen_P(signMessage);
  for (k = 0; k < len; k++)
  {
    myChar =  pgm_read_byte_near(signMessage + k);
    Serial.print(myChar);
  }
 
  Serial.println();
}
 
void loop() {
  // помістіть головний код тут, щоб запустити повторно:
 
}

Масиви рядків

При роботі з великими обсягами тексту, такими як проект з рідкокристалічним дисплеєм, часто зручно встановлювати масив рядків. Насправді, це приклад двовимірного масиву, оскільки рядки самі є масивами.

Як правило, вони є великими структурами, тому поміщати їх в програмну пам’ять часто небажано. Наведений нижче код ілюструє цю ідею.

#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()
{
 
  for (int i = 0; i < 6; i++)
  {
    strcpy_P(buffer, (char*)pgm_read_word(&(string_table[i]))); // необхідне, просто скопіюйте
    Serial.println(buffer);
    delay( 500 );
  }
}

Примітка

Зверніть увагу, що змінні повинні бути визначені як глобальні або з допомогою ключового слова static для того, щоб працювати з PROGMEM.

Наступний код не працюватиме всередині функції:

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("Напишіть щось у серійний монітор");


надрукований рядок зберігається в RAM. Якщо Ваш скетч друкує багато матеріалів у серійний монітор, Ви можете легко заповнити оперативну пам'ять. Якщо у Вас є вільний простір флеш-пам'яті, можна легко вказати, що рядок повинен бути збережений у флеш, використовуючи синтаксис:

Serial.print(F("Напишіть щось у серійний монітор, що буде збережене у флеш-пам’яті"))


Повернутись до головної

Коментарі 0

Тільки зареєстровані та авторизовані користувачі можуть залишати коментарі.