PROGMEM

Przeanalizujmy następujący fragment kodu:

LCD_write("Jakis tekst");

Jest to fragment kodu wypisujący na wyświetlaczu LCD tekst. Pomimo że wydaje się to optymalnym rozwiązaniem takim nie jest. Co się powinno dziać w przypadku wywołania takiej funkcji? Funkcja powinna pobierać znak po znaku każdą literę z pamięci programu i wysyłać je do wyświetlacza. Niestety funkcja ta nie odczytuje tekstu z pamięci programu (przypominam FLASH) lecz z pamięci RAM co jest wielką stratą i kosztuje nas cykle pracy układu. Jest jednak sposób na oszczędzenie pamięci. Będziemy korzystać z nagłówka:

#include <avr/pgmspace.h>

Teraz jeżeli chcemy przechowywać łańcuch znaków tylko w pamięci programu napiszemy:

const char string[] PROGMEM = "Ten łańcuch znaków nie może zostać zmieniony i jest przechowywany w pamięci FLASH.";

Lub kożystając z makra możemy wprowadzać łańcuchy wewnątrz kodu:

LCD_write_P(PSTR("Program Memory String"));

Niestety to nie wszystko co trzeba zrobić, zmienna string oraz makro zwracają adres w pamięci FLASH a nie RAM tak jak jest to oczekiwane przez dotychczas istniejące funkcje. Trzeba je niestety zmodyfikować. Przeanalizujmy następujące fragmenty kodu:

while (*data != '\0') ...
while (pgm_read_byte(data) != 0x00) 

W przypadku odczytu z pamięci RAM korzystamy z pierwszej pętli natomiast aby odczytać bajt z pamięci programu należy wykorzystać funkcję pgm_read_byte. Często wyróżnia się funkcje odczytujące z pamięci FLASH kończąc ich nazwę na _P.

Bardzo dobre opracowanie PROGMEM: AVRFreaks [EN]