PROGMEM

Almacena datos en la memoria flash (memoria de programa) en lugar de la  SRAM. En este enlace hay una descripción de varios tipos de memoia disponibles en una placa Arduino.
La palabra clave PROGMEM es un nodificador de variable, debe ser usada solo con los tipos de datos definidos en la biblioteca pgmspace.h. Se le dice al compilador "poner esta información en la memoria flash", en lugar de en la SRAM, donde normalmente iría.
PROGMEM es parte de la biblioteca pgmspace.h que está disponible solo en la arquitectura AVR. Por lo que primero necesita incluir la biblioteca en la parte superior de su boceto, como esto:
#include <avr/pgmspace.h>

Sintaxis

const dataType variableName[] PROGMEM = {data0, data1, data3...};
  • - dataType - cualquier tipo de variable
  • - variableName - el nombre de nuesto dato o matriz

Tenga en cuenta que debido a que PROGMEM es un modificador de la variable, no hay ninguna regla dura y rápida acerca de donde debe ir, por lo que el compilador de Arduino acepta todas las definiciones de más abajo, que también son sinónimos. Sin embargo los experimentos han indicado que, en varias versiones de Arduino (que tienen que ver con la versión de GCC), PROGMEM puede trabajar en un lugar y no en otro. El ejemplo "tabla de cadenas" siguiente ha sido probado para trabajar con Arduino 13. Las versiones anteriores del IDE pueden funcionar mejor si se incluye PROGMEM después del el nombre de la variable.
const dataType variableName[] PROGMEM = {};   // usar este formato
const PROGMEM  dataType  variableName[] = {}; // o este formato
const dataType PROGMEM variableName[] = {};   // no usar este
Mientras que PROGMEM podría ser utilizado con una sola variable, realmente sólo vale la pena el trabajo si se tiene un bloque más grande de datos que necesitan ser almacenados, que suele ser más fácil en una matriz, (u otra estructura de datos C más allá de nuestra presente discusión) .
El uso de PROGMEM es un procedimiento de dos pasos. Después de obtener los datos en la memoria Flash, que requiere métodos especiales (funciones), también definidas en la biblioteca pgmspace.h leemos de  nuevo los datos de la memoria de programa en SRAM, por lo que podemos hacer algo útil con él.

Ejemplo

El siguiente fragmento de código ilustra como podemos leer y escribir caracteres (bytes) e ints (2 bytes) en PROGMEM.
#include <avr/pgmspace.h>

//guarda algunos ints sin digno
const PROGMEM  uint16_t charSet[]  = { 65000, 32796, 16843, 10, 11234};

// guarda algunos caracteres
const char signMessage[] PROGMEM  = {"YO SOY PREDATOR, COMBATIENTE INVISIBLE . CREADO POR EL DEPARTAMENTO DE LOS ESTADOS UNIDOS"};

unsigned int displayInt;
int k;    // contador de la variable
char myChar;


void setup() {
  Serial.begin(9600);
  while (!Serial);

  // aquí se pone el código de setup para ejecutar una sola vez:
  // lee de nuevo un int de 2 bytes
  for (= 0; k < 5; k++)
  {
    displayInt = pgm_read_word_near(charSet + k);
    Serial.println(displayInt);
  }
  Serial.println();

  //lee de nuevo un caracter
  int len = strlen_P(signMessage);
  for (= 0; k < len; k++)
  {
    myChar =  pgm_read_byte_near(signMessage + k);
    Serial.print(myChar);
  }

  Serial.println();
}

void loop() {
  // aquí ponemos el código principal que se ejecuta repetidamente:

}

Matriz de cadenas

A menudo es conveniente cuando se trabaja con grandes cantidades de texto, como un proyecto con una pantalla LCD, configurar una matriz de cadenas. Debido a que las cadenas en sí son arrays, esto es en realidad un ejemplo de una matriz de dos dimensiones.
Estas tienden a ser grandes estructuras para su puesta en memoria de programa que a menudo es deseable. El código siguiente ilustra la idea.

/*
 Demo de PROGMEM con cadenas
 Como almacenar una tabla de cadenas en la memoria de programa (flash),
y recuperarles después

 Información redumida de:
 http://www.nongnu.org/avr-libc/user-manual/pgmspace.html

 La creación de una tabla (array)de cadenas en la memoria de programa es algo complicado pero
 aquí tenemos una plantilla para hacerlo.

 La configuración de las cadenas es un proceso de dos pasos. Primero definimos las cadenas
*/

#include <avr/pgmspace.h>
const char string_0[] PROGMEM = "String 0";   // "String 0" etc son cadenas a guardar .
const char string_1[] PROGMEM = "String 1";
const char string_2[] PROGMEM = "String 2";
const char string_3[] PROGMEM = "String 3";
const char string_4[] PROGMEM = "String 4";
const char string_5[] PROGMEM = "String 5";


// Después definir una tabla para referirse a nuestras cadenas.

const char* const string_table[] PROGMEM = {string_0, string_1, string_2, string_3, string_4, string_5};

char buffer[30];    // asegurarse de que esto es lo suficiente grande para la mayor cadena

void setup()
{
  Serial.begin(9600);
  while(!Serial);
  Serial.println("OK");
}

void loop()
{

  /* El uso de una tabla de cadenas en la memoria de programa necesita funciones especiales para recuperar       los datos.
     La función strcpy_P  copia una cadena desde el espacio de programa a una cadena en la RAM         ("buffer").
     Asegurarse de que la cadena recibida en la RAM  es tan grande como para alojar cualquier cadena     recuperada del espacio de memoria */


  for (int i = 0; i < 6; i++)
  {
    strcpy_P(buffer, (char*)pgm_read_word(&(string_table[i]))); // Necessary casts and dereferencing, just copy.
    Serial.println(buffer);
    delay( 500 );
  }
}
Noa

Tenga en cuenta que las variables deben definirse como globales, o definidas con la palabra clave static, para poder trabajar con PROGMEM.
El siguiente código no trabajará dentro de una función:
const char long_str[] PROGMEM = "Hola, me gustaría contarles un poco acerca de mí mismo.\n";
El siguiente código funciona, incluso si está definido a nivel local dentro de una función:
const static char long_str[] PROGMEM = "Hola, me gustaría contarles un poco acerca de mí mismo.\n"

La macro F()

Cuando una instrucción similar a esta :
Serial.print("Escribe algo en el Monitor Serie");
se utiliza, la cadena que se va a imprimir se guarda normalmente en la memoria RAM. Si el sketch imprime un montón de cosas en el monitor serie, puede llenar fácilmente la memoria RAM. Si tenemos espacio libre en la memoria FLASH, fácilmente podemos indicar que la cadena debe estar guardada en flash utilizando la sintaxis:
Serial.print(F("Escribe algo en el monitor de serie que se almacena en FLASH"));


No hay comentarios:

Publicar un comentario