Exceso de consumo de RAM con LCDs

Que tal gente, hace rato que vengo programando LCDs con PICs Microchip y compilador MikroC.
Y hace tambien desde entonces que tengo un problema de RAM al utilizarlos. Aunque no se si es un problema, o algo perfectamente normal y esperable.

Mi duda puntualmente es la siguiente:

Resulta que para mostrar textos en el LCD (utilizando tanto las librerias de MicroC o unas hechas por uno mismo) inebitablemente se tiene que escribir ese texto en algun lado... con variables tipo Char, o cadenas de Char (String)... pero sea como sea que lo camuflemos en el lenguaje de alto nivel (C), para el compilador, eso significa memoria RAM... mucha memoria RAM... Entonces e ahi el problema... si queres hacerte una interface en tu LCD con un menu rico y minimamente extenso, olvidate... no se puede... enseguida te quedas sin RAM...

Ejemplo con las librerias de MicroC:

Lcd_Out_Cp("¡ Bienvenido !"); <----- esto ocupa 15 Bytes de RAM.... 15 ! (un Byte por caracter) Cuando en un 16F628A solo tenemos 208 Bytes disponibles... Le salen las cuentas? Si, solo podriamos escribir menos de 14 lineas de texto distintas... Y, jaja, olvidate de crear variables de cualquier tipo para manejar tus datos... No hay espacio para ellas en el mundo de las librerias para LCDs... toda la RAM es para tu LCD... ¬¬ (Disculpen el tono ironico, es a causa de la frustracion... jaja)

La vengo piloteando de la manera que puedo... pero no me quedan lindas cosas... si quiero tener variedad de textos trato de guardar en una unica variable las palabras que mas se repiten y llamarlas como funcion... .pero eso me consume mas ROM... y asi estamos en un tire y afloje entre ROM y RAM... y ni hablar que el codigo queda hecho una chanchada... un asco...

Recurro al foro por que me ilumine (?) y dije, "no! no puede ser esto asi!" "seguro tiene que haber una forma mas eficiente y prolija de laburar con LCDs..." jaja...

Asi que por favor... acudo a la experiencia e informacion sobre el tema que tengan... por favor demuestrenme que soy un tonto y estoy manejandome muy mal.... que habia una forma mucho mejor de hacer esas cosas que no estoy viendo.

Gracias y saludos!
 
El problema que comentas viene motivado porque los PIC no tienen punteros a ROM. Por lo tanto para poder manejar arrays de constantes las copian a RAM y usan punteros a RAM. Eso consume mucha ROM y mucha RAM.
Soluciones:
a) Usar la EEPROM, aunque tampoco es muy grande, se pueden guardar las cadenas en ella y ir leyendo caracter a caracter y mandándolo al display. No hay cadenas no hay consumo.
pseudocódigo:
#rom 0x2100={"hola"};
Puntero=0;
Dato=i2c_read(Puntero++);
DisplayLCD(Dato);
b) Usar la directiva const:
const char Msg[14]="Hola a todos";
Esto hace que el array se guarde SOLO en ROM, pero limita las cosas que puedes hacer con los datos, esto no podrías hacerlo:
char *Puntero;
Puntero=&Msg[0];
Porque los datos están en ROM que es un espacio de memoria distinto y un puntro a RAM no puede alcanzarlos.
Yo uso CCS, pero el problema viene derivado del diseño del PIC, supongo que será extensible a todos los compiladores.
Si programas en RAM con tablas retlw entonces lo ves claro
 
Ya probaste la ultima version de mikroC, la 5.4, resulta que yo cuando use por primera ves mikroC "version 3.0" el archivo hex lo genera enorme aun con todo y la supuesta optimizacion, en fin lo deje y cuando probe la version 5.4 con el mismo codigo lo genera mucho mejor.
 
Te paso la función que utilizo yo para solucionar este problema, también uso mikroC:

Código:
void LCDRAM(char fila, char col, const char *dat)
{
     while(*dat)
     {
         Lcd_Chr(fila, col++, *dat++);
     }
}

