Урок по использованию PROGMEM
avr/pgmspace.h #
Информация относится к библиотеке avr/pgmspace.h для МК AVR, но для совместимости она поддерживается и в других платформах семейства Arduino, например ESP8266, ESP32.
Макросы и типы #
PGM_P- синонимconst char *для строк в PGM памятиPGM_VOID_P- синонимconst void *для данных в PGM памятиPROGMEM- синоним атрибута__ATTR_PROGMEM__для помещения в PGMPSTR(const char* s)- поместить строку в PGM
Чтение #
pgm_read_byte(addr)- прочитать 1 байт из PGM по адресуaddrpgm_read_word(addr)- прочитать 2 байта из PGM по адресуaddrpgm_read_dword(addr)- прочитать 4 байта из PGM по адресуaddrpgm_read_float(addr)- прочитать float из PGM по адресуaddrpgm_read_ptr(addr)- прочитать указатель из PGM по адресуaddr
У этих функций ещё бывают версии _near (близко) и _far (далеко), например pgm_read_byte_near. Для МК с объёмом Flash памяти меньше 64 кБ они не имеют различий, а вот если памяти больше - нужно быть аккуратнее, например на Mega2560. Обычная версия (без суффикса) вызывает _near и работает с адресами 0x0000.. 0xFFFF. Если данные нужно прочитать с адреса 0x10000 и выше - нужно вызывать _far-версию. Узнать адрес, по которому линкер разместил данные, можно выведя в консоль адрес указателя или через утилиты тулчейна AVR
Байты, массивы #
Аналоги функций для работы с памятью для PROGMEM, здесь PGM_VOID_P - указатель на данные в PGM памяти:
memcpy_P #
void* memcpy_P(void* dest, PGM_VOID_P src, size_t n)n байт из src в dest до значения valmemccpy_P #
void* memccpy_P(void* dest, PGM_VOID_P src, int val, size_t len)n байт из src в dest до значения valmemcmp_P #
int memcmp_P(const void* s1, PGM_VOID_P s2, size_t len)s1 и s2 на длине lenmemchr_P #
PGM_VOID_P memchr_P(PGM_VOID_P s, int val, size_t len)val в области s длиной len с началаmemrchr_P #
PGM_VOID_P memrchr_P(PGM_VOID_P s, int val, size_t len)val в области s длиной len с концаmemmem_P #
void* memmem_P(const void* s1, size_t len1, PGM_VOID_P s2, size_t len2)s1 длиной len1 с s2 длиной len2Строки #
Аналоги функций для работы со строками для PROGMEM, здесь PGM_P - указатель на строку в PGM памяти:
strlen_P #
size_t strlen_P(PGM_P s)strnlen_P #
size_t strnlen_P(PGM_P src, size_t len)lenstrcpy_P #
char* strcpy_P(char* dest, PGM_P src)src в dest буферstrncpy_P #
char* strncpy_P(char* dest, PGM_P src, size_t n)src в dest буферstrlcpy_P #
size_t strlcpy_P(char* dst, PGM_P src, size_t size)src в dest буфер размером sizestrcat_P #
char* strcat_P(char* dest, PGM_P src)src к буферу deststrncat_P #
char* strncat_P(char* dest, PGM_P src, size_t len)src к буферу deststrlcat_P #
size_t strlcat_P(char* dst, PGM_P src, size_t size)src к буферу dest размером sizestrcmp_P #
int strcmp_P(const char* s1, PGM_P s2)strncmp_P #
int strncmp_P(const char* s1, PGM_P s2, size_t n)n символов строкstrcasecmp_P #
int strcasecmp_P(const char* s1, PGM_P s2)strncasecmp_P #
int strncasecmp_P(const char* s1, PGM_P s2, size_t n)n символов строк без учёта регистра буквstrchr_P #
PGM_P strchr_P(PGM_P s, int val)strrchr_P #
PGM_P strrchr_P(PGM_P s, int val)strstr_P #
PGM_P strstr_P(const char* s1, PGM_P s2)strcasestr_P #
PGM_P strcasestr_P(const char* s1, PGM_P s2)strspn_P #
size_t strspn_P(const char* s, PGM_P accept)acceptstrcspn_P #
size_t strcspn_P(const char* s, PGM_P reject)rejectstrpbrk_P #
PGM_P strpbrk_P(const char* s, PGM_P accept)acceptstrtok_P #
char* strtok_P(char* s, PGM_P delim)strtok_rP #
char* strtok_rP(char* string, PGM_P delim, char** last)