PROGMEM
¿Para que sirve?
- PROGMEM hace que una variable constante a la que se le aplica resida en la memoria flash en vez de la RAM. Asi podemos ahorrar RAM para las demás variables.
- Si tenemos muchos strings que no se tienen que modificar (por ejemplo strings de menus) vale la pena guardarlos en la flash para que no ocupen RAM
- Las variables PROGMEM tienen espacio asignado en la memoria que no cambia durante la ejecución del programa.
Declaración de variables
Para alojar una variable constante en la memoria Flash se hace asi:
PROGMEM const tipoVariable nombreVariable = valoresIniciales;
Por ejemplo:
PROGMEM const int a = 5;
PROGMEM const int a[] = {0,3,4,2};
También puede hacerse asi:
const int a[] PROGMEM = {0,4,3,2};
O de un modo más abreviado:
const prog_uint16_t a[] = {0,4,3,2);//Esto equivale al ejemplo de encima
-----
'----> se mantiene const
Esta tabla muestra las equivalencias:
| escritura normal | escritura abrebiada | stdint.h |
|---|---|---|
| char PROGMEM | prog_char | |
| unsigned char PROGMEM | prog_uchar | |
| int8_t PROGMEM | prog_int8_t | signed char |
| uint8_t PROGMEM | prog_uint8_t | unsigned char |
| int16_t PROGMEM | prog_int16_t | signed int |
| uint16_t PROGMEM | prog_uint16_t | unsigned int |
| int32_t PROGMEM | prog_int32_t | signed long int |
| uint32_t PROGMEM | prog_uint32_t | unsigned long int |
| int64_t PROGMEM | prog_int64_t | signed long long int |
| uint64_t PROGMEM | prog_uint64_t | unsigned long long int |
Funciones de lectura
pgm_read_byte() //Lee un byte de la memoria Flash pgm_read_word() //Lee 2 bytes de la memoria Flash pgm_read_dword() //Lee 4 bytes de la memoria Flash pgm_read_float() //Lee un número de coma flotante de 4 bytes
- A cada una de estas funciones se le pasa una dirección de 16 bits que indican donde reside el elemento de la variable
Ejemplos
const prog_uint8_t a[]={1,2,3,32,55,12};
int b;
b = pgm_read_byte(&a[0]);
- b es igual a 1. Lo que le paso a pgm_read_byte es la dirección de la primera posición del array a
const prog_uint8_t a[]={1,2,3,32,55,12};
int b;
b = pgm_read_byte(&a++);
- b es igual a 2. Como a realmente es un puntero, apunta al primer elemento del array. Cuando hago a++ paso al siguiente elemento, que es a[1]
const prog_uint8_t a[]={1,2,3,32,55,12};
int b[5];
for(int i=0;i<6;i++){
b[i] = pgm_read_byte(&a++);
}
- En el array b he copiado el array a entero
Funciones
Globales y Locales
- Cuando declaramos una variable PROGMEM globalmente se hace como hemos dicho antes
const prog_uint8_t a = 1;
- Cuando es una variable local de una función en los compiladores AVR IAR C y AVR GCC se tiene que poner static.La función setup y loop de Arduino son funciones, por tanto si declaramos variables PROGMEM tenemos que hacerlo como sigue
static const porg_uint8_t a =1;