i para utilizarlo:

LCDRAM(1,6,"MENU:");

Prueba i verás como baja ;)
Un saludo
 
Bueno, primero que todo gracias a todos por responder, me es de gran ayuda sus opiniones.

La verdad que lo primero que voy a hacer es hacerle caso a "Ajna" e instalarme la ultima version de MikroC.

Luego te pregunto "tannke", podrias explicarme un poco como funciona esa funcion?? pasa que aun no comprendo bien dos cosas; los punteros *, y las variables const.... estas aplicando en parte lo que dijo "heli" no?? Le pregunto a "heli" tambien de paso.

Por ejemplo, expliquenme los de los punteros respondiendome la siguiente pregunta ¿que diferencia hay entre las siguientes declaraciones?

const char *dat;
const char dat[];

Eso siempre me confundio... :S

Saludos!
 
Última edición:
Con
const char *dat;
se declara una variable que se llama dat y que permite apuntar a unos datos en ROM
no reservamos espacio para los datos, solo para la variable que los apunta mientras que en
const char dat[10];
reservamos espacio para 10 datos en ROM, pero no una variable que los apunte.
En PIC, como ya he comentado, esto presenta bastantes problemas por la inexistencia de microinstrucciones para manejar punteros a ROM (a la zona de código).
 
Te dejo la dirección de un pdf con la explicación de los punteros.
http://www.iisa.com.ar/images/contenidos/pointersc.pdf

Sobre la función.
-El const char *dat; ya te lo explicó heli.

-Con el "while(*dat)", con esto conseguimos no salir del while hasta que dat no apunte a una dirección con contenido 0 o null, (al pasar "MENU:" estamos pasando la dirección donde está M)
dir 0 = M
dir 1 = E
dir 2 = N
dir 3 = U
dir 4 = :
dir 5 = \0 (este caracter se agraga automaticamente al tratar "strings")

- Con col++ pasamos el valor de col y después se incrementa este.

- Con *dat++ pasamos el contenido de la constante donde apunta "dat" y después incrementamos la dirección donde apunta.

- Al llegar a la "dirección 6" con contenido null(0) sale del bucle while.

Esto es todo, espero no haber metido la pata con la explicación, yo también ando algo flojo con los punteros.

Un saludo
 
Ah listo, gracias "tannke", lei el apunte que me pasaste y ya entendi bien lo de los punteros :)... Soy feliz.

Ahora, lo que me confundia era la expresion *dat++.

Por lo que entendi, *dat es el contenido del registro a donde apunta la direccion contedida en el puntero dat. Por lo que si yo hago *dat = 0 estoy poniendo el numero cero en la direccion a la que apunta dat, pero si yo hago dat = 0 estoy haciendo que *dat ahora sea el contenido que hay en la direccion cero.

Entonces, por intuicion, yo entiendo que la expresion *dat++ devuelve el valor contenido en la direccion dat y luego hace *dat = *dat + 1, lo que estaria haciendo que el contenido del registro a donde apunta la direccion contedida en el puntero dat se incremente en uno, NO que el puntero dat se incremente en uno... Para lograr esto yo haria (por intuicion nuevamente) dat++, esto si haria dat = dat + 1 (ademas de anteriormente haber devuelto la direccion contedida en dat)

Pero encambio, segun la funcion que me pasaste y tu explicacion, *dat++ si devuelve el valor contenido en dat PERO luego hace dat = dat + 1, en lugar de hacer *dat = *dat + 1 cosa que va contra mi sentido comun y nunca se me hubiera ocurrido... :S

Por ejemplo, yo hubiera logrado el mismo codigo de la siguiente forma:

Código:
void LCDRAM(char fila, char col, const char *dat) 
{      
       while(*dat) 
       {          
              Lcd_Chr(fila, col++, *dat); 
              dat++;
       } 
}
Me explico?
Estoy bien? Estoy mal?

PD: duda, funciona el operador & para punteros en MikroC? Ej: &var devuelve la direccion de la variable var.
 
Última edición:
Atrás
Arriba