TODOPIC

Otros Microcontroladores / Dispositivos programables => Microcontroladores 8 bits => Mensaje iniciado por: JCAK en 03 de Octubre de 2010, 19:42:29

Título: PROGMEM .... dificil de entender
Publicado por: JCAK en 03 de Octubre de 2010, 19:42:29
Hola a todos

Estoy tratando de entender el uso del PROGMEM pero cuanto más leo mas me confundo.

Una de las cosas que me tiene confundido es por ejemplo la siguiente:

**** Ejemplo 1
const prog_char PROGMEM message_00[] PROGMEM = "HOLA";
const prog_char PROGMEM message_01[] PROGMEM = "PRUEBA";

**** Ejemplo 2
const prog_uint8_t PROGMEM sprite_00[] = {
    0x18,    // ___XX___
    0x3C,    // __XXXX__
    0x7E,    // _XXXXXX_
    0xDB,    // X_XXXX_X
    0xFF,    // XXXXXXXX
  };

**** Ejemplo 3
const uint8_t LcdCustomChar[] PROGMEM=//define 8 custom LCD chars
{
   0x00, 0x1F, 0x00, 0x00, 0x00, 0x00, 0x1F, 0x00, // 0. 0/5 full progress block
   0x00, 0x1F, 0x10, 0x10, 0x10, 0x10, 0x1F, 0x00, // 1. 1/5 full progress block
   0x00, 0x1F, 0x18, 0x18, 0x18, 0x18, 0x1F, 0x00, // 2. 2/5 full progress block
   0x00, 0x1F, 0x1C, 0x1C, 0x1C, 0x1C, 0x1F, 0x00, // 3. 3/5 full progress block
   0x00, 0x1F, 0x1E, 0x1E, 0x1E, 0x1E, 0x1F, 0x00, // 4. 4/5 full progress block
   0x00, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x00, // 5. 5/5 full progress block
   0x03, 0x07, 0x0F, 0x1F, 0x0F, 0x07, 0x03, 0x00, // 6. rewind arrow
   0x18, 0x1C, 0x1E, 0x1F, 0x1E, 0x1C, 0x18, 0x00  // 7. fast-forward arrow
};


Son tres maneras de definir algo que deseo guardar en memoria, pero no entiendo las diferencias en el modo de almacenarlas.
Las tipo CHAR (ej.1) tienen "" y supongo que esto es asi de simple de interpretar, pero las de tipo UINT veo que en algunos casos estan linea por linea (ej.2), y en otros, cada linea tiene multiples valores (ej.3)


Yo deseo definir un sprite de 5x5 bit y enviarlo bit pot bit

  43210
A 01111
B 10000
C 10000
D 10000
E 01111


Primero envio A0, luego B0, C0, D0, E0
Segundo envio A1, luego B1, C1, D1, E1



¿Alguien me puede orientar o ayudar?


Saludos y gracias


Título: Re: PROGMEM .... dificil de entender
Publicado por: fabianjsm en 03 de Octubre de 2010, 20:22:37
PROGMEM especifica que la variable pertenece a la flash.
Podes definir asi:

Código: C
  1. const unsigned char sprite[] = {
  2.              //    43210
  3.     0x0F,  // A 01111
  4.     0x10, // B 10000
  5.     0x10, // C 10000
  6.     0x10, // D 10000
  7.     0x0F  // E 01111
  8. };
  9.  
  10. //.... despues te recorres el sprite...
  11.  
  12. int i, msk;
  13. for(i=0; i<5; i++) {
  14.     for(msk=1; msk<32; msk<<=1) {
  15.         int bit = sprite[i] & msk? 1: 0;
  16.     }
  17. }
Título: Re: PROGMEM .... dificil de entender
Publicado por: jonathanPIC888 en 03 de Octubre de 2010, 22:12:50
fabianjm  como vos definis "const unsigned char" aunque te parezca mentira te consume RAM.
Una solución para liberar la RAM es la siguiente:

Código: C
  1. #include <avr/io.h>     // Definiciones de hardware.
  2. #include <util/delay.h> // Librería para generar retardos.
  3. #include <avr/pgmspace.h> // Librería para trabajar con la memoria flash
  4.                           // del microcontrolador.
  5.  
  6. const char sprite[5] PROGMEM= {
  7. 0x0F, 0x10,0x10, 0x10,0x0F  };
  8.  
  9. int i; // Variable auxiliar.
  10.  
  11. for(i=0;i<=4;i++) {
  12.  
  13.       PORTB = pgm_read_byte(&sprite[i]); // Te muestra los valores en el puerto B cada 250ms.
  14.  
  15.           _delay_ms(250);
  16.    
  17.          }
