这里会显示出您选择的修订版和当前版本之间的差别。
两侧同时换到之前的修订记录前一修订版 | |||
zh:reference:language:progmem [2017/05/18 23:21] – 弘毅 | reference:language:progmem [2023/06/07 04:23] (当前版本) – 外部编辑 127.0.0.1 | ||
---|---|---|---|
行 1: | 行 1: | ||
+ | ====== PROGMEM ====== | ||
+ | |||
+ | 将数据存储在Flash存储器中,而不是SRAM。 | ||
+ | |||
+ | PROGMEM关键字是一个变量修饰符,它只能用于pgmspace.h中定义的数据类型。它告诉编译器“把这些信息放入Flash”,而不是平时放入的SRAM。 | ||
+ | |||
+ | PROGMEM仅是AVR GCC的pgmspace.h库的一部分。所以你首先需要添加一行代码,如下所示: | ||
+ | |||
+ | < | ||
+ | #include < | ||
+ | </ | ||
+ | |||
+ | ===== Syntax ===== | ||
+ | |||
+ | |||
+ | < | ||
+ | const dataType variableName[] PROGMEM = {data0, data1, data3...}; | ||
+ | </ | ||
+ | |||
+ | |||
+ | * dataType - any variable type | ||
+ | * variableName - the name for your array of data | ||
+ | Note that because PROGMEM is a variable modifier, there is no hard and fast rule about where it should go, so the Arduino compiler accepts all of the definitions below, which are also synonymous. However experiments have indicated that, in various versions of Arduino (having to do with GCC version), PROGMEM may work in one location and not in another. The " | ||
+ | |||
+ | < | ||
+ | const dataType variableName[] PROGMEM = {}; // use this form | ||
+ | const PROGMEM | ||
+ | const dataType PROGMEM variableName[] = {}; // not this one | ||
+ | </ | ||
+ | |||
+ | While PROGMEM could be used on a single variable, it is really only worth the fuss if you have a larger block of data that needs to be stored, which is usually easiest in an array, (or another C data structure beyond our present discussion). | ||
+ | |||
+ | Using PROGMEM is also a two-step procedure. After getting the data into Flash memory, it requires special methods (functions), | ||
+ | |||
+ | ===== Example ===== | ||
+ | |||
+ | The following code fragments illustrate how to read and write chars (bytes) and ints (2 bytes) to PROGMEM. | ||
+ | |||
+ | < | ||
+ | #include < | ||
+ | |||
+ | |||
+ | // save some unsigned ints | ||
+ | const PROGMEM | ||
+ | |||
+ | // save some chars | ||
+ | const char signMessage[] PROGMEM | ||
+ | |||
+ | 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: | ||
+ | |||
+ | } | ||
+ | </ | ||
+ | |||
+ | Arrays of strings | ||
+ | |||
+ | It is often convenient when working with large amounts of text, such as a project with an LCD display, to setup an array of strings. Because strings themselves are arrays, this is in actually an example of a two-dimensional array. | ||
+ | |||
+ | These tend to be large structures so putting them into program memory is often desirable. The code below illustrates the idea. | ||
+ | |||
+ | < | ||
+ | /* | ||
+ | | ||
+ | How to store a table of strings in program memory (flash), | ||
+ | and retrieve them. | ||
+ | |||
+ | | ||
+ | | ||
+ | |||
+ | | ||
+ | here is a good template to follow. | ||
+ | |||
+ | | ||
+ | */ | ||
+ | |||
+ | #include < | ||
+ | const char string_0[] PROGMEM = " | ||
+ | const char string_1[] PROGMEM = " | ||
+ | const char string_2[] PROGMEM = " | ||
+ | const char string_3[] PROGMEM = " | ||
+ | const char string_4[] PROGMEM = " | ||
+ | const char string_5[] PROGMEM = " | ||
+ | |||
+ | |||
+ | // 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]; | ||
+ | |||
+ | void setup() | ||
+ | { | ||
+ | Serial.begin(9600); | ||
+ | while(!Serial); | ||
+ | Serial.println(" | ||
+ | } | ||
+ | |||
+ | |||
+ | 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 (" | ||
+ | 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, | ||
+ | Serial.println(buffer); | ||
+ | delay( 500 ); | ||
+ | } | ||
+ | } | ||
+ | </ | ||
+ | Note | ||
+ | |||
+ | Please note that variables must be either globally defined, OR defined with the static keyword, in order to work with PROGMEM. | ||
+ | |||
+ | The following code will NOT work when inside a function: | ||
+ | < | ||
+ | const char long_str[] PROGMEM = "Hi, I would like to tell you a bit about myself.\n"; | ||
+ | </ | ||
+ | |||
+ | The following code WILL work, even if locally defined within a function: | ||
+ | < | ||
+ | const static char long_str[] PROGMEM = "Hi, I would like to tell you a bit about myself.\n" | ||
+ | </ | ||
+ | |||
+ | The F() macro | ||
+ | |||
+ | When an instruction like : | ||
+ | |||
+ | < | ||
+ | Serial.print(" | ||
+ | </ | ||
+ | |||
+ | is used, the string to be printed is normally saved in RAM. If your sketch prints a lot of stuff on the Serial Monitor, you can easily fill the RAM. If you have free FLASH memory space, you can easily indicate that the string must be saved in FLASH using the syntax: | ||
+ | |||
+ | < | ||
+ | Serial.print(F(" | ||
+ | </ | ||
+ | |||