相關(guān)推薦
您可能對(duì)下面課程感興趣
Arduino視頻教程基礎(chǔ)篇

75小節(jié)已有138460人學(xué)過(guò)

使用PROGMEM在flash中存儲(chǔ)數(shù)據(jù)
發(fā)布時(shí)間:2022-03-12 09:22 [ 我要自學(xué)網(wǎng)原創(chuàng) ] 發(fā)布人: 小劉2175 閱讀: 3066

本方法只適用于使用AVR作為核心的Arduino!

閃存(程序)內(nèi)存而不是SRAM存儲(chǔ)數(shù)據(jù)。有各種類(lèi)型的可用內(nèi)存的描述上的Arduino板。

該P(yáng)ROGMEM關(guān)鍵字是一個(gè)可變調(diào)節(jié)劑,但只應(yīng)在pgmspace.h定義的數(shù)據(jù)類(lèi)型使用。它告訴編譯器“把這個(gè)信息到閃存”,而不是到SRAM,它通常會(huì)去。

PROGMEM是pgmspace.h庫(kù)僅在AVR架構(gòu)可用的一部分。所以,你首先需要包含庫(kù)頂部草圖,就像這樣:

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

dataType   任何變量類(lèi)型
variableName   數(shù)組名稱(chēng)

請(qǐng)注意,因?yàn)镻ROGMEM是一個(gè)可變的調(diào)節(jié)劑,也沒(méi)有嚴(yán)格的,它應(yīng)該走的快規(guī)律,Arduino的編譯器接受以下所有的定義,這也是代名詞。然而實(shí)驗(yàn)已經(jīng)表明,在Arduino的各種版本(具有用GCC版本做),PROGMEM可以在一個(gè)位置,而不是工作在另一!白址怼毕旅娴睦右呀(jīng)過(guò)測(cè)試,Arduino的合作13. IDE的早期版本可能更好地工作,如果PROGMEM的變量名后包括在內(nèi)。

[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可以在單個(gè)變量使用,真的是唯一值得大驚小怪的,如果你有更大的數(shù)據(jù)塊需要存儲(chǔ),這通常是最容易在數(shù)組中(或其他C數(shù)據(jù)結(jié)構(gòu)超出了我們現(xiàn)在的討論)。

使用PROGMEM也是一個(gè)兩步過(guò)程。獲取數(shù)據(jù)到閃存后,它需要特殊的方法(函數(shù)),在pgmspace.h庫(kù)還規(guī)定,從程序存儲(chǔ)器中的數(shù)據(jù)讀回SRAM,所以我們可以做一些有用的事情吧。



示例程序:
下面的代碼片段說(shuō)明了如何讀取和寫(xiě)入字符(字節(jié))和int(2字節(jié))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]


字符串?dāng)?shù)組

用大量的文字,如配有液晶顯示器的一個(gè)項(xiàng)目工作時(shí),設(shè)置一個(gè)字符串?dāng)?shù)組它往往是方便。因?yàn)樽址旧硎菙?shù)組,這是在實(shí)際的二維陣列的實(shí)例。

這些往往是這樣把它們放入程序存儲(chǔ)器經(jīng)常需要大的結(jié)構(gòu)。下面的代碼說(shuō)明了這個(gè)想法。



[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]

注意事項(xiàng)

請(qǐng)注意,必須使用全局變量定義flash存儲(chǔ)的數(shù)據(jù),或者用static關(guān)鍵字定義,這樣才能使PROGMEM正常工作。
如果在一個(gè)函數(shù)中使用如下方式定義,PROGMEM將無(wú)法正常工作:
[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 關(guān)鍵字,如:
[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()宏
通常我們都使用如下語(yǔ)句,進(jìn)行串口輸出:
[mw_shl_code=cpp,true]Serial.print("Write something on  the Serial Monitor");[/mw_shl_code]
但這樣使用,每次調(diào)用時(shí),都會(huì)先將數(shù)據(jù)保存在RAM中。當(dāng)我們要輸出長(zhǎng)的字符串時(shí),就會(huì)占用很多的RAM空間。使用F()就可以很好的解決這個(gè)問(wèn)題:
[mw_shl_code=cpp,true]Serial.print(F("Write something on the Serial Monitor that is stored in FLASH"));[/mw_shl_code]

Arduino視頻教程基礎(chǔ)篇
我要自學(xué)網(wǎng)商城 ¥40 元
進(jìn)入購(gòu)買(mǎi)
文章評(píng)論
0 條評(píng)論 按熱度排序 按時(shí)間排序 /350
添加表情
遵守中華人民共和國(guó)的各項(xiàng)道德法規(guī),
承擔(dān)因您的行為而導(dǎo)致的法律責(zé)任,
本站有權(quán)保留或刪除有爭(zhēng)議評(píng)論。
參與本評(píng)論即表明您已經(jīng)閱讀并接受
上述條款。
V
特惠充值
聯(lián)系客服
APP下載
官方微信
返回頂部
相關(guān)推薦
您可能對(duì)下面課程感興趣
Arduino視頻教程基礎(chǔ)篇

75小節(jié)已有138460人學(xué)過(guò)

分類(lèi)選擇:
電腦辦公 平面設(shè)計(jì) 室內(nèi)設(shè)計(jì) 室外設(shè)計(jì) 機(jī)械設(shè)計(jì) 工業(yè)自動(dòng)化 影視動(dòng)畫(huà) 程序開(kāi)發(fā) 網(wǎng)頁(yè)設(shè)計(jì) 會(huì)計(jì)課程 興趣成長(zhǎng) AIGC