PROGMEM 是您希望将数据存储在程序存储器(闪存)而不是 SRAM 中时使用的关键字。虽然您可以将 PROGMEM 用于单个变量,但这样做没有多大意义。毕竟,SRAM 将有足够的空间来容纳您的单个变量,并且访问存储在 SRAM 中的变量会更快。
PROGMEM 主要用于大块数据(主要是数组),它可以压倒 SRAM(它的大小通常比闪存小得多,但访问速度更快)。在 PROGMEM 中存储一些东西的含义是它不能在运行时动态修改。因此,人们一般使用 PROGMEM 来存储大型的不可变文本或数据。
如果您使用的是低于 1.0 的 Arduino IDE 版本(为什么?),那么您需要包括
#include <avr/pgmspace.h>
在代码顶部使用 PROGMEM 关键字。对于 Arduino >= 1.0 的版本,您可以直接使用 PROGMEM 关键字而无需任何包含。
请注意,PROGMEM 仅适用于全局变量或使用 static 关键字定义的变量。
语法如下 -
const dataType arrayName[] PROGMEM = {data0, data1, data3…};
datatype 允许任何变量类型,arrayName是数组的名称。
为了使用 PROGMEM 访问存储在闪存中的数据,您可以使用专门的功能 -
strlen_P(arrayName)− 此函数返回数组arrayName的长度。
pgm_read_byte_near(address) − 此函数返回位于地址的一个字节的值。
pgm_read_word_near(address) − 此函数返回一个字的值(大多数微控制器上为 2 个字节),位置从地址开始。
这些函数的用法将在下面的示例中一目了然。这些不是与 PROGMEM 一起使用的唯一函数。还有其他几个,你可以在这里找到。
让我们从示例开始。我们将使用 Arduino 文档中给出的示例。
我们将看第一个例子。如您所见,PROGMEM 中定义了两个数组,一个是 16 位整数数组(在 Arduino Uno 上为 16 位 = 1 个字),而第二个是字符数组(每个字符为 8 位或1 字节长)
// save some 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; char myChar;
在setup 中,我们初始化Serial。稍后,我们一次读取一个单词,以打印字符集数组的整数。注意我们如何使用charSet + k作为我们想要读取的地址。您可能还记得数组的名称也是指向其第一个元素的指针。此处使用了相同的属性。
void setup() { Serial.begin(9600); while (!Serial); //等待串口连接。本机 USB 需要 // 把你的设置代码放在这里,运行一次: // 读回一个 2 字节的 int for (byte k = 0; k < 5; k++) { displayInt = pgm_read_word_near(charSet + k); Serial.println(displayInt); } Serial.println();
稍后,我们从signMessage数组中读取每个字节并将其打印到串行监视器。请注意,我们使用strlen_P函数来获取数组的长度,以确定for循环的终止条件。
// 读回一个字符 for (byte k = 0; k < strlen_P(signMessage); k++) { myChar = pgm_read_byte_near(signMessage + k); Serial.print(myChar); } Serial.println(); }
循环内什么也没有发生。