当前位置: 首页>>代码示例 >>用法及示例精选 >>正文


Arduino PROGMEM用法及代码示例


[实用程序]

说明

将数据存储在闪存(程序)存储器而不是 SRAM 中。 Arduino板上有各种types of memory的说明。

PROGMEM 关键字是一个变量修饰符,它只能用于 pgmspace.h 中定义的数据类型。它告诉编译器“将这些信息放入闪存中”,而不是放入通常存放的 SRAM 中。

PROGMEM 是pgmspace.h 库的一部分。它自动包含在现代版本的 IDE 中。但是,如果您使用低于 1.0 (2011) 的 IDE 版本,您首先需要在您的草图顶部包含该库,如下所示:

#include <avr/pgmspace.h> 虽然 PROGMEM 可以用于单个变量,但只有在需要存储更大的数据块时才值得大惊小怪,这通常在数组中最简单,(或其他 C++ 数据结构超出我们目前的讨论)。

使用PROGMEM 也是一个两步过程。将数据放入闪存后,需要特殊的方法(函数)(也定义在pgmspace.h 库中)将数据从程序存储器读回 SRAM,因此我们可以用它做一些有用的事情。

用法

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

请注意,由于 PROGMEM 是一个变量修饰符,因此对于它应该去哪里没有硬性规定,因此 Arduino 编译器接受以下所有定义,它们也是同义词。然而,实验表明,在各种版本的 Arduino 中(与 GCC 版本有关),PROGMEM 可能在一个位置而不是在另一个位置工作。下面的"string table" 示例已经过测试,可与 Arduino 13 一起使用。如果在变量名称后包含 PROGMEM,则早期版本的 IDE 可能会更好地工作。

const dataType variableName[] PROGMEM = {}; // use this form
const PROGMEM dataType variableName[] = {}; // or this one
const dataType PROGMEM variableName[] = {}; // not this one

参数

dataType:允许的数据类型:任何变量类型。
variableName:数据数组的名称。

示例代码

以下代码片段说明了如何将无符号字符(字节)和整数(2 个字节)读写到 PROGMEM。

// save some unsigned ints
const PROGMEM uint16_t charSet[] = { 65000, 32796, 16843, 10, 11234};

// save some chars
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);
  }
}

注意事项和警告

请注意,变量必须是全局定义的,或使用 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("Write something on  the Serial Monitor");

使用时,要打印的字符串通常保存在 RAM 中。如果你的草图在串行监视器上打印了很多东西,你可以很容易地填满 RAM。如果您有可用的 FLASH 内存空间,您可以使用以下语法轻松指示字符串必须保存在 FLASH 中:

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

相关用法


注:本文由纯净天空筛选整理自arduino.cc大神的英文原创作品 PROGMEM。非经特殊声明,原始代码版权归原作者所有,本译文未经允许或授权,请勿转载或复制。