由于结构只包含一个指针,而不是字符串数据,因此字符串仍然存储在 RAM 中。
此外,当您访问数据时,您没有从 PROGMEM 读取数据,它在某些情况下工作的事实只是运气,但它仍然不正确。
要将所有数据放在 PROGMEM 中,您需要在结构内为其分配空间。由于最大的字符串是 11 个字符 + null,您可以将长度设为 12。
struct commandCode {
int code;
const char name[12];
};
const commandCode commands[] PROGMEM = {
{ CMD_DEMO, "DEMO" } ,
{ CMD_STOP, "STOP"} ,
{ CMD_FORWARD, "FORWARD"},
{ CMD_BACKWARD, "BACKWARD"},
{ CMD_TURN_LEFT, "TURN LEFT"},
{ CMD_TURN_RIGHT, "TURN RIGHT"},
{ CMD_WAIT, "WAIT"},
{ CMD_WAIT_DONE, "WAIT DONE"}
}
由于每个结构的内部都在 PROGMEM 中,因此您需要使用特殊函数来读取它们。您无法直接阅读它们。
这也意味着您不能像以前那样复制项目:
CommandCodes::commandCode cmd = commands[i];
但是您可以使用参考。
const commandCode &cmd = commands[i];
然而,就像我上面提到的,被引用结构的元素仍然需要被正确访问。
对于整数,您需要使用pgm_read_word
. 对于字符串,您可以欺骗 Serial 类在处理 Flash 字符串时为您打印它(就像您使用F()
宏的位置一样)。这可以通过将指针转换为 a 来完成const __FlashStringHelper*
。
这是一个工作草图,展示了如何正确访问每个部分。给它一个测试,试着弄清楚我做了什么。我相信你会有一些问题,所以只需将它们添加到这个答案的评论中,我会为你更新我的答案。
struct commandCode {
int code;
const char name[12];
};
enum COMMANDS{
CMD_DEMO,
CMD_STOP,
CMD_FORWARD,
CMD_BACKWARD,
CMD_TURN_LEFT,
CMD_TURN_RIGHT,
CMD_WAIT,
CMD_WAIT_DONE,
};
const commandCode commands[] PROGMEM = {
{ CMD_DEMO, "DEMO" } ,
{ CMD_STOP, "STOP"} ,
{ CMD_FORWARD, "FORWARD"},
{ CMD_BACKWARD, "BACKWARD"},
{ CMD_TURN_LEFT, "TURN LEFT"},
{ CMD_TURN_RIGHT, "TURN RIGHT"},
{ CMD_WAIT, "WAIT"},
{ CMD_WAIT_DONE, "WAIT DONE"}
};
#define FIRST_COMMAND 0
#define LAST_COMMAND sizeof(commands) / sizeof(*commands)
#define FSH (const __FlashStringHelper*) //A helper to allow printing the PROGMEM strings.
void show() {
for (int i = FIRST_COMMAND; i < LAST_COMMAND; i++) {
const commandCode &cmd = commands[i];
showCommand(cmd);
}
}
void showCommand(const commandCode &cmd) {
if ( pgm_read_word( &cmd.code ) > FIRST_COMMAND) {
Serial.print(F("["));
Serial.print( pgm_read_word( &cmd.code ) );
Serial.print(F("] "));
Serial.println( FSH( cmd.name ) );
}
}
const char* name(int code) {
for (int i = FIRST_COMMAND; i < LAST_COMMAND; i++) {
const commandCode &cmd = commands[i];
if (pgm_read_word(&cmd.code) == code) {
return cmd.name; //As cmd.name resolves to a pointer it can be passed back as is.
//However to use the 'pointed to data' it will have to be accessed properly.
}
}
return NULL;
}
void setup() {
Serial.begin(9600);
Serial.println("Show test");
show();
Serial.println("Name test");
for (int i = FIRST_COMMAND; i < LAST_COMMAND; i++) {
Serial.println( FSH( name(i) ) );
}
Serial.println("Done");
}
void loop() {}