Título: Re: PROGMEM .... dificil de entender
Publicado por: fabianjsm en 03 de Octubre de 2010, 23:06:24
Realmente no tenia ese dato, habia considerado que por ser const estaria en la flash  :(
Gracias jonathanPIC888!
Título: Re: PROGMEM .... dificil de entender
Publicado por: JCAK en 03 de Octubre de 2010, 23:09:36
HOLA FABIAN

La verdad que te agradezco un montón que me estés dando esta mano.
Probé el código y el tema es que el valor se lee de manera secuencial, por ejemplo: A0,A1,A2,A3,A4,B0,B1,B2,B3,B4,C0,C1,C2,C3,C4, etc.
Y yo necesito leerlo A0,B0,C0,D0,E0,A1,B1,C1,D1,E1,A2,B2,C2,D2,E2, etc.

¿Me darías una mano para poder hacerlo en ese orden?


Yo después veo como hago para resolver lo del PROGMEM, pero me serìa de gran ayudar que me puedas pasr esto porque me facilitaría entender lo que leo de la memoria.


Mil gracias de verdad




PROGMEM especifica que la variable pertenece a la flash.
Podes definir asi:

Código: C
  1. const unsigned char sprite[] = {
  2.              //    43210
  3.     0x0F,  // A 01111
  4.     0x10, // B 10000
  5.     0x10, // C 10000
  6.     0x10, // D 10000
  7.     0x0F  // E 01111
  8. };
  9.  
  10. //.... despues te recorres el sprite...
  11.  
  12. int i, msk;
  13. for(i=0; i<5; i++) {
  14.     for(msk=1; msk<32; msk<<=1) {
  15.         int bit = sprite[i] & msk? 1: 0;
  16.     }
  17. }

Título: Re: PROGMEM .... dificil de entender
Publicado por: fabianjsm en 03 de Octubre de 2010, 23:30:50
Podes intercambiar la linea 13 por la 14 del codigo anterior, para invertir el orden de los bucles, quedaria asi:

Código: C
  1. for(msk=1; msk<32; msk<<=1) {
  2.   for(i=0; i<5; i++) {

Título: Re: PROGMEM .... dificil de entender
Publicado por: JCAK en 03 de Octubre de 2010, 23:44:24
JonathanPIC888
Fabianjm

IDOLOS !!!!
Entre el código de Fabianjm y entre el modo para leer la Flash que paso Jonathan pude lograrlo.
GRACIAS mil gracias !!!!!


Una pregunta más si no es mucho preguntar ...
En un sitio leí un codigo en el cual usan memcpy_P para pasar el dato de la Flash a la SRAM y luego lo leen de ahí ¿tienen idea para qué conviene usarlo así en lugar de leerlo directo de la flash?


Saludos y muchas gracias como siempre

 :-/
Título: Re: PROGMEM .... dificil de entender
Publicado por: debora en 04 de Octubre de 2010, 10:13:39
Claro que podes leer directamente de la flash, pero si queres trabajar con los datos (concatenar, operar, modificar, etc.) te conviene que este en la sram, por eso lo moves antes.
Título: Re: PROGMEM .... dificil de entender
Publicado por: jonathanPIC888 en 04 de Octubre de 2010, 11:40:38
Es por una cuestion de comodidad y rapidez. Leer la flash quizas te tome "1ms" para darte un ejemplo....y leer el mismo dato de la RAM te tome "50ns"....para algunas aplicaciones críticas puede resultar necesario mover los datos de la flash a la memoria RAM.

Me alegro que te haya sido de ayuda  :-/ :-/
Título: Re: PROGMEM .... dificil de entender
Publicado por: JCAK en 04 de Octubre de 2010, 22:43:44
Hola una vez más ... perdón pero estoy confundido con el Shift dentro del FOR y no se como debo modificarlo para lograr lo siguiente:

En este código se hace una lectura de la martiz en el siguiente orden: A0,B0,C0,D0,E0,A1,B1,C1,D1,E1,A2,B2,C2,D2,E2,etc.
¿Cómo hay que modificarlo apra que lo lea en este otro orden: A4,B4,C4,D4,E4,A3,B3,C3,D3,E3,A2,B2,C2,D2,E2,etc.

¡Alguien me podrá ayudar con la solución o a entender este FOR?


Muchísimas gracias por adelantado.



Código: [Seleccionar]
const unsigned char sprite[] = {
          //   43210
    0x0F, // A 01111
    0x10, // B 10000
    0x10, // C 10000
    0x10, // D 10000
    0x0F  // E 01111
}

int i, msk;
for(msk=1; msk<32; msk<<=1) {
    for(i=0; i<5; i++)
        int bit = sprite & msk? 1: 0;
    }
}


.
Título: Re: PROGMEM .... dificil de entender
Publicado por: JCAK en 05 de Octubre de 2010, 10:13:29
Enviado por Fabian en MP:

Creo que con esto voy encaminando, pero me queda una pregunta .... ahí va


Código: [Seleccionar]
Hola, disculpa, deberia haber comentado las lineas de código.
El valor 32 es una máscara.
Si tengo por ejemplo una variable llamada dato, al realizar la operación
dato & 0x01
obtengo como resultado 0x01 si el bit menos significativo es 1, o cero en otro caso.
Para evaluar el segundo bit menos significativo, realizo la operacion
dato & 0x02
dato & 0x04 … para el tercer bit,
dato & 0x08 … el cuarto bit, y asi sigue...
Siempre obtento el valor de la máscara si el bit evaluado es 1, o cero en otro caso.
Los valores que va tomando la máscara en binario son:
0x01 → 0000 0001 → 1
0x02 → 0000 0010 → 2
0x04 → 0000 0100 → 4
0x08 → 0000 1000 → 8
0x10 → 0001 0000 → 16
0x20 → 0010 0000 → 32
Lo que se observa que el el uno se va desplazando a la izquierda.
Si evaluamos desde el bit 0 hasta el bit 4, la máscara tomara los valores 1, 2, 4, 8 y 16, de modo que iremos desplazando hacia la izquierda mientras la máscara sea menor que 32 (de ahí sale):

El FOR 'for(msk=1; msk<32; msk<<=1)' se podria leer así:
Para msk=1, mientras msk<32, desplazar msk a la izquierda.

En cuanto al último parametro del FOR, donde se suele incrementar la variable de control con el operador ++, en C se puede realzar cualquier operación e incluso se permite no hacer nada, cerrando el paréntesis inmediatamente después del punto y coma.

Un WHILE(expresion) es equivalente a FOR(;expresion;), lo que puedes hacer con un WHILE podras hacer con un FOR, y viceversa.



Hola Fabián
Gracias por el tutorial ..  :)

Anoche me la pase tratando de entenderlo y hoy a la mañana creia tener el panorama más claro, y luego de leer lo que enviaste estaba en lo correcto.
Estaba con el 32 dando vuelta hasta que pude verlo en binario, ese era mi problema.

32-16-8-4-2-1
 1  0 0 0 0 0


Con 16 se cumplen las 5 columnas que tengo en el sprite.

Ahora bien, a causa de esta confución creia que el msk=1 era en binario y hoy con algunas horas de descanso me doy cuenta que es en decimal ¿es correcto lo que entiendo?

O sea, pregunto ¿Yo debería hacer un sentencia asi para poder leer desde 5 bit hacia el 1?:
FOR 'for(msk=16; msk>=1; msk>>=1)'

No estoy seguro, por favor, podrias decirme si es asi para poder invertir el orden de lectura, empezar a leer desde el 5 bit hacia el 1, en lugar de leer desde el 1 al 5 como es actualmente.


Gracias

Título: Re: PROGMEM .... dificil de entender
Publicado por: fabianjsm en 05 de Octubre de 2010, 14:02:17
Es correcto JCAK, msk iniciará valiendo 16 y terminará valiendo 1.

Código: C
  1. for(msk=16; msk; msk>>=1)
Título: Re: PROGMEM .... dificil de entender
Publicado por: cristian_elect en 05 de Octubre de 2010, 14:48:10
Prueba con esta función que hace los ambos sentidos.   bueno es una idea no es la solución.
A.0 B.0 ......

 const unsigned char *e;
 char salida,b,sentido=0;
 while(sentido<2){
  for(b=0;b<5;b++){
    e=sprite;
    for(char a=0;a<5;a++){
     if(sentido==0)
      salida=((*e++) & 1<<b)?1:0;
     else
      salida=((*e++) & 1<<(4-b))?1:0;
    }
  }
  sentido++;
 }
Título: Re: PROGMEM .... dificil de entender
Publicado por: cristian_elect en 12 de Octubre de 2010, 20:04:38
Publica la solucion para los demas.