Arduinoファームウェアの基礎 - PROGMEM
ナビゲーションに移動
検索に移動
概要
PROGMEM
キーワードは変数修飾子であり、SRAMの代わりにフラッシュメモリにデータを格納する。
PROGMEM
キーワードは、pgmspace.hファイルで定義されたデータ型でのみ使用される。
Arduino IDEが古い場合は、以下のようにライブラリをインクルードする必要がある。
#include <avr/pgmspace.h>
使用方法
PROGMEM
キーワードの使用方法は、2ステップに分かれている。
- まず、データをフラッシュメモリに格納する。
- 次に、プログラムメモリからSRAMにデータを読み戻す(使用する)には、avr/pgmspace.hファイルで定義されているPROGMEM専用の関数を使用する。
以下に、PROGMEM
キーワードのシンタックスを示す。
const <データ型> <変数名または配列変数名> PROGMEM = {data0, data1, data3 ...};
// または
const PROGMEM <データ型> <変数名または配列変数名> = {data0, data1, data3 ...};
以下の例では、PROGMEM
キーワードを使用したchar型とuint16_t型の配列を読み書きしている。
// save some unsigned int
const PROGMEM uint16_t charSet[] = {65000, 32796, 16843, 10, 11234};
// save some char
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:
}
LCDを使用して大量のテキストを扱う場合、文字列配列を設定すると便利なことが多い。
このような配列はサイズが大きくなりがちなため、フラッシュメモリ上に格納することが望ましい場合がある。
以下は、その例である。
/*
PROGMEM string demo
How to store a table of strings in program memory (flash),
and retrieve them.
Information summarized from:
http://www.nongnu.org/avr-libc/user-manual/pgmspace.html
Setting up a table (array) of strings in program memory is slightly complicated, but
here is a good template to follow.
Setting up the strings is a two-step process. First, define the strings.
*/
#include <avr/pgmspace.h>
const char string_0[] PROGMEM = "String 0"; // "String 0" etc are strings to store - change to suit.
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";
// Then set up a table to refer to your strings.
const char *const string_table[] PROGMEM = {string_0, string_1, string_2, string_3, string_4, string_5};
char buffer[30]; // make sure this is large enough for the largest string it must hold
void setup()
{
Serial.begin(9600);
while (!Serial); // wait for serial port to connect. Needed for native USB
Serial.println("OK");
}
void loop()
{
/*
Using the string table in program memory requires the use of special functions to retrieve the data.
The strcpy_P function copies a string from program space to a string in RAM ("buffer").
Make sure your receiving string in RAM is large enough to hold whatever
you are retrieving from program space.
*/
for (int i = 0; i < 6; i++)
{
strcpy_P(buffer, (char *)pgm_read_word(&(string_table[i]))); // Necessary casts and dereferencing, just copy.
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()
を使用する場合、表示される文字列はRAMに保存される。
Serial.print("Write something on the Serial Monitor");
シリアルモニタに多くのものを表示する場合、RAMが不足する可能性がある。
この時、フラッシュメモリの空き容量がある場合は、F()
マクロを使用して、文字列をフラッシュメモリに保存することができる。
Serial.print(F("Write something on the Serial Monitor that is stored in FLASH"));