如何在 Arduino 中使用 PROGMEM 存储大量不可变数据?
PROGMEM是您希望将数据存储在程序存储器(闪存)而不是SRAM中时使用的关键字。虽然您可以将PROGMEM用于单个变量,但这样做没有多大意义。毕竟,SRAM将有足够的空间来容纳您的单个变量,并且访问存储在SRAM中的变量会更快。
PROGMEM主要用于大块数据(主要是数组),它可以压倒SRAM(它的大小通常比闪存小得多,但访问速度更快)。在PROGMEM中存储一些东西的含义是它不能在运行时动态修改。因此,人们一般使用PROGMEM来存储大型的不可变文本或数据。
如果您使用的是低于1.0的ArduinoIDE版本(为什么?),那么您需要包括
#include
在代码顶部使用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位整数数组(在ArduinoUno上为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(); }
循环内什么也没有发生。