Arduinoリファレンス

Arduinoリファレンスの日本語訳のページです
garretlab
PROGMEM

説明

データをSRAMではなく、フラッシュ(プログラム)メモリに配置する。Arduinoボードで利用可能なさまざまな種類のメモリの詳細説明がある。

PROGMEMは変数の修飾子である。pmgspace.hで定義されたデータ型に対してだけ利用すること。通常変数を配置するSRAMではなく、フラッシュメモリに変数を配置するようコンパイラに対して指示を出す。

PROGMEMはpgmspace.hで定義されているので、スケッチの最初で以下のようにヘッダファイルを取り込む必要がある。

#include <avr/pgmspace.h>

書式

dataType variableName[] PROGMEM = {dataInt0, dataInt1, dataInt3...};

dataType 任意の変数のデータ型
variableName データの配列の名前

注意

PROGMEMは変数の修飾子なので、どこに記述するかの明確な規則はない。Arduinoコンパイラは以下の定義をすべて受け付ける。これらはすべて同じ意味である。しかし、多くのバージョンのArduinoでの経験上、PROGMEMはある場所に記述したときは動作するが、他の場所では動作しないこともある。Arduino13での文字列テーブルでの例では、以下が動作することがわかっている。古いバージョンのIDEでは、PROGMEMが変数名の後ろにあるほうがいい。

const dataType variableName[] PROGMEM = {};   // この形式か
const PROGMEM  dataType  variableName[] = {}; // この形式を使う
const dataType PROGMEM variableName[] = {};   // この形式は使わない
                

PROGMEMは(配列ではない)一つの変数に対しても利用できる。しかし、実際には大きなデータブロックを利用しなければならないときに有用であり、それを利用する簡単で一般的な方法は配列である(今まで議論していないC言語のデータ構造もあるかもしれないが)。

PROGMEMの利用は2段階からなる。まず、データをフラッシュメモリに配置し、その後、pgmspace.hに定義された特別なメソッド(関数)を使って、データをフラッシュメモリからSRAMに読み出す。このようにすることでPROGMEMを有効に利用することができる。

最初に述べたように、pgmspace.hで定義されたデータ型に対して利用することが重要である。pgmspace.hで定義されていない他のデータ型に対して利用すると、意味不明なバグが生成されるかもしれない。以下に利用可能なデータ型を示す。浮動小数点型はサポートされていない。

prog_char 符号付き文字型、-128から127
prog_uchar 符号なし文字型、0から255
prog_int16_t 符号付きint型、-32768から32767
prog_uint16_t 符号なしint型、0から65535
prog_int32_t 符号付きlong型、2147483648から2147483647
prog_uint32_t 符号なしlong型、0から4294967295

以下のコードは、PROGMEMにchar(1バイト)とint(2バイト)のデータを読み書きする。

#include <avr/pgmspace.h>


// unsigned intをセーブする
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);

  // put your setup code here, to run once:
  // 2バイト読む
  for (k = 0; k < 5; k++)
  {
    displayInt = pgm_read_word_near(charSet + k);
    Serial.println(displayInt);
  }
  Serial.println();

  // 1文字読む
  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() {
  // put your main code here, to run repeatedly:

}

文字列の配列

LCDディスプレイを利用したプロジェクトなどにおいて文字列の配列を設定するときなど、大量の文字を利用する場合に有用である。文字列自身が配列なので、これは2次元配列の実際の例である。

これらは大きな構造になることが多いので、プログラムメモリに配置することが望ましい。以下のコードでは考え方を示す。

/*
 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>
prog_char string_0[] PROGMEM = "String 0";   // "String 0" etc are strings to store - change to suit.
prog_char string_1[] PROGMEM = "String 1";
prog_char string_2[] PROGMEM = "String 2";
prog_char string_3[] PROGMEM = "String 3";
prog_char string_4[] PROGMEM = "String 4";
prog_char string_5[] PROGMEM = "String 5";


// Then set up a table to refer to your strings.

PGM_P PROGMEM string_table[] =     // change "string_table" name to suit
{   
  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);
}


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()マクロ

以下のようなコードが使われたときには、表示される文字列はRAMにセーブされる。

Serial.print("Write something on  the Serial Monitor");

シリアルモニタに大量の文字を表示するときには、簡単にRAMを満杯にしてしまう。FLASHメモリの領域が余っているときには、以下のようなコードを使って、簡単にFLASHメモリを利用することができる。

Serial.print(F("Write something on the Serial Monitor that is stored in FLASH"));

バージョン

Arduino 1.8.4

オリジナルのページ

https://www.arduino.cc/en/Reference/PROGMEM



メニューを表示するためにJavaScriptを有効にしてください。

inserted by FC2 system