說明
將數據存儲在閃存(程序)存儲器而不是 SRAM 中。 Arduino板上有各種types of memory的說明。
PROGMEM
關鍵字是一個變量修飾符,它隻能用於 pgmspace.h 中定義的數據類型。它告訴編譯器“將這些信息放入閃存中”,而不是放入通常存放的 SRAM 中。
PROGMEM 是pgmspace.h 庫的一部分。它自動包含在現代版本的 IDE 中。但是,如果您使用低於 1.0 (2011) 的 IDE 版本,您首先需要在您的草圖頂部包含該庫,如下所示:
#include <avr/pgmspace.h>
雖然 PROGMEM
可以用於單個變量,但隻有在需要存儲更大的數據塊時才值得大驚小怪,這通常在數組中最簡單,(或其他 C++ 數據結構超出我們目前的討論)。
使用PROGMEM
也是一個兩步過程。將數據放入閃存後,需要特殊的方法(函數)(也定義在pgmspace.h 庫中)將數據從程序存儲器讀回 SRAM,因此我們可以用它做一些有用的事情。
用法
const dataType variableName[] PROGMEM = {data0, data1, data3…};
請注意,由於 PROGMEM 是一個變量修飾符,因此對於它應該去哪裏沒有硬性規定,因此 Arduino 編譯器接受以下所有定義,它們也是同義詞。然而,實驗表明,在各種版本的 Arduino 中(與 GCC 版本有關),PROGMEM 可能在一個位置而不是在另一個位置工作。下麵的"string table" 示例已經過測試,可與 Arduino 13 一起使用。如果在變量名稱後包含 PROGMEM,則早期版本的 IDE 可能會更好地工作。
const dataType variableName[] PROGMEM = {}; // use this form
const PROGMEM dataType variableName[] = {}; // or this one
const dataType PROGMEM variableName[] = {}; // not this one
參數
dataType
:允許的數據類型:任何變量類型。
variableName
:數據數組的名稱。
示例代碼
以下代碼片段說明了如何將無符號字符(字節)和整數(2 個字節)讀寫到 PROGMEM。
// 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;
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() {
// put your main code here, to run repeatedly:
}
字符串數組
在處理大量文本(例如帶有 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);
}
}
注意事項和警告
請注意,變量必須是全局定義的,或使用 static 關鍵字定義的,才能與 PROGMEM 一起使用。
在函數內部時,以下代碼將不起作用:
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()
宏
當一個指令像:
Serial.print("Write something on the Serial Monitor");
使用時,要打印的字符串通常保存在 RAM 中。如果你的草圖在串行監視器上打印了很多東西,你可以很容易地填滿 RAM。如果您有可用的 FLASH 內存空間,您可以使用以下語法輕鬆指示字符串必須保存在 FLASH 中:
Serial.print(F("Write something on the Serial Monitor that is stored in FLASH"));
相關用法
- Arduino long用法及代碼示例
- Arduino Arduino_EMBRYO_2 - setLengthXY()用法及代碼示例
- Arduino ~用法及代碼示例
- Arduino ArduinoBLE - bleDevice.advertisedServiceUuidCount()用法及代碼示例
- Arduino const用法及代碼示例
- Arduino Ethernet - server.begin()用法及代碼示例
- Arduino ArduinoBLE - BLEService()用法及代碼示例
- Arduino digitalWrite()用法及代碼示例
- Arduino ArduinoBLE - bleCharacteristic.subscribe()用法及代碼示例
- Arduino Servo - attach()用法及代碼示例
- Arduino write()用法及代碼示例
- Arduino Arduino_LSM9DS1 - readGyroscope()用法及代碼示例
- Arduino ArduinoSound - FFTAnalyzer.input()用法及代碼示例
- Arduino MKRGSM - gprs.attachGPRS()用法及代碼示例
- Arduino WiFiNINA - WiFi.config()用法及代碼示例
- Arduino MKRGSM - sms.read()用法及代碼示例
- Arduino MKRNB - getCurrentCarrier()用法及代碼示例
- Arduino Scheduler - Scheduler.startLoop()用法及代碼示例
- Arduino Arduino_LSM9DS1 - magneticFieldAvailable()用法及代碼示例
- Arduino MKRWAN - available()用法及代碼示例
- Arduino ArduinoBLE - BLE.poll()用法及代碼示例
- Arduino ArduinoBLE - bleCharacteristic.hasDescriptor()用法及代碼示例
- Arduino Ethernet - EthernetUDP.parsePacket()用法及代碼示例
- Arduino WiFi101 - WiFi.subnetMask()用法及代碼示例
- Arduino TFT - PImage.width()用法及代碼示例
注:本文由純淨天空篩選整理自arduino.cc大神的英文原創作品 PROGMEM。非經特殊聲明,原始代碼版權歸原作者所有,本譯文未經允許或授權,請勿轉載或複製。