2016-06-13 8 views
0

Ich möchte eine Zeichenfolge aus einer Struktur in Arduino PROGMEM gespeichert lesen:von struct in Arduino PROGMEM Lese String

struct commandCode { 
    int code; 
    const char *name; 
}; 

const PROGMEM commandCode commands[LAST_COMMAND] = { 
    { 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"}, 
}; 

Dieser Code druckt die Zeichenfolge nur fein:

void CommandCodes::show() { 
    Serial.print(LAST_COMMAND); 
    Serial.println(" Comands Defined:"); 
    for (int i = FIRST_COMMAND; i < LAST_COMMAND; i++) { 
     CommandCodes::commandCode cmd = commands[i]; 
     showCommand(cmd); 
    } 
} 

void CommandCodes::showCommand(commandCode cmd) { 
    if (cmd.code > FIRST_COMMAND) { 
     Serial.print(F("[")); 
     Serial.print(cmd.code); 
     Serial.print(F("] ")); 
     Serial.println(cmd.name); 
    } 

} 

Dieser Code Bomben und das Programm startet:

const char* CommandCodes::name(int code) { 
    for (int i = FIRST_COMMAND; i < LAST_COMMAND; i++) { 
     CommandCodes::commandCode cmd = commands[i]; 
     if (cmd.code == code) { 
      return cmd.name; 
     } 
    } 
    return NULL; 
} 

Was ist der Code einen Zeiger auf cmd.name zurückzukehren?

Antwort

0

Da die Struktur nur einen Zeiger und nicht die String-Daten enthält, werden die Strings immer noch im RAM gespeichert.

Auch Sie lesen nicht von PROGMEM, wenn Sie auf die Daten zugreifen, die Tatsache, dass es in bestimmten Situationen funktioniert, ist nur Glück, aber immer noch falsch.

Um alle Daten in PROGMEM zu platzieren, müssen Sie Speicherplatz innerhalb der Struktur dafür reservieren. Da der größte String 11 Zeichen ist + null Sie die Länge 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"} 
} 

machen können als die Einbauten jeder Struktur sind in PROGMEM müssen Sie sie mit speziellen Funktionen lesen. Sie können sie nicht direkt lesen.

Das bedeutet auch, Sie ein Element nicht kopieren können, wie Sie getan haben:
CommandCodes::commandCode cmd = commands[i];

Aber Sie können eine Referenz verwenden. const commandCode &cmd = commands[i];

Allerdings müssen, wie oben erwähnt, die Elemente der referenzierten Struktur immer noch richtig aufgerufen werden.

Für eine ganze Zahl müssen Sie pgm_read_word verwenden. Für die Strings können Sie die Serial-Klasse dazu bringen, sie für Sie auszudrucken, da Flash-Strings behandelt werden (z. B. wenn Sie das Makro F() verwenden). Dies kann erreicht werden, indem der Zeiger auf eine const __FlashStringHelper* geworfen wird.

Hier ist eine Arbeitsskizze, die zeigt, wie man auf jedes Teil richtig zugreift. Probieren Sie es aus und versuchen Sie herauszufinden, was ich getan habe. Ich bin sicher, dass Sie einige Fragen haben werden, also fügen Sie sie einfach zu den Kommentaren dieser Antwort hinzu und ich werde meine Antwort für Sie aktualisieren.

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() {} 
Verwandte Themen