Arduino PROGMEM静态存储区的使用介绍

Arduino PROGMEM静态存储区的使用介绍

关键字PROGMEM

由于程序存储区SRAM 内存是分开的,于是就有了像328P 有 32K 的 FLASH 程序存储区 和 2K 的 SRAM 动态内存,当然还有 ROM,PROGMEM将数据存储在闪存(程序)存储器而不是动态内存SRAM中。

  • promem关键字是一个变量修饰符,它应该只用于pgmspace.h中定义的数据类型。它告诉编译器“将这些信息放入闪存中”,而不是通常的SRAM中。
  • PROGMEMpgmspace.h库的一部分。它自动包含在IDE的新版版本中。如果你使用的IDE版本低于1.0(2011),程序代码的的顶部需要添加包含引入这个头文件库,像这样:#include <avr/pgmspace.h>
  • 虽然promem可以用于单个变量,但只有在需要存储更大的数据块的情况下才值得这样做,这通常是最简单的数组(或其他c++数据结构)。
  • 使用promem也是分两个步骤过程。在将数据存入闪存之后,它需要特殊的方法(函数),也定义在pgmspace.h库中,从程序内存中读取数据到SRAM中,这样我们就可以用它做一些有用的事情。

定义方式

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

dataType: Allowed data types: any variable type.
variableName: the name for your array of data.

  • 示例代码
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() {

}
  • 编译信息
项目使用了 1782 字节,占用了 (5%) 程序存储空间。最大为 32256 字节。
全局变量使用了188字节,(9%)的动态内存,余留1860字节局部变量。最大为2048字节。

📑字符串数组

在处理大量文本时,例如使用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);
  }
}

⚡使用注意事项

请注意,为了使用promem,变量必须是全局定义的,或者用static关键字定义的。

  • 示例

下面的代码,如果定义在函数内部则,不能工作:(缺少静态修饰词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中。如果你的程序在串行监视器上打印了很多东西,你可以很容易地占满RAM。如果你有空闲的FLASH内存空间,你可以很容易地使用语法指示字符串必须保存在FLASH中:

Serial.print(F("Write something on the Serial Monitor that is stored in FLASH"));
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值