Obecnie zmieniam niektóre biblioteki, aby używały pamięci flash zamiast pamięci RAM do przechowywania ciągów, aby nie zabrakło SRAM w projekcie.
Niektóre ciągi w bibliotece są zadeklarowane w następujący sposób:
const char *testStringA = "ABC";
Różni się to od tego, jak zwykle to robię:
const char testStringB[] = "DEF";
Myślę jednak, że te dwa są równoważne, gdy zostaną zadeklarowane jako const i zainicjowane w deklaracji. Oba działają dobrze w kodzie.
Próbowałem przenieść je do flashowania:
const prog_char *testStringC PROGMEM = "GHI";
Potem odkryłem, że to nie działa. Po wydrukowaniu produkował gobbledegook.
Jednak zgodnie z bardziej typowym wzorem:
const prog_char testStringD[] PROGMEM = "JKL";
działa w porządku.
Widzę w demontażu:
00000068 <testStringC>:
68: 04 01 ..
0000006a <_ZL11testStringD>:
6a: 4a 4b 4c 00 JKL.
Jest więc jasne, że wskaźnik i PROGMEM powoduje, że łańcuch / tablica nie jest inicjowany.
Dlaczego to?
Przykładowy kod:
#include <avr/pgmspace.h>
const int BUFFER_LEN = 20;
const char *testStringA = "ABC";
const char testStringB[] = "DEF";
const prog_char *testStringC PROGMEM = "GHI";
const prog_char testStringD[] PROGMEM = "JKL";
void setup()
{
Serial.begin(9600);
}
void loop()
{
char buffer[BUFFER_LEN];
Serial.println(testStringA);
Serial.println(testStringB);
strncpy_P(buffer, testStringC, BUFFER_LEN);
Serial.println(buffer);
strncpy_P(buffer, testStringD, BUFFER_LEN);
Serial.println(buffer);
delay(1000);
}
PSTR()
makro, ale zmieniłem naF()
przed przesłaniem, ponieważ twoje stałe są globalne w twoim Q, więc wolałem trzymać się tego, który powinien działać w obu kontekstach.Co ta linia:
robi to napisać kod prologu, aby skopiować znaki z łańcucha do SRAM, a następnie inicjuje wskaźnik zapisany we flashu do tej lokalizacji SRAM. Musisz załadować wskaźnik w normalny sposób, a następnie wyrejestrować wskaźnik jak zwykle.
Ta linia:
tworzy tablicę znaków we flashu, umożliwiając dostęp do niej zgodnie z oczekiwaniami.
źródło