相关推荐
您可能对下面课程感兴趣
Arduino视频教程基础篇

75小节已有149886人学过

使用PROGMEM在flash中存储数据
发布时间:2022-03-12 09:22 [ 我要自学网原创 ] 发布人: 小刘2175 阅读: 4336

本方法只适用于使用AVR作为核心的Arduino!

闪存(程序)内存而不是SRAM存储数据。有各种类型的可用内存的描述上的Arduino板。

该PROGMEM关键字是一个可变调节剂,但只应在pgmspace.h定义的数据类型使用。它告诉编译器“把这个信息到闪存”,而不是到SRAM,它通常会去。

PROGMEM是pgmspace.h库仅在AVR架构可用的一部分。所以,你首先需要包含库顶部草图,就像这样:

[mw_shl_code=cpp,true]#include <avr/pgmspace.h>[/mw_shl_code]
使用语法:
[mw_shl_code=cpp,true]const dataType variableName[] PROGMEM = {data0, data1, data3...};[/mw_shl_code]

dataType   任何变量类型
variableName   数组名称

请注意,因为PROGMEM是一个可变的调节剂,也没有严格的,它应该走的快规律,Arduino的编译器接受以下所有的定义,这也是代名词。然而实验已经表明,在Arduino的各种版本(具有用GCC版本做),PROGMEM可以在一个位置,而不是工作在另一。“字符串表”下面的例子已经过测试,Arduino的合作13. IDE的早期版本可能更好地工作,如果PROGMEM的变量名后包括在内。

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

虽然PROGMEM可以在单个变量使用,真的是唯一值得大惊小怪的,如果你有更大的数据块需要存储,这通常是最容易在数组中(或其他C数据结构超出了我们现在的讨论)。

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


示例程序:
下面的代码片段说明了如何读取和写入字符(字节)和int(2字节)PROGMEM。
[mw_shl_code=cpp,true]#include <avr/pgmspace.h>


// 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;
int k;    // counter variable
char myChar;


void setup() {
  Serial.begin(9600);
  while (!Serial);

  // put your setup code here, to run once:
  // read back a 2-byte int
  for (k = 0; k < 5; k++)
  {
    displayInt = pgm_read_word_near(charSet + k);
    Serial.println(displayInt);
  }
  Serial.println();

  // read back a char
  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:

}[/mw_shl_code]


字符串数组

用大量的文字,如配有液晶显示器的一个项目工作时,设置一个字符串数组它往往是方便。因为字符串本身是数组,这是在实际的二维阵列的实例。

这些往往是这样把它们放入程序存储器经常需要大的结构。下面的代码说明了这个想法。



[mw_shl_code=cpp,true]/*
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);
  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))); // Necessary casts and dereferencing, just copy.
    Serial.println(buffer);
    delay( 500 );
  }
}[/mw_shl_code]

注意事项

请注意,必须使用全局变量定义flash存储的数据,或者用static关键字定义,这样才能使PROGMEM正常工作。
如果在一个函数中使用如下方式定义,PROGMEM将无法正常工作:
[mw_shl_code=cpp,true]const char long_str[] PROGMEM = "Hi, I would like to tell you a bit about myself.\n";[/mw_shl_code]
要作为局部变量定义,必须添加static 关键字,如:
[mw_shl_code=cpp,true]const static char long_str[] PROGMEM = "Hi, I would like to tell you a bit about myself.\n"[/mw_shl_code]

F()宏
通常我们都使用如下语句,进行串口输出:
[mw_shl_code=cpp,true]Serial.print("Write something on  the Serial Monitor");[/mw_shl_code]
但这样使用,每次调用时,都会先将数据保存在RAM中。当我们要输出长的字符串时,就会占用很多的RAM空间。使用F()就可以很好的解决这个问题:
[mw_shl_code=cpp,true]Serial.print(F("Write something on the Serial Monitor that is stored in FLASH"));[/mw_shl_code]

Arduino视频教程基础篇
我要自学网商城 ¥40 元
进入购买
文章评论
0 条评论 按热度排序 按时间排序 /350
遵守中华人民共和国的各项道德法规,
承担因您的行为而导致的法律责任,
本站有权保留或删除有争议评论。
参与本评论即表明您已经阅读并接受
上述条款。
V
特惠充值
联系客服
APP下载
官方微信
返回顶部
相关推荐
您可能对下面课程感兴趣
Arduino视频教程基础篇

75小节已有149886人学过

分类选择:
电脑办公 平面设计 室内设计 室外设计 机械设计 工业自动化 影视动画 程序开发 网页设计 会计课程 兴趣成长 AIGC