TODOPIC

Microcontroladores PIC => Lenguaje C para microcontroladores PIC => Mensaje iniciado por: drago109 en 31 de Enero de 2011, 12:18:51

Título: Ayuda con lcd
Publicado por: drago109 en 31 de Enero de 2011, 12:18:51
Buenas amigos del foro. Ante todo me presento ya que soy nuevo en el foro, asi que espero sus ayuda y ayudarles en el futuro.

Bueno este es el tema. Tengo un tiempito en programacion  y aprendio lo mas basico y algunas otras cosas pero en este caso quisiera saber algo que es nuevo para mi y me hurge ya que estoy fabricando una estacion de reballing para mi taller.

Lo que quiero es que alguien me ayude a entender como puedo colocar en un display LCD 4x20 los numeros grande. Para ler una entrada ADC y medir temperatura. E visto algunos tema como http://www.todopic.com.ar/foros/index.php?topic=16408.0
pero no logro entender.

Que me quede como el de este video pero claro midiendo temperatura y personalizado a mi manera pero la lectura la quiero como ese.
feature=related

Graciass. Espero sus ayuda
Título: Re: Ayuda con lcd
Publicado por: mariano_pic en 31 de Enero de 2011, 13:11:28

  Bueno, pero tienes algo adelantado? Por lo menos el esquema, ponlo aca para ver como se hace, yo uso mikroc y puedo ayudarte si usas ese, el ccs hace rato que no lo uso, pero lo pienso retomar en estos dias.
Título: Re: Ayuda con lcd
Publicado por: drago109 en 31 de Enero de 2011, 16:34:47
Gracias mariano por tu repuesta. La verdad es que ya lo tengo echo y trabajando en la estacion  pero ahora me encuentro modificandolo ya que les cambie los modo de lectura y le coloque los amplificadores analogico para termocuplas ad595. Por eso es que quiero modificar el modo de la LCD por los numeros que los vi super. Pero nunca e tocado ese tema con las LCD.  Trabajo con CCS Compiler pero si lo sabes esplicame algo que hay por lo menos agarro la idea.

Este es el programa y ajuntado el completo con proteus.

#include <16F876.h>
#device adc=10
#fuses XT,NOWDT

#use delay(clock=4000000)

#include <lcd416.c>
#include <internal_eeprom.c>

#BYTE TRISA = 0x85
#BYTE PORTA = 0x05

#define up1 pin_a2
#define down1 pin_a3
#define up2 pin_a4
#define down2 pin_a5
#define buzer pin_c5
#define pcb pin_c4
#define gpu pin_c3

void main(){

   int16 q;
   float cupla_pcb,cupla_gpu,g_pcb,g_gpu;
   
   bit_set (TRISA,2);
   bit_set (TRISA,3);
   bit_set (TRISA,4);
   bit_set (TRISA,5);
   
   setup_adc_ports(RA0_ANALOG);
   setup_adc(ADC_CLOCK_INTERNAL);
   
lcd_init();
lcd_gotoxy(1,1);
lcd_putc("   DRAGO109\n");
lcd_putc("<<<PROYECTOS>>>>\n");
lcd_putc("Estacion Reflow\n");
lcd_putc(" Control ON/OFF");
delay_ms(3000);
lcd_putc("\f");

      g_pcb=read_float_eeprom(0x00);
      g_gpu=read_float_eeprom(0x04);

   for (;;){
   set_adc_channel(0);
   delay_us(20);
   q = read_adc();
   cupla_pcb = 401.0 * q / 1024.0;
   
   set_adc_channel(1);
   delay_us(20);
   q = read_adc();
   cupla_gpu = 401.0 * q / 1024.0;
   
   lcd_gotoxy(1,1);
   printf(lcd_putc,"__PCB__");
   lcd_gotoxy(1,2);
   printf(lcd_putc, "T=%01.0fC ", cupla_pcb);
   
   lcd_gotoxy(8,1);
   printf(lcd_putc, "I___GPU__");
   lcd_gotoxy(8,2);
   printf(lcd_putc, "I  T=%01.0fC ", cupla_gpu);
   
   if(!input(up1)){
   delay_ms(150);
   if(g_pcb>=200)
      g_pcb=200;
      else
      g_pcb+=1; }
     
   if(!input(down1)){
   delay_ms(150);
      if(g_pcb<=0)
      g_pcb=0;
      else
      g_pcb-=1; }
     
    if(!input(up2)){
    delay_ms(150);
    if(g_gpu>=320)
    g_gpu=320;
    else
    g_gpu+=1; }
   
    if(!input(down2)){
    delay_ms(150);
    if(g_gpu<=0)
    g_gpu=0;
    else
    g_gpu-=1; }
   
    if(cupla_pcb>=g_pcb){
    output_low(pcb);}
    if(cupla_pcb<=g_pcb){
    output_high(pcb);}
   
    if(cupla_gpu>=g_gpu){
    output_low(gpu);}
    if(cupla_gpu<=g_gpu){
    output_high(gpu);}
   
   if(!input(up1)){
    output_high(buzer);
    delay_ms(50);
    output_low(buzer);}
   
    if(!input(down1)){
    output_high(buzer);
    delay_ms(50);
    output_low(buzer);}
   
   if(!input(up2)){
    output_high(buzer);
    delay_ms(50);
    output_low(buzer);}
   
    if(!input(down2)){
    output_high(buzer);
    delay_ms(50);
    output_low(buzer);}
   
   lcd_gotoxy(1,3);
   printf(lcd_putc, "Ajuste");
   lcd_gotoxy(1,4);
   printf(lcd_putc, "T=%01.0fC ", g_pcb);
   write_float_eeprom(0x00,g_pcb);
   
   lcd_gotoxy(8,3);
   printf(lcd_putc, "I  Ajuste");
   lcd_gotoxy(8,4);
   printf(lcd_putc, "I  T=%01.0fC ", g_gpu);
   write_float_eeprom(0x04,g_gpu);
   
    } while (true);
   delay_ms(100);
 }

Título: Re: Ayuda con lcd
Publicado por: MGLSOFT en 31 de Enero de 2011, 17:03:30
Algo asi quieres hacer ??

(http://img132.imageshack.us/img132/1286/digitosgrandesenlcd.jpg)
Título: Re: Ayuda con lcd
Publicado por: MGLSOFT en 31 de Enero de 2011, 17:08:57
O tal vez esto otro ??

(http://img810.imageshack.us/img810/969/bignum2x4lcd.jpg)

Si es así escribe en tu buscador web:  Bignum LCD
Título: Re: Ayuda con lcd
Publicado por: mariano_pic en 31 de Enero de 2011, 17:12:35

  Bueno en ccs es mas complicado, mikroc tiene un plugin que permite hacer todo eso. pero como ya esta listo voy a bajar el archivo para hacerlo yo tambien mas adelante. Saludos.
Título: Re: Ayuda con lcd
Publicado por: MGLSOFT en 31 de Enero de 2011, 17:15:20
No es tan complejo, hay que generar caracteres en la CGRam del LCD y después llamarlos de a uno y por fila.

Esa es la técnica para hacerlo, si miras con detenimiento, no hay mas de 8 caracteres diferentes, siempre mirando por lineas y columnas, se entiende??
 :mrgreen:
Título: Re: Ayuda con lcd
Publicado por: mariano_pic en 31 de Enero de 2011, 17:16:39


  Gracias por los datos mglsoft lo tendre en cuenta, un saludo.
Título: Re: Ayuda con lcd
Publicado por: MGLSOFT en 31 de Enero de 2011, 17:41:52
En el subforo de C, yo puse un ejemplo hace ya mucho tiempo, con la librería completa para usar un LCD 2x16 con números grandes, y el ejemplo para probarlo.
Si los descomprimen en una carpeta, pueden verlo en Proteus.

No es la librería que ven en el ejemplo que puse, la que hoy utilizo, pero pueden sacar la experiencia de allí, sin problemas.
Eso es mucho mas que lo que yo tuve de información inicial para hacerlo...je..je.. :D :D :D
Título: Re: Ayuda con lcd
Publicado por: drago109 en 31 de Enero de 2011, 18:12:46
Gracias MGLSOFT. Eso es exaptamente lo que quiero hacer y la pagina esta buena. Aun no entiendo mucho pero voy a intentar hacer algo y ver si me sale. Voy a buscar tu post  ya que no lo e visto.
Título: Re: Ayuda con lcd
Publicado por: drago109 en 31 de Enero de 2011, 18:30:56
En el subforo de C, yo puse un ejemplo hace ya mucho tiempo, con la librería completa para usar un LCD 2x16 con números grandes, y el ejemplo para probarlo.
Si los descomprimen en una carpeta, pueden verlo en Proteus.

No es la librería que ven en el ejemplo que puse, la que hoy utilizo, pero pueden sacar la experiencia de allí, sin problemas.
Eso es mucho mas que lo que yo tuve de información inicial para hacerlo...je..je.. :D :D :D


Amigo aun tendras el ejemplo del convertidor A/D que tenias en el subforo c que ya no esta disponible para la descarga.
Título: Re: Ayuda con lcd
Publicado por: mariano_pic en 01 de Febrero de 2011, 11:04:42
En el subforo de C, yo puse un ejemplo hace ya mucho tiempo, con la librería completa para usar un LCD 2x16 con números grandes, y el ejemplo para probarlo.
Si los descomprimen en una carpeta, pueden verlo en Proteus.

No es la librería que ven en el ejemplo que puse, la que hoy utilizo, pero pueden sacar la experiencia de allí, sin problemas.
Eso es mucho mas que lo que yo tuve de información inicial para hacerlo...je..je.. :D :D :D


Amigo aun tendras el ejemplo del convertidor A/D que tenias en el subforo c que ya no esta disponible para la descarga.
 

Mira tres posts mas arriba el amigo MGLSOFT  la puso como adjunto para que la descargues
Título: Re: Ayuda con lcd
Publicado por: MGLSOFT en 01 de Febrero de 2011, 11:08:44
Te pongo el ejemplo con el ADC.
Espero te sirva... :mrgreen: :mrgreen:
Título: Re: Ayuda con lcd
Publicado por: drago109 en 02 de Febrero de 2011, 12:15:15
Te pongo el ejemplo con el ADC.
Espero te sirva... :mrgreen: :mrgreen:

Gracias amigo ya lo tengo en mi programa funcionando de verdad a sido de gran ayuda. Solo tengo 2 consultas mas si no es mucho pedir.

Como ago para realizar esa lectura en un lcd 4x20 que es la que estoy usando pero con los numeros ocupando 2 lineas nada mas.
La otra es como ago para posicionar la lectura en la parte de la pantalla donde la quiero por que con lcd_gotoxy no me funciona siempre sale en el mismo sitio.
Graciass
Título: Re: Ayuda con lcd
Publicado por: drago109 en 06 de Febrero de 2011, 22:54:46
Amigos quisiera que me ayudaran en una cosa mas. Quisiera que me ayudaran a saber como podria retrasar la lectura adc del canal AN0 ya que los cambio de temperatura son rapidos y no se logran ver bien en el lcd, quisiera que lo mostrara cada 1 segundo por ejemplo sin perjudicar el otro canal analogico.

Si alguien sabe seria de mucha ayuda. Saludos
Título: Re: Ayuda con lcd
Publicado por: arielmdq en 05 de Octubre de 2015, 20:37:50
Hola que tal, estoy con este tema de los numeros grandes para lcd 2x16 y estoy queriendo modificar la libreria NumGran.c ,pero no tengo demasiado conocimiento ,la idea es modificar los caracteres que forman los numeros para hacer trazos mas gruesos ,mas o menos me eh dado cuenta como estan formados los caracteres y algunos eh podido cambiar hasta ahora cambié esta parte :
                                                                       
 #rom  0x2100={28,30,30,30,30,30,30,28, //  Media barra lateral derecha.==> Esta quedo como quería
              7,15,15,15,15,15,15,7,  //  Media barra lateral izquierda.           ==> Esta quedo como quería
              31,31,0,0,0,0,0,0,       //  Barra superior sola.                          ==> Esta quedo como quería
              0,0,0,0,0,0,31,31,       //  Barra inferior sola                             
              31,31,0,0,0,0,31,31,     //  Barra superior e inferior.
              31,30,0,0,0,0,0,0,      //  Flecha Izquierda.
              0,0,0,0,0,0,30,31,    //  Flecha Derecha.
              0,0,0,0,0,0,0,0}         //  Vacio.

Pero por lo que veo no aparece ( flecha izquierda) ni ( flecha derecha) ,que en el formato original tampoco aparece ,y la otra cosa es que  los caracteres de la linea de arriba  y los de abajo estan cortados ,le falta la linea de pixeles de abajo pero no me doy cuenta donde tengo que tocar para acomodar esto ,dejo una foto para que se entienda mejor lo que quiero explicar 
https://drive.google.com/file/d/0BwFymA3SNp36V1VUZjZzc3I4Unc/view?usp=sharing
Tampoco entiendo a que es : segmento y grilla 
Si me pueden orientar un poco les estaré agradecido.
                                                                         Saludos !!!
Título: Re: Ayuda con lcd
Publicado por: KILLERJC en 06 de Octubre de 2015, 01:07:46
Citar
Pero por lo que veo no aparece ( flecha izquierda) ni ( flecha derecha) ,que en el formato original tampoco aparece ,y la otra cosa es que  los caracteres de la linea de arriba  y los de abajo estan cortados ,le falta la linea de pixeles de abajo pero no me doy cuenta donde tengo que tocar para acomodar esto ,dejo una foto para que se entienda mejor lo que quiero explicar 

Primero que vos estas guardando los bits de los cuadritos en la memoria del LCD. Eso hace que se pinten como vos quieras. Luego tenes que traducirlo eso lo haces en C, es decir si vos envias con tu programa que escriba un 890. En el mismo programa dice.. MMmm es un 8 y esta primero, entonces debo decir que mueste la barra lateral izquierda aca, la derecha aca y etc etc etc.
Si vos no tenes nada que le indique al programa en C que debe enviar la flecha arriba cuando tiene como entrada $ el programa no va a saber eso.

Eso con respecto a lo de flecha izquierda y derecha. Sobre el caracter cortado no se a cual te referis, y seria bueno si en la imagen lo marcas. o decis donde exactamente.
Título: Re: Ayuda con lcd
Publicado por: arielmdq en 06 de Octubre de 2015, 13:55:09
Hola KILLERJC ,gracias por responder ,voy a intentar explicarme mejor. El primer problema ya se resolvió, yo pensaba que los caracteres estaban cortados o tal vez mal posicionados pero no, eso la hace en proteus solamente .Hoy grabe un pic para probar y salen perfectos :
 https://drive.google.com/file/d/0BwFymA3SNp36bXk3ZlRKZWVYV3M/view?usp=sharing
Si te fijas en la foto que puse ayer, que era de proteus las barras laterales que forman tanto el cero como el uno etc etc, tienen la forma de una D maaaso meeenos  :D .Y a estas les faltaba la parte redondeadita de abajo ,pero bueno era un problema del proteus ya que en la realidad salieron bien .
Ahora el tema de las flechas: en la foto que puse ahora se nota como al numero 2 le falta una parte tanto en el extremo superior como en el inferior que es donde creo yo, que va la flecha que terminaría de completar el numero para que esteticamente se vea mejor .
Estoy usando el programa ejemplo que presento el compañero MGLSOFT que lo adapte para grabarlo en un 16f876a que es el siguiente:

Código: C
  1. #include <16f876a.h>
  2. #device adc=10
  3. #use delay(clock=4000000)
  4. #fuses HS,NOWDT,NOPROTECT,NOLVP,PUT,NODEBUG,BROWNOUT,NOCPD,NOWRT
  5. #include <LCD.C>
  6. #include <NumGran.C>
  7. #use fast_io(B)
  8. #use fast_io(c)
  9. #use fast_io(a)
  10.  
  11. void main()
  12. {
  13.    int16 i;
  14.    set_tris_a (0b00001011);
  15.    output_a(0b00000000);
  16.    set_tris_c (0b01111001);
  17.    output_c(0b00000000);
  18.    // Inicializacion del micro
  19.   setup_adc_ports(AN0_AN1_AN3);
  20.    setup_adc( ADC_CLOCK_INTERNAL );
  21.    set_adc_channel( 0 );
  22.   // setup_psp(PSP_DISABLED);
  23.    setup_spi(FALSE);
  24.    setup_counters(RTCC_INTERNAL,RTCC_DIV_1);
  25.    setup_timer_1(T1_DISABLED);
  26.    setup_timer_2(T2_DISABLED,0,1);
  27.  
  28.    lcd_init();       //Inicializacion del display LCD
  29.  
  30.    // Inicializacion necesaria de la rutina de Numeros Grandes
  31.    NumGran_Init();
  32.  
  33.    WHILE(TRUE)
  34.    {
  35.  
  36.       i = Read_ADC();
  37.       lcd_send_byte(0,1);delay_us(2);  //limpiar LCD - Necesario si
  38.       NumGran(i);          // ademas se quiere escribir en numeros normales
  39.       printf(lcd_putc,"%04lu",i);
  40.       delay_ms(80);      // en las posiciones libres del display LCD
  41.  
  42.       i = Read_ADC();
  43.       delay_ms(300);                  // POSICIONA
  44.       printf(lcd_putc," %04lu    ",i);
  45.  
  46. }
  47. }

Este programa incluye el archivo NumGran.c que es este:

Código: C
  1. #rom  0x2100={16,24,24,24,24,24,24,16, //  Media barra lateral derecha.
  2.               1,3,3,3,3,3,3,1,         //  Media barra lateral izquierda.
  3.               31,31,0,0,0,0,0,0,       //  Barra superior sola.
  4.               0,0,0,0,0,0,31,31,       //  Barra inferior sola
  5.               31,31,0,0,0,0,31,31,     //  Barra superior e inferior.
  6.               2,6,14,30,14,6,2,0,      //  Flecha Izquierda.
  7.               8,12,14,15,14,12,8,0,    //  Flecha Derecha.
  8.               0,0,0,0,0,0,0,0}         //  Vacio.
  9. int8 Digito[4],Segmento[3],Linea;
  10. const int16 Grilla[2][10]={{120,770,740,740,130,147,147,720,140,140},
  11.                           {130,770,137,730,770,730,130,770,130,770}};
  12. //llamada CGRAM a numeros = 0 , 1 , 2 , 3 , 4 , 5 , 6 , 7 , 8 , 9
  13.  
  14. Void Desmembra (int16 Dato);
  15. Void Obtiene_Segmento (int16 Dato);
  16. Void NumGran_Init();
  17.  
  18.  
  19. Void NumGran(int16 Numero)
  20. {
  21.    int Dig;
  22.    Desmembra (Numero);
  23.    for (Linea=1;Linea<3;++Linea)
  24.    {
  25.       switch (Linea)
  26.       {
  27.          Case 1: for (Dig=0;Dig<4;++Dig){
  28.             Obtiene_Segmento (Grilla[0][Digito[Dig]]);
  29.             printf(LCD_PUTC,"%C%C%C",Segmento[2],Segmento[1],Segmento[0]);
  30.          } break;
  31.          Case 2: printf(LCD_PUTC,"\n"); for (Dig=0;Dig<4;++Dig){
  32.             Obtiene_Segmento (Grilla[1][Digito[Dig]]);
  33.             printf(LCD_PUTC,"%C%C%C",Segmento[2],Segmento[1],Segmento[0]);
  34.          } break;
  35.       }
  36.    }
  37. }
  38.  
  39. Void Desmembra (int16 Dato)      //Esta funcion obtiene el valor de los
  40. {                             // digitos a enviar al display
  41.    Digito[0] = Dato/1000; Dato = Dato%1000;
  42.    Digito[1] = Dato/100;  Dato = Dato%100;
  43.    Digito[2] = Dato/10;   Dato = Dato%10;
  44.    Digito[3] = Dato;
  45. }
  46.  
  47. Void Obtiene_Segmento (int16 Dato)  //Esta funcion obtiene el valor de los
  48. {                                // segmentos a enviar al display
  49.    Segmento[2] = Dato/100;  Dato = Dato%100;
  50.    Segmento[1] = Dato/10;   Dato = Dato%10;
  51.    Segmento[0] = Dato;
  52. }
  53.  
  54. Void NumGran_Init()
  55. {
  56.    int8 posicion;
  57.    lcd_send_byte(0x00,0x40);                 // apunta al inicio de la CGRAM y
  58.    for(posicion=0;posicion<=63;++posicion)   //carga los caracteres en la CGRAM
  59.    lcd_send_byte(1,Read_eeprom(posicion));   //traidos de la EEPROM del PIC
  60. }

Al cual yo le modifique solo la parte de la rom que muestro en el psot de arriba .Esto funciono bien ya que los caracteres se ven con trazos mas gruesos ,pero ahora la parte que me falta es la de las flechas .segun como escribió mglsoft en la rom el codigo para las flechas :            
                                                                                                                                  2,6,14,30,14,6,2,0,      //  Flecha Izquierda.
                                                                                                                                  8,12,14,15,14,12,8,0,    //  Flecha Derecha
Deberia salir esto:
https://drive.google.com/file/d/0BwFymA3SNp36WHRwN0FkYzFKSm8/view?usp=sharing
Pero esto es lo que no sale
Entonces algunas preguntas serían:
Como forma los numeros ? Entiendo que esta es la grilla de numeros
const int16 Grilla[2][10]={{120,770,740,740,130,147,147,720,140,140},
                                    {130,770,137,730,770,730,130,770,130,770}};
Pero no entiendo a que hacen referencia estos numeros ? supongo que el 120 forma la parte superior del cero y el 130 la parte inferior ,sera asi?pero de donde salen ?

por que no salen las flechas si es que estas son parte de los numeros ? (correccion en el PD, no son parte de los numeros)
Por que forma el caracter "Vacio" para que sirve ?
Bueno espero haberme explicado correctamente y disculpen tantas preguntas, pero me gustaria aprender a manejar los numero grandes a gusto ,para poder cambiarle las formas.
                                                                                                  Saludos!!!!!


PD : anoche en medio del sueño me di cuenta de algo, las flechas no son para formar parte de los numeros ya que ocupan casi un caracter completo y el numero perderia la forma  asi que la pregunta sería como poder usar los dos caracteres que ocupan las flechas en hacer 2 caracteres mas pequeños para poder darle forma a los numeros, osea como habría que llamar a estos caracteres para que formen parte de los numeros.
                                                                         
Título: Re: Ayuda con lcd
Publicado por: KILLERJC en 07 de Octubre de 2015, 09:11:51
Tendrias que haber seguido el programa :P, te lo voy a poner de otra forma para que lo entiendas.

Respecto a como se dibujan los segmentos:

Código: C
  1. #rom  0x2100={16,24,24,24,24,24,24,16, //  Segmento 0 - Media barra lateral derecha.
  2.                    1, 3, 3, 3, 3, 3, 3, 1, //  Segmento 1
  3.                   31,31, 0, 0, 0, 0, 0, 0, //  Segmento 2
  4.                    0, 0, 0, 0, 0, 0,31,31, //  Segmento 3
  5.                   31,31, 0, 0, 0, 0,31,31, //  Segmento 4
  6.                    2, 6,14,30,14, 6, 2, 0, //  Segmento 5
  7.                    8,12,14,15,14,12, 8, 0, // Segmento 6
  8.                    0, 0, 0, 0, 0, 0, 0, 0} // Segmento 7 - Vacio.
  9.  
  10. const int16 Grilla[2][10]={{120,770,740,740,130,147,147,720,140,140},
  11.                           {130,770,137,730,770,730,130,770,130,770}};
  12. //llamada CGRAM a numeros = 0 , 1 , 2 , 3 , 4 , 5 , 6 , 7 , 8 , 9

El array Grilla  son 2 vectores de 10 posiciones, cada vector es una linea del LCD.
Es decir Grilla[0] indice la primer linea del LCD y Grilla[1] la segunda linea.

Si necesitas representar por ejemplo el 1, Observamos Grilla y dice que Grilla[0][1] es 770 y Grilla[1][1] es 770, presta atencion a las centenas,decenas y unidades, ahora vamos a ver los segmentos. El 7 es vacio y el 0 es "Media barra lateral derecha.", entonces que va a dibujar?

1era linea: vacio vacio barra
2da  linea: vacio vacio barra

Ahi tenes tu 1 en numeros grandes. En resumen, si quieres agregarle el cuadrito al 2 deberias editar Grilla. buscar el del 2, cambiarle las centenas a la primera linea y las unidades en la segunda, para facilitarte la vida, ahi le puse una n asi te das cuenta donde esta:

Código: C
  1. const int16 Grilla[2][10]={{120,770,n40,740,130,147,147,720,140,140},
  2.                           {130,770,13n,730,770,730,130,770,130,770}};
  3. //llamada CGRAM a numeros = 0 , 1 , 2 , 3 , 4 , 5 , 6 , 7 , 8 , 9

Cambiar las flechas

Si no vas a utilizar esas flechas podes cambiarlas bit a bit es como un gran array de 5x8 en el que lo que tiene un 1 es un pixel negro. Suponete Flecha Izquierda.

             2,6,14,30,14,6,2,0,      //  Flecha Izquierda.

Representado en hexadecimal

             0x02,0x06,0x0E,0x1E,0xE,0x06,0x02,0x00,      //  Flecha Izquierda.

Representado en binario, y puesto verticalmente:

0 0 0 1 0 = 0x02 , recorda que el 1 es el pixel en negro
0 0 1 1 0 = 0x06
0 1 1 1 0 = 0x0E
1 1 1 1 0
0 1 1 1 0
0 0 1 1 0
0 0 0 1 0
0 0 0 0 0
Título: Re: Ayuda con lcd
Publicado por: arielmdq en 07 de Octubre de 2015, 17:40:50
Buenisimo KILLERJC ,me hicistes ver la luz  :-/  :D :D :D muchas gracias !!!!! excelente explicacion !!!! ya mostraré los resultados.

                                                                                         Saludos!!!!
Título: Re:Ayuda con lcd
Publicado por: arielmdq en 10 de Octubre de 2015, 19:21:20
Hola que tal , estuve probando la manera de cambiar la forma de los numeros grandes,gracias a la explicacion de KILLERJC, y me funcionó correctamente con el programa de ejemplo ,peeeero........  :D siempre tengo un pero ,cuando se lo implemente a mi programa
que es un cuenta vueltas y horimetro me encontré con una sorpresa: en mi programa estoy guardando datos en varias posiciones de memoria ,respetando el archivo de numeros grandes, que dice que no se puede grabar en las primeras 64 posiciones ya que estas estan ocupadas para los numeros grandes .
Y lo que me ocurre es que mientras no apague el pic ,puedo guardar mis datos y todo funciona perfecto ,pero cuando lo apago y lo vuelvo a encender le faltan partes a los numeros grandes o aparecen pixeles sueltos ,que pude ser ?
Este es mi programa :
Código: [Seleccionar]
#include <16f876a.h>
#device adc=10
#use delay(clock=4000000)
#fuses HS,NOWDT,NOPROTECT,NOLVP,PUT,NODEBUG,BROWNOUT,NOCPD,NOWRT
#include <lcd.c>
#include <NumGran.C>
#include <internal_eeprom.c>
#use fast_io(B)
#use fast_io(c)
#use fast_io(a)

//****variables del cuneta vueltas***//
int16 contador=0,RPM,i;
float ajuste=10,e;       
//****variables del cuneta horas***//
int8 Segundos=0,SegundosParcial=0,Minuto=0,MinutoParcial=0;
int menu=0,sw;
int16 b,service=1,corte, Hora=0,cont=0, HoraParcial=0,mantenimiento=0;

//*********Funciones**************************
int menus(void)
{
if (input(pin_c2)==1)
{   
  if (menu==0)  //Cambia a programacion
    return('1');
  if (menu==1)  //Info proximo service
    return('2');   
  if (menu==2)  //Cambia el tiempo del proximo service
    return('3'); 
  if (menu==3)  //Calibra RPM
    return('4');
  if (menu==4)  //Reset cuenta horas toatl
    return('5');
  if (menu==5)  //Reset cuenta horas parcial
    return('6');
  if (menu==6)  //Vuelve al comienzo del menu
    return('7');   
}
}

void corte_alimentacion(void) // si la alimentacion es menor que 4,5 Volt
 { if (corte<920)            // Guarda valores en eeprom
       {
          write_int16_eeprom(0x227, Hora);
          delay_ms(15);
          write_int16_eeprom(0x230, HoraParcial);
          delay_ms(15);         
          write_eeprom(0x236, Minuto);
          delay_ms(15);
          write_eeprom(0x238, MinutoParcial);
          delay_ms(15);
       }
 }
 
#int_timer1
void timer1_isr(void)
{  cont++;
  if (cont==2)
  {
   contador=get_timer0();
   set_timer0(0);
   cont=0;
   if (rpm>600)
   {
    Segundos++;
    SegundosParcial++;
  }
//*********Cuenta Horas Total**********************************/         
      if(Segundos == 60)
      {
          Minuto++;
          Segundos=0;
             
      if(Minuto == 60)
       {
          Hora++;
          Minuto=0;
       }
      }
/**********Cuenta Horas Parcial*********************************/
      if(SegundosParcial == 60)
      {           
          MinutoParcial++;
          SegundosParcial=0;
             
      if(MinutoParcial == 60)
       {
         
          HoraParcial++;
          MinutoParcial=0;
       }
      }   
  }
   set_timer1(3036);
   
}
//***************************************************
void main()


   set_tris_a(0b00010011);
   output_a  (0b00000000);
    set_tris_c(0b01111110);
   output_c  (0b00000000);
   
   setup_timer_0(rtcc_ext_h_to_l | rtcc_div_2);
   setup_timer_1(t1_internal | t1_div_by_8);
   
   set_timer0(0);
   set_timer1(3036);
   enable_interrupts(int_timer1);
   enable_interrupts(global);

 //****************ADC**************************
   setup_adc_ports(AN0_AN1_AN3);
   setup_adc (ADC_CLOCK_INTERNAL);
   
 //*************Lectura de eeprom *****************************
   Hora=read_int16_eeprom(0x227);
   delay_ms(15);
   HoraParcial=read_int16_eeprom(0x230);
   delay_ms(15); 
   Minuto=read_eeprom(0x236);
   delay_ms(15);
   MinutoParcial=read_eeprom(0x238);
   delay_ms(15);
   e=read_float_eeprom(0x240);
   delay_ms(15);
   service=read_int16_eeprom(0x245);
   delay_ms(15);
   mantenimiento=read_int16_eeprom(0x250);
   delay_ms(15);
//*************************************************************
    lcd_init();
    NumGran_Init();       
     lcd_gotoxy(1,1);           
      lcd_putc("    PROYECTO    \n RPM Y HORIMETRO ");           
      delay_ms(2000);               
 
      lcd_gotoxy(1,1);           
      lcd_putc(" GRACIAS TODOPIC \n    SALUDOS!!!   ");         
      delay_ms(2000);             

      lcd_putc("\f");
 
   while(1)
    {

       
         set_adc_channel(1);     //Lee la tension de alimentacion
         delay_ms(10);          // del pic ,si baja de 4,5volt
         corte=read_adc();     //
         corte_alimentacion();// actua esta funcion
         
         mantenimiento=read_int16_eeprom(0x250);
         delay_ms(15);
         
          service=read_int16_eeprom(0x245);
         delay_ms(15);
         e=read_float_eeprom(0x240);
         delay_ms(15);                             
         RPM= contador*e;       
         

      if (input(pin_c2)==0)        // Funcionamiento normal
     {       
          menu=0;
      if ( Minuto<mantenimiento)// ATENCION: cambiar Minuto por horas
      {

      output_low(pin_c7);
      i =RPM;
      lcd_send_byte(0,1);delay_us(2);
      NumGran(i);         
      printf(lcd_putc,"RPM");
      delay_ms(80);     

      i = RPM;
      delay_ms(300);                 
      printf(lcd_putc," %04lu    ",i);     
         
      if(input(pin_c6))
      {
         delay_ms(50);
      while(input(pin_c6)==0);
         
                       
         lcd_gotoxy(1,1);                       
         printf(lcd_putc,"    RPM %lu       " ,RPM);     
 
         lcd_gotoxy(1,2);
         printf(lcd_putc,"Par  %05lu:%02u:%02u",HoraParcial,MinutoParcial,SegundosParcial);
         delay_ms(3000);
         
         lcd_gotoxy(1,2);
         printf(lcd_putc,"Tot  %05lu:%02u:%02u",Hora,Minuto,Segundos);
         delay_ms(3000);
     
     
      }
      }
     
     
//********************************************************************************     
     if ( Minuto>=mantenimiento&&mantenimiento>0)//ATENCION cambiar Minuto por horas
      { 
       
        output_high(pin_c7); // Aviso luminoso de mantenimiento     
        lcd_gotoxy(1,1);                   //           
        lcd_putc("    ATENCION    \n  MANTENIMIENTO ");
                                 
        if (input(pin_c6))
       {   delay_ms(50);
       while(input(pin_c6)==0);//hasta q no suelta no graba
       
         mantenimiento=mantenimiento+1;
         write_int16_eeprom(0x250,mantenimiento);  // escribe en la memoria
         delay_ms(15);                           // tiempo para escritura
         lcd_gotoxy(1,1);                       //           
         lcd_putc("   SE POSPUSO   \n    + 1 HORA    ");
         delay_ms(2000);
         lcd_gotoxy(1,1);                   //           
         lcd_putc("INGRESE AL MENU \n PARA CAMBIARLO ");
         delay_ms(2000);
       
      } 
     }
     }//cierra funcionamiento normal
     
 /***********************ENTRA AL  MENU*************************************/
 
  if (input(pin_c2)==1)//
 {      menus();
         
     
        if (input(pin_c3)==1)
       {   delay_ms(50);
       while(input(pin_c3));
        {
           menu++; 
       if (menu>7)
           menu=0;             
        }           
       }
       
    sw=menus();     
   switch (sw)
   {
     case '1':
              lcd_gotoxy(1,1);
              printf(lcd_putc," Uds A INGRESADO \n     AL MENU    ");
              delay_ms(1000);
              menu++;
              break;
     case '2':         
              service=read_int16_eeprom(0x245);
              delay_ms(15);
              lcd_gotoxy(1,1);
              printf(lcd_putc,"Proximo Service \n   %4lu Horas     ",service);
             
              break;
                 

     case '3':                             //Service

              lcd_gotoxy(1,1);
              printf(lcd_putc,"Programe Service");
             
              if (input(pin_c4)==1)   
             {    delay_ms(50);       // antirebote
              while(input(pin_c4)); 
                    b+=1;         
             }
             if (input(pin_c5)==1)  // Boton que decrementa
             { delay_ms(50);
              while(input(pin_c5));
                    b-=1;
             }
             
             lcd_gotoxy(1,2);
             printf(lcd_putc,"   Horas  %4lu    ",b);
             
             if (input(pin_c6)==1)
             { delay_ms(50);
              while(input(pin_c6));           
               write_int16_eeprom(0x245, b);  // escribe en la memoria
               delay_ms(25);
               service=read_int16_eeprom(0x245);
               delay_ms(15);
               mantenimiento=Minuto+service;//ATENCION cambiar Minuto por hora
               write_int16_eeprom(0x250,mantenimiento);  // escribe en la memoria
               delay_ms(15);               
               mantenimiento=read_int16_eeprom(0x250);
               delay_ms(15);
               lcd_gotoxy(1,1);
               printf(lcd_putc,"     PROXIMO    \nMANT:%05lu Horas   ",mantenimiento ) ;
               delay_ms(2000);
             }
              break;
             
     case '4':                               //CALIBRA RPM
              e=read_float_eeprom(0x240);
              delay_ms(15);
              RPM= contador*e;
              lcd_gotoxy(1,1);
              printf(lcd_putc,"Actual RPM %lu       ",RPM);
              if (input(pin_c4)==1)
             {   
                   delay_ms(150);                   
                   ajuste+=0.02;          // Incremento
             }
             if (input(pin_c5)==1)
             {   
                 delay_ms(150);
                 ajuste-=0.02;        //Decremento 
             }             
             if (input(pin_c6)==1)
             { delay_ms(50);
              while(input(pin_c6));           
               write_float_eeprom(0x240, ajuste); 
               delay_ms(15); 
             }               
              RPM= contador*ajuste;
              lcd_gotoxy(1,2);
              printf(lcd_putc,"Ajuste RPM %lu       ",RPM);       
              break;
               
     case '5':                               
              lcd_gotoxy(1,1);
              printf(lcd_putc,"   RESET TOTAL    ");
              lcd_gotoxy(1,2);
              printf(lcd_putc,"   %05lu:%02u:%02u  ",Hora,Minuto,Segundos);
              if (input(pin_c6)==1) // Reset de cuenta horas parcial
               {  delay_ms(100);
                  Hora=00000;
                  write_int16_eeprom(0x227, Hora);
                  delay_ms(15);
                  Minuto=00;
                  write_eeprom(0x236, Minuto);
                  delay_ms(15);
              }
              break; 
 
             
     case '6':
              lcd_gotoxy(1,1);
              printf(lcd_putc,"  RESET PARCIAL    ");
              lcd_gotoxy(1,2);
              printf(lcd_putc,"   %05lu:%02u:%02u  ",HoraParcial,MinutoParcial,Segundos);
              if (input(pin_c6)==1) // Reset de cuenta horasparcial
               {  delay_ms(50);
                  HoraParcial=00000;
                  write_int16_eeprom(0x230, HoraParcial);
                  delay_ms(15);               
                  MinutoParcial=00;
                  write_eeprom(0x238, MinutoParcial);
                  delay_ms(15);
               }
              break;               
      case '7':
               menu=1;
               break;
   }       
 }         
    }
}
Esta es la foto como se ven los numeros correctamente:
https://drive.google.com/file/d/0BwFymA3SNp36SXJNMGVUbHRmNFU/view?usp=sharing

Y estas  despues de quitar la alimentacion y volver a conectarlo :
https://drive.google.com/file/d/0BwFymA3SNp36T3pBZk5rRUZtLU0/view?usp=sharing
https://drive.google.com/file/d/0BwFymA3SNp36QlJ1VkFFQmMxV1k/view?usp=sharing

                                                                                        Saludos!!!!!

Título: Re:Ayuda con lcd
Publicado por: KILLERJC en 10 de Octubre de 2015, 19:50:43
Tal ves estes equivocandote de direccion xD

Código: C++
  1. Hora=read_int16_eeprom(0x227);
  2.    delay_ms(15);
  3.    HoraParcial=read_int16_eeprom(0x230);
  4.    delay_ms(15);
  5.    Minuto=read_eeprom(0x236);
  6.    delay_ms(15);
  7.    MinutoParcial=read_eeprom(0x238);
  8.    delay_ms(15);
  9.    e=read_float_eeprom(0x240);
  10.    delay_ms(15);
  11.    service=read_int16_eeprom(0x245);
  12.    delay_ms(15);
  13.    mantenimiento=read_int16_eeprom(0x250);
  14.    delay_ms(15);

0x250 no es lo mismo que el byte 250, 0x250 es igual a 592 y tu memoria tiene solo 256 bytes :P. El byte 250 es 0xFA , pero podes usar decimales en esa funcion sin problemas.
Otra cosa que vi solo al comienzo (ya que no vi todo el programa):

Código: C++
  1. if (menu==0)  //Cambia a programacion
  2.     return('1');
  3.   if (menu==1)  //Info proximo service
  4.     return('2');  
  5.   if (menu==2)  //Cambia el tiempo del proximo service
  6.     return('3');
  7.   if (menu==3)  //Calibra RPM
  8.     return('4');
  9.   if (menu==4)  //Reset cuenta horas toatl
  10.     return('5');
  11.   if (menu==5)  //Reset cuenta horas parcial
  12.     return('6');
  13.   if (menu==6)  //Vuelve al comienzo del menu
  14.     return('7');

Por

Código: C++
  1. return (menu+'1');      //Suponiendo que menu sea solamente numeros de 0 a 7 , sino vas a tener que agregar un if(menu<7) si es que es unsigned

En la interrupcion del timer1 intenta poner el valor mas al comienzo, asi de esa forma hay menos errores, ya que al cargarlo al final no estas teniendo en cuenta todas las lineas entre medio y suma al tiempo, incluso deberias usar el modulo CCP para mayor precision, me refiero a esta linea:

Código: C++
  1. set_timer1(3036);

El corte de la alimentacion deberias hacerlo en una interrupcion del ADC por ejemplo o por flanco segun tu hardware, ya que ahi en el while corres riesgo de que se quede enviando al LCD y no llegue a guardar.
Especialmente cuando estas teniendo delays de 100us o mas dentro del menu. Otra cosa espero que no grabe demasiado la memoria sino la vas a terminar rompiendo.

Bueno son unas cosa que vi apenas comenzo el programa hasta llegar ahi, no segui mas adelante.
Título: Re:Ayuda con lcd
Publicado por: arielmdq en 10 de Octubre de 2015, 20:39:11
Muchas gracias KILLERJC ,hasta ahora hice los cambios que me dijiste y todo funciona ,por ahora en simulacion, pero lo de la memoria seguro que era eso  :5] como se me paso ese detalle  :mrgreen: ,.
No puedo creer como se simplifico la funcion del menu  :D  el que sabe sabe ......
Me quedó una duda con lo que me decis de grabar mucho en la memoria ,y quiero contarte la manera en que pense el programa a ver si esta bien: en la memoria solo voy a grabar los parametros una sola vez ,cuando se instale el instrumento.Luego hice la funcion corte para que cuando el adc detecte menos de 4,5 volt  me guarde los datos de la hora y minutos parcial y total y hasta ahora funciona bien esto ya lo probé y alcanza a guardar los datos cuando le quito la alimentacion al pic  , pero ahora me entra la duda si solo me esta grabando en la eeprom cuando baje la tension de 4,5 volt o constantemente ? ya que si se me paso por alto de confundir hexa con decimal  :D cualquier cosa me podria pasar  :oops:
Voy a ver la manera que me decis de detectar un flanco para grabar en la memoria a ver como me funciona ,si me sale jaja
Para contar los pulsos tenia un programa hecho con CCP ,pero se me ponia muy inestable la lectura  por eso decidí usar este metodo ,de todos modos como ya sabes yo no se mucho de esto solo me funcionó asi   ;-)
Bueno te agradezco muchisimo la ayuda ya te estaré contando los resultados
                                                                                                                            Saludos!!!!
Título: Re:Ayuda con lcd
Publicado por: KILLERJC en 10 de Octubre de 2015, 20:47:06
Citar
No puedo creer como se simplifico la funcion del menu  :D  el que sabe sabe ......

Y podes simplificarla aun mas, yo creo que eso vos lo haces por el tema de que en tus switch case usas '1','2','3' esos son caracteres ASCII, 0x31 , 0x32 , 0x33 respectivamente.

Citar
    sw=menus();     
   switch (sw)
   {
     case '1':

Si hubieras realizado simplemente asi:

Citar
   switch (menu+1)
   {
     case 1:

Hubiera sido mas corto, el tema es que preguntas por la entrada esa.. y tal ves tengas que cambiar otra parte del programa. Poniendole un if antes.
Bue mi idea no fue complicarte la vida, solo ver que estabas haciendo mucho para sacar poco provecho. Y no termine de ver el programa. Asi que puede haber aun mas. Proba lo de la direccion de memoria y luego contas como te fue
Título: Re:Ayuda con lcd
Publicado por: arielmdq en 11 de Octubre de 2015, 23:06:03
Hola Killerjc, no me complicas para nada ,todo lo contrario me estas enseñando un monton la idea es ir aprendiendo de a poco y te agradezco mucho  ;-)
Te cuento que probé lo de la memoria y funciona bien asi que era eso nomas  .Estuve chequeando todo el programa otra vez y descubrí un par de errores ,cosas que en realidad no hacian nada ja ja, implemente lo del switch y dentro de la funcion corte saque el if de ahi y lo puse dentro del while, seguro debe haber mucho por mejorar pero hasta ahora asi funciona cualquier correccion bienvenida sea ,dejo el programa correjido.
                Saludos!!!
Código: C++
  1. #include <16f876a.h>
  2. #device adc=10
  3. #use delay(clock=4000000)
  4. #fuses HS,NOWDT,NOPROTECT,NOLVP,PUT,NODEBUG,BROWNOUT,NOCPD,NOWRT
  5. #include <lcd.c>
  6. #include <NumGran.C>
  7. #include <internal_eeprom.c>
  8. #use fast_io(B)
  9. #use fast_io(c)
  10. #use fast_io(a)
  11.  
  12. //****variables del cuneta vueltas***//
  13. int16 contador=0,RPM,i;
  14. float ajuste=10,e;      
  15. //****variables del cuneta horas***//
  16. int8 Segundos=0,SegundosParcial=0,Minuto=0,MinutoParcial=0;
  17. int menu=0;
  18. int16 b,service=1,corte, Hora=0,cont=0, HoraParcial=0,mantenimiento=0;
  19.  
  20. //*********Funciones**************************
  21. int menus(void)
  22. { return (menu+'1');
  23.  
  24. }
  25.  
  26. void corte_alimentacion(void) // si la alimentacion es menor que 4,5 Volt
  27.  {
  28.           write_int16_eeprom(100, Hora);
  29.           delay_ms(15);
  30.           write_int16_eeprom(110, HoraParcial);
  31.           delay_ms(15);          
  32.           write_eeprom(120, Minuto);
  33.           delay_ms(15);
  34.           write_eeprom(130, MinutoParcial);
  35.           delay_ms(15);      
  36.  }
  37.  
  38. #int_timer1
  39. void timer1_isr(void)
  40. {  cont++;
  41.   if (cont==2)
  42.   {
  43.    contador=get_timer0();
  44.    set_timer0(0);
  45.    set_timer1(3036);
  46.    cont=0;
  47.    if (rpm>600)
  48.    {
  49.     Segundos++;
  50.     SegundosParcial++;
  51.   }
  52. //*********Cuenta Horas Total**********************************/        
  53.       if(Segundos == 60)
  54.       {
  55.           Minuto++;
  56.           Segundos=0;
  57.              
  58.       if(Minuto == 60)
  59.        {
  60.           Hora++;
  61.           Minuto=0;
  62.        }
  63.       }
  64. /**********Cuenta Horas Parcial*********************************/
  65.       if(SegundosParcial == 60)
  66.       {          
  67.           MinutoParcial++;
  68.           SegundosParcial=0;
  69.              
  70.       if(MinutoParcial == 60)
  71.        {
  72.          
  73.           HoraParcial++;
  74.           MinutoParcial=0;
  75.        }
  76.     }  
  77.   }    
  78. }
  79. //***************************************************
  80. void main()
  81. {  
  82.  
  83.    set_tris_a(0b00010001);
  84.    output_a  (0b00000000);
  85.     set_tris_c(0b01111110);
  86.    output_c  (0b00000000);
  87.    
  88.    setup_timer_0(rtcc_ext_h_to_l | rtcc_div_2);
  89.    setup_timer_1(t1_internal | t1_div_by_8);
  90.    
  91.    set_timer0(0);
  92.    set_timer1(3036);
  93.    enable_interrupts(int_timer1);
  94.    enable_interrupts(global);
  95.  
  96.  //****************ADC**************************
  97.    setup_adc_ports(AN0_AN1_AN3);
  98.    setup_adc (ADC_CLOCK_INTERNAL);
  99.    
  100.  //*************Lectura de eeprom *****************************
  101.    Hora=read_int16_eeprom(100);
  102.    delay_ms(15);
  103.    HoraParcial=read_int16_eeprom(110);
  104.    delay_ms(15);  
  105.    Minuto=read_eeprom(120);
  106.    delay_ms(15);
  107.    MinutoParcial=read_eeprom(130);
  108.    delay_ms(15);
  109.    e=read_float_eeprom(140);
  110.    delay_ms(15);
  111.    service=read_int16_eeprom(150);
  112.    delay_ms(15);
  113.    mantenimiento=read_int16_eeprom(160);
  114.    delay_ms(15);
  115. //*************************************************************
  116.     lcd_init();
  117.     NumGran_Init();      
  118.      lcd_gotoxy(1,1);          
  119.       lcd_putc("    PROYECTO    \n RPM Y HORIMETRO ");          
  120.       delay_ms(2000);              
  121.  
  122.       lcd_gotoxy(1,1);          
  123.       lcd_putc(" GRACIAS TODOPIC \n    SALUDOS!!!   ");        
  124.       delay_ms(2000);            
  125.  
  126.       lcd_putc("\f");
  127.  
  128.    while(1)
  129.     {
  130.  
  131.        
  132.          set_adc_channel(0);     //Lee la tension de alimentacion
  133.          delay_ms(10);          // del pic ,si baja de 4,5volt
  134.          corte=read_adc(); //
  135.          if (corte<920)            // Guarda valores en eeprom
  136.        {
  137.         corte_alimentacion();// actua esta funcion
  138.        }
  139.          mantenimiento=read_int16_eeprom(160);
  140.          delay_ms(15);
  141.          
  142.           service=read_int16_eeprom(150);
  143.          delay_ms(15);
  144.          e=read_float_eeprom(140);
  145.          delay_ms(15);                              
  146.          RPM= contador*e;      
  147.          
  148.  
  149.       if (input(pin_c2)==0)        // Funcionamiento normal
  150.      {        
  151.           menu=0;                 // vuelve a cero el menu
  152.       if ( Minuto<mantenimiento)// ATENCION: cambiar Minuto por horas
  153.       {
  154.  
  155.       output_low(pin_c7);
  156.       i =RPM;
  157.       lcd_send_byte(0,1);delay_us(2);
  158.       NumGran(i);          
  159.       printf(lcd_putc,"RPM");
  160.       delay_ms(80);    
  161.  
  162.       i = RPM;
  163.       delay_ms(300);                  
  164.       printf(lcd_putc," %04lu    ",i);    
  165.          
  166.       if(input(pin_c6))
  167.       {
  168.          delay_ms(50);
  169.       while(input(pin_c6));
  170.          
  171.                        
  172.          lcd_gotoxy(1,1);                      
  173.          printf(lcd_putc,"    RPM %lu       " ,RPM);      
  174.  
  175.          lcd_gotoxy(1,2);
  176.          printf(lcd_putc,"Par  %05lu:%02u:%02u",HoraParcial,MinutoParcial,SegundosParcial);
  177.          delay_ms(3000);
  178.          
  179.          lcd_gotoxy(1,2);
  180.          printf(lcd_putc,"Tot  %05lu:%02u:%02u",Hora,Minuto,Segundos);
  181.          delay_ms(3000);
  182.      
  183.      
  184.       }
  185.       }
  186.      
  187.      
  188. //********************************************************************************      
  189.      if ( Minuto>=mantenimiento&&mantenimiento>0)//ATENCION cambiar Minuto por horas
  190.       {  
  191.        
  192.         output_high(pin_c7); // Aviso luminoso de mantenimiento    
  193.         lcd_gotoxy(1,1);                   //          
  194.         lcd_putc("    ATENCION    \n  MANTENIMIENTO ");
  195.                                  
  196.         if (input(pin_c6))
  197.        {   delay_ms(50);
  198.        while(input(pin_c6));//hasta q no suelta no graba
  199.        
  200.          mantenimiento=mantenimiento+1;
  201.          write_int16_eeprom(160,mantenimiento);  // escribe en la memoria
  202.          delay_ms(15);                           // tiempo para escritura
  203.          lcd_gotoxy(1,1);                       //          
  204.          lcd_putc("   SE POSPUSO   \n    + 1 HORA    ");
  205.          delay_ms(2000);
  206.          lcd_gotoxy(1,1);                   //          
  207.          lcd_putc("INGRESE AL MENU \n PARA CAMBIARLO ");
  208.          delay_ms(2000);
  209.        
  210.       }  
  211.      }
  212.      }//cierra funcionamiento normal
  213.      
  214.  /***********************ENTRA AL  MENU*************************************/
  215.  
  216.   if (input(pin_c2))//si es igual a 1
  217.  {      menus();
  218.          
  219.      
  220.         if (input(pin_c3))
  221.        {   delay_ms(100);
  222.        while(input(pin_c3));
  223.         {
  224.            menu++;  
  225.        if (menu>7)
  226.            menu=0;            
  227.         }          
  228.        }
  229.            
  230.    switch (menu+1)
  231.    {
  232.      case  1:
  233.               lcd_gotoxy(1,1);
  234.               printf(lcd_putc," Uds A INGRESADO \n     AL MENU    ");
  235.               delay_ms(1000);
  236.               menu++;
  237.               break;
  238.      case  2 :          
  239.               service=read_int16_eeprom(150);
  240.               delay_ms(15);
  241.               lcd_gotoxy(1,1);
  242.               printf(lcd_putc,"Proximo Service \n   %4lu Horas     ",service);
  243.              
  244.               break;
  245.                  
  246.  
  247.      case  3 :                             //Service
  248.  
  249.               lcd_gotoxy(1,1);
  250.               printf(lcd_putc,"Programe Service");
  251.              
  252.               if (input(pin_c4))    
  253.              {  
  254.                   delay_ms(300);       // antirebote              
  255.                   b+=1;        
  256.              }
  257.              if (input(pin_c5))  // Boton que decrementa
  258.              {
  259.                  delay_ms(300);
  260.                  b-=1;
  261.              }
  262.              
  263.              lcd_gotoxy(1,2);
  264.              printf(lcd_putc,"   Horas  %4lu    ",b);
  265.              
  266.              if (input(pin_c6))
  267.              { delay_ms(50);
  268.               while(input(pin_c6));            
  269.                write_int16_eeprom(150, b);  // escribe en la memoria
  270.                delay_ms(25);
  271.                service=read_int16_eeprom(150);
  272.                delay_ms(15);
  273.                mantenimiento=Minuto+service;//ATENCION cambiar Minuto por hora
  274.                write_int16_eeprom(160,mantenimiento);  // escribe en la memoria
  275.                delay_ms(15);              
  276.                mantenimiento=read_int16_eeprom(160);
  277.                delay_ms(15);
  278.                lcd_gotoxy(1,1);
  279.                printf(lcd_putc,"     PROXIMO    \nMANT:%05lu Horas   ",mantenimiento ) ;
  280.                delay_ms(2000);
  281.              }
  282.               break;
  283.              
  284.      case  4 :                               //CALIBRA RPM
  285.               e=read_float_eeprom(140);
  286.               delay_ms(15);
  287.               RPM= contador*e;
  288.               lcd_gotoxy(1,1);
  289.               printf(lcd_putc,"Actual RPM %lu       ",RPM);
  290.               if (input(pin_c4))
  291.              {  
  292.                   delay_ms(300);                    
  293.                   ajuste+=0.02;          // Incremento
  294.              }
  295.              if (input(pin_c5))
  296.              {  
  297.                  delay_ms(300);
  298.                  ajuste-=0.02;        //Decremento  
  299.              }              
  300.              if (input(pin_c6))
  301.              { delay_ms(50);
  302.               while(input(pin_c6));            
  303.                write_float_eeprom(140, ajuste);  
  304.                delay_ms(15);  
  305.              }              
  306.               RPM= contador*ajuste;
  307.               lcd_gotoxy(1,2);
  308.               printf(lcd_putc,"Ajuste RPM %lu       ",RPM);        
  309.               break;
  310.                
  311.      case  5 :                                
  312.               lcd_gotoxy(1,1);
  313.               printf(lcd_putc,"   RESET TOTAL    ");
  314.               lcd_gotoxy(1,2);
  315.               printf(lcd_putc,"   %05lu:%02u:%02u  ",Hora,Minuto,Segundos);
  316.               if (input(pin_c6)) // Reset de cuenta horas parcial
  317.                {  delay_ms(50);
  318.                 while(input(pin_c6));
  319.                   Hora=00000;
  320.                   write_int16_eeprom(100, Hora);
  321.                   delay_ms(15);
  322.                   Minuto=00;
  323.                   write_eeprom(120, Minuto);
  324.                   delay_ms(15);
  325.               }
  326.               break;  
  327.  
  328.              
  329.      case  6 :
  330.               lcd_gotoxy(1,1);
  331.               printf(lcd_putc,"  RESET PARCIAL    ");
  332.               lcd_gotoxy(1,2);
  333.               printf(lcd_putc,"   %05lu:%02u:%02u  ",HoraParcial,MinutoParcial,Segundos);
  334.               if (input(pin_c6)) // Reset de cuenta horasparcial
  335.                {  delay_ms(50);
  336.                while(input(pin_c6));
  337.                   HoraParcial=00000;
  338.                   write_int16_eeprom(110, HoraParcial);
  339.                   delay_ms(15);              
  340.                   MinutoParcial=00;
  341.                   write_eeprom(130, MinutoParcial);
  342.                   delay_ms(15);
  343.                }
  344.               break;              
  345.       case  7 :
  346.                menu=1;
  347.                break;
  348.    }        
  349.  }        
  350.     }
  351. }
Título: Re:Ayuda con lcd
Publicado por: KILLERJC en 11 de Octubre de 2015, 23:48:06
el set_timer1() lo pusiste dentro del if del timer1, deberia ir fuera y al comienzo, antes del cont++ . Ya que cuando entra ahi deberia cargarse, si termina no entrando al if no va a cargarse con el valor adecuado. Y la duracion va a ser variable

Respecto al programa hay MUCHOS delays. Especialmente esos delays de 3 segundos o cosas asi que no hacen nada bien. Esto se podria evitar totalmente (y dejar algunos pequeños como el de antirebote de las teclas) si es que lo programas de otra forma. Parecido pero pensando en otra forma. De esta forma que digo tu programa puede responder al instante. Ademas si aprovechas el CCP aun mejor, tendrias la misma interrupcion y no deberias cargar el timer. Pero bueno, hacerlo como te digo implica cambiar mucho, tu programa. Y si asi funciona bien.... que mejor :P, Si por alguna razon deseas crearlo de esta forma postea Aca o crea un nuevo tema y te voy diciendo como hacerlo.
Título: Re:Ayuda con lcd
Publicado por: arielmdq en 13 de Octubre de 2015, 22:49:37
Hola killerjc ,como le pifié al set_timer1()  :D  lo modifique despues de haber hecho la prueba ,par dejar correjido el codigo y lo terminé empeorando   :(  ,de todos modos entiendo por que va donde me decis , gracias.
Ahora encontré un problema peor  :5] ,y es que estaba leyendo el canal (1) del adc y llamando a la funcion corte()  cuando detecte que la tension bajaba de 5v asi guardaba los cuatro datos de horas y minutos parcial y total.Pero en realidad en la placa estaba leyendo el canal (0) no el (1) con lo cual como nunca detectaba tension,me estaba grabando constantemente los valores en la memoria y yo pensaba que estaba funcionando bien por que cuando cortaba la alimentacion efectivamente los valores se guardaban pero no de la manera que yo pensaba ja ja,asique estuve haciendo unas pruebas por hardware pero no me funcionó.Una de las cosas creo que es la manera en que quiero detectar la falta de alimentacion con la funcion corte ,y de aca sale una pregunta :en  un momento me dijiste que debía detectar con el adc un flanco de bajada pero no me doy cuenta con que instruccion debería detectarlo ? o como debería hacer una funcion para hacerlo.O si es algo que hacen comunmente y ya esta todo resuelto de una manera sencilla y justo  a mi se me ocurre inovar  :D :D :D
Con respecto a los delays de 3 seg los puse como en la pantalla solo voy a mostrar las rpm en numeros grandes ,tenga la opcion que pulsando un boton me muestra primero las horas min y seg parcial y luego de 3 seg el total y luego vuelvo a las rpm en numeros grandes. La otra forma de hacerlo que sugeris(es lo que se me ocurre pensar desde mi ignorancia)es en vez de usar los delays usar la base de tiempo que ya voy llevando con los segundos ? .
Con lo de cambiar el programa no tengo problema ya que es la manera de poder aprender y es lo que quiero hacer  :)
Desde que leí tu mensaje ayer que me puse a investigar lo del CCP, yo habia probado con un programa  muy basico a mi estilo :oops:  desde lo que había entendido de como hacerlo   y no me había gustado por el tema de la inestabilidad, como ya te había contado ,pero buscando una manera mejor de hacerlo encontre un ejemplo en la web que adapte para probarlo .Te lo adjunto para ver que te parece.
Código: C
  1. #include <16f876a.h>
  2. #device adc=10
  3. #use delay(clock=4000000)
  4. #fuses HS,NOWDT,NOPROTECT,NOLVP,PUT,NODEBUG,BROWNOUT,NOCPD,NOWRT
  5. #include <lcd.c>
  6. #include <internal_eeprom.c>
  7. #use fast_io(B)
  8. #use fast_io(c)
  9. #use fast_io(a)
  10.  
  11. unsigned int16 ps=0;
  12. unsigned int16 ss=0;
  13. int1 pulso=0, cambiapulso=0;
  14. long frec;
  15.  
  16. #int_CCP1
  17. void  CCP1_isr(void)
  18. {
  19.    if (pulso==0)
  20.    {
  21.       ps=CCP_1;
  22.       pulso=1;
  23.    }
  24.    else
  25.    {
  26.       ss=CCP_1;
  27.       pulso=0;
  28.    if(cambiapulso==0)
  29.    {
  30.       cambiapulso=1;
  31.    }
  32. }
  33. }
  34.  
  35. void main()
  36. {
  37. unsigned int16 tiempo=0;
  38.  
  39.     setup_timer_1(T1_INTERNAL|T1_DIV_BY_1);
  40.    // setup_ccp1(CCP_CAPTURE_DIV_4);
  41.     setup_ccp1(CCP_CAPTURE_RE);
  42.     enable_interrupts(INT_CCP1);
  43.     enable_interrupts(GLOBAL);
  44.     set_timer1(0);
  45.     lcd_init();
  46. while(true)
  47. {
  48.    if (cambiapulso==1)
  49.    {
  50.        disable_interrupts(GLOBAL);
  51.        tiempo=ss-ps;
  52.       // tiempo=tiempo/4;
  53.        frec= 1000000/tiempo;
  54.        lcd_gotoxy(1,1);
  55.        printf(lcd_putc,"   HZ %lu", frec);
  56.        cambiapulso=0;
  57.        enable_interrupts(global);
  58.    }
  59. }
  60. }
Con respecto a esto tengo la duda si puedo lograr estabilidad contando cada flanco o cada 4 flancos o 16 o no se logra estabilidad con variar esto.Bueno te agradezco mucho la ayuda .
                                                                                  Saludos !!!
 PD: en el programa solo estoy leyendo frecuencia ,si funciona bien haré los calculos para sacar las RPM
Título: Re:Ayuda con lcd
Publicado por: KILLERJC en 13 de Octubre de 2015, 23:32:16
No tengo CCS para probarlo, no me gusta por otra parte. utilizo XC8, asi que los codigos que ponga con funciones de CCS por favor tomalos con pinza.

CCP
Yo lo decia por el Timer1. Vos normalmente haces:

set_timer1(3036);

asi el timer cuenta: 62500 ciclos, cuando cuenta eso el Timer1 pasa de 0xFFFF a 0x0000 y se activa la interrupcion. Luego a medida que entras a la interrupcion el Timer1 sigue contando hasta que nuevamente le decis que ponga 3036 en el Timer, entonces si supongamos que tardo 5 instrucciones hasta poner a 3036 el Timer 1, deberias haber cargado 3041. En el modulo CCP vos cargas 62500 en los registros del CCP, Y al comienzo pones el Timer1 en 0. El timer cuenta hasta llegar a 62500 en el que tiene el mismo contenido que los registros del modulo CCP, al producirse la igualdad, si esta bien configurado el modulo, produce que el Timer1 se pone a 0 por si solo y activa una interrupcion. Entonces vos no tenes mas el trabajo de andar cargando una y otra ves el timer, ni siquiera pensar en cuantas instrucciones pasaron desde la interrupcion hasta que seteas el Timer1, ya se hace todo por Hardware.  Para eso debes configurar el Timer a tu gusto(como lo tenes normalmente) y el CCP en modo compare, tenes 3 modos de ahi el C-C-P Capture-Compare-PWM

El Capture es para cuando se produce un evento como puede ser una entrada externa, toma el valor del Timer 1 y lo guarda en los registros CCP, util para medir el pulso de una señal.
El Compare esta comparandose siempre el Timer1 con lo que hay dentro de los registros del CCP, cuando son iguales se produce la interrupcion ( lo que nos interesa )
El PWM Hace uso de 1 registro mas, Ambos comparados con el Timer1, cuando el registro de duty es igual que el timer1 pone a 0 la salida, cuando el registro de periodo es igual al timer1, pone a 0 el timer1 y a 1 la salida, y ahi tenes un PWM :P,

segun el manual CCS:
setup_ccp1(CCP_COMPARE_RESET_TIMER);

Decirle que el ccp tenga el valor 62500 y poner a 0 el timer y esperar xD

Algo asi:

Código: C
  1. #include <16f876a.h>
  2. #device adc=10
  3. #use delay(clock=4000000)
  4. #fuses HS,NOWDT,NOPROTECT,NOLVP,PUT,NODEBUG,BROWNOUT,NOCPD,NOWRT
  5. #use fast_io(B)
  6. #use fast_io(c)
  7. #use fast_io(a)
  8.  
  9. #int_CCP1
  10. void  CCP1_isr(void)
  11. {
  12.         bit_toggle(PIN_C0);
  13. }
  14.  
  15. void main()
  16. {
  17.     setup_timer_1(T1_INTERNAL|T1_DIV_BY_1);
  18.     setup_ccp1(CCP_COMPARE_RESET_TIMER);
  19.     CCP_1 = 62500;
  20.     set_timer1(0);
  21.     enable_interrupts(INT_CCP1);
  22.     enable_interrupts(GLOBAL);
  23.     while(true);
  24. }

No se si falta configurar algo mas, o si es necesario ademas el limpiar la flag, pero creo que tu timer duraba 0.5s, con ese valor, este va a durar lo mismo y cada ves que entre a la interrupcion va a cambiar el estado del pin C0, al menos en este ejemplo. observaras que no cargo el timer ni nada, defini los valores iniciales y que corra nomas.

A fines practicos es identico hacerlo con timer o con el CCP, lo unico que te ahorras es la cargada del timer y esto te lleva a tener un poco mas de precision final en el tiempo.

Corte
Esto puede ser de varias formas:

- la mejor seria que tengas un comparador analogico con el PIC, es lo mas rapido y no agrega circuito. Ese PIC no posee comparadores analogicos.
- La otra es usar una entrada que tenga deteccion de flanco, como Rb0 (no se si otro pin lo posee en ese pic) de esa forma usas un comparador externo y cuando se produce la caida de tension se pone a 0 la salida de ese comparador, de esa forma detectas el flanco de bajada y actuas. El circuito exterior es el que te va a fijar la tension de corte. Esto implica agregar Hardware. Pero lo bueno es que podes detectar el corte incluso antes del regulador/filtrado etc. permitiendo que si hay corte rapido al menos con la poca carga de los condensadores guardar los datos.
- Finalmente otra de las mas baratas es... el ADC ... en tu caso utilizaria el ADC y posiblimente interrupciones del mismo, entonces al comienzo pones a hacer funcionar y le decis que convierta. Apartir de ahi cada ves que entra a la interrupcion o esperas un tiempo para pedir otra muestra o pedis continuamente, siempre tratando de utilizar alguna funcion no bloqueante. Ejemplo Read_ADC() espera que el ADC termine, y deberias buscar una funcion que no haga eso, que lo active y salga.  Para tener un control verdadero en este caso deberias estar leyendo una y otra ves el ADC, lo cual va a tener un GRAN impacto en tu programa. Ya que vas a hacer: X instrucciones - ADC - otras X instr - ADC - y asi continuamente
Por lo que optes va a depender de vos. tambien va a depender de donde estes midiendo con el ADC, al igual de donde pones el comparador si es que armas un circuito externo.

EEPROM
Citar
estaba grabando constantemente los valores en la memoria
Si siguen funcionando por las dudas segui con los mismos lugares de memoria, si ya encontras problemas o algo por el estilo, cambias los lugares de las memorias, ya que con tantas grabaciones se pueden haber roto. Una ves que lo tengas como "final" y arreglado todo tambien podes cambiarle la posicion de memoria si es que no lo habias cambiado antes.
En este caso te salvo todos esos delays que tenias xD.

Para leer o escribir en el EEPROM no necesitas delays.

Tiempo y Delays

Citar
La otra forma de hacerlo que sugeris(es lo que se me ocurre pensar desde mi ignorancia)es en vez de usar los delays usar la base de tiempo que ya voy llevando con los segundos ? .

Exacto, pero ojo, eso no quiere decir que esperes ahi hasta que pasen X interrupciones, sino que no se produzca ningun cambio en el LCD mientras continua haciendo el bucle while con lo cual podes seguir leyendo las entradas, con lo que tu programa pasaria mas a tener "estados"
Título: Re:Ayuda con lcd
Publicado por: arielmdq en 14 de Octubre de 2015, 08:03:25
Muchas gracias por la respuesta ,bueno esto me va a llevar tiempo ja ja , en cuanto tenga algo te cuento
                                                                                        Saludos !!!!
Título: Re:Ayuda con lcd
Publicado por: MGLSOFT en 14 de Octubre de 2015, 08:05:34
Me alegro que les sirviera Numgran, hace mucho que lo hice, de hecho fue una de mis primeras cosas hechas en lenguaje C, antes usaba PicBasic.
Killer, excelente explicación sobre como crear los caracteres.
Las flechas no tienen nada que ver con los números, solo las uso para marcar en los menúes largos, en que posición estoy.

La perdida de parte de los números grandes es un problema de glitch en el lcd.

Habría que hacer una rutina que compruebe cada tanto si los caracteres estan bien (recuerden que son posiciones de RAM dentro del LCD) o de hecho, regrabarlos cada tanto, lo que lleva unos 18 milisegundos en los LCD que yo use, que son buenos, no se en otros.

Mi próximo desafió, aunque por ahora no tengo tiempo, es hacerlo en LCD del tipo OLED, que tienen otro driver diferente al estándar.

Saludos
Título: Re:Ayuda con lcd
Publicado por: arielmdq en 14 de Octubre de 2015, 12:59:11
Hola ,MGLSOFT te quería agradecer por los archivos de los numeros grandes que le pasaste a chaly29 el me los envió y despues los encontre en este post ja ja , y gracias  por comentar en el tema ,saludos .

A KILLERJC  te quiero preguntar algo por que sino me mareo un poco  :-)  :D y yo me mareo facil  :D con el ejemplo que me explicaste de comparar el ccp con el timer(1) es solo para crear la base de tiempo ,no?.Por que vos ya estas cargando el CCP con un valor ,por eso es modo COMPARE  :mrgreen:
Si es asi entonces ,tengo que seguir utilizano el timer(0) como contador de pulsos pero realizando la captura para poder medir la frecuencia  con la interrupcion del ccp en vez de la interrupcion por timer(1) algo asi:
Código: C
  1. #int_CCP1
  2. void  CCP1_isr(void)
  3. {
  4.    contador=get_timer0();
  5.    set_timer0(0);  
  6.  
  7. }
O si no , no entendi nada  :shock: :shock: :shock: :D
Título: Re:Ayuda con lcd
Publicado por: KILLERJC en 14 de Octubre de 2015, 14:44:23
Exacto, pero ya no tocas mas el timer1 ( recargandolo ni nada por el estilo ).


Citar
Mi próximo desafió, aunque por ahora no tengo tiempo, es hacerlo en LCD del tipo OLED, que tienen otro driver diferente al estándar.

Hace un tiempo habia uno con una banderita de nueva zelanda creo que habia hecho el driver de un OLED, con graficos y todo, como que no le contestaron muchos y se fue xD, solia escribir en ingles y español
Título: Re:Ayuda con lcd
Publicado por: MGLSOFT en 14 de Octubre de 2015, 16:12:16
Si lo del timer es para generar una base de tiempo para temporizaciones, te conviene un tiempo muy pequeño (yo uso 1 milisegundo) y despues creas banderas con el conteo dentro de la interrupcion, y segun el estado de esas banderas ejecutas rutinas y volves a poner la bandera en cero.

Con una sola interrupcion podes llegar a disponer de 10 bases de tiempo distintas, que ejecutan diferentes tareas, lo lindo de eso es que esas tareas se ejecutan solas despues.

Respecto a medir tiempos de pulsos, usa el modo capture, anda joya para eso, igual para tener precision tendras que poner un cristal de los mas rapidos que puedas disponer en el micro que uses, porque eso aumenta la precision de la medicion.

Killer, te referis al que ponia los temas de rock metalico en sus videos?? Lo voy a buscar, hizo cosas interesantes, igual solo queria hacerlo en modo texto, pero es cierto que la principal diferencia entre ese driver y el del LCD estandar es que permite ambos modos de uso, modo texto y modo grafico...
Título: Re:Ayuda con lcd
Publicado por: KILLERJC en 14 de Octubre de 2015, 18:25:57
 ahi nomas lo encontro en la busqueda, a este me referia:

http://www.todopic.com.ar/foros/index.php?topic=44230.msg367161#msg367161

Y esa musica que le ponia xD
Título: Re:Ayuda con lcd
Publicado por: arielmdq en 14 de Octubre de 2015, 20:31:35
Hola vuelvo con mas preguntas , bueno ya le cambié al programa la parte de la interrupcion del timer por la de ccp ,y hasta ahora en la simulacion funciona lo mas bien , recien mañana la probaré en el pic .
Pero ahora lo que me preocupa es la forma de poder grabar en la memoria cuando haya un corte de alimentacion .Por ahora me decidi por la opcion de detectar un flanco de bajada por Rb0 que creo es lo que tengo mas mano para hacer. Ya le cambié al lcd la distribucion de pines para que me quedara Rb0 libre y asi poder usarlo  .Activé la int_ext para que me detecte un flanco de bajada
Código: C
  1. enable_interrupts(int_ext);
  2.   ext_int_edge(h_to_l);
Y luego hice esta funcion:
Código: C
  1. #int_ext
  2. void corte()
  3.        {
  4.           write_int16_eeprom(100, Hora);
  5.           delay_ms(15);
  6.           write_int16_eeprom(110, HoraParcial);
  7.           delay_ms(15);          
  8.           write_eeprom(120, Minuto);
  9.           delay_ms(15);
  10.           write_eeprom(130, MinutoParcial);
  11.           delay_ms(15);
  12.          
  13.        }
pero cuando compilo me salen 2 warning que dicen:  interrupts disabled call to prevent re-entrancy {@delay_ms1}
                                                                                   interrupts disabled call to prevent re-entrancy { write_int16_eeprom}
Que estoy haciendo mal ?
Esto que estoy haciendo ,sirve?


PD:Cuando se active esta interrupcion ya no me interesa el resto del programa ,solo que guarde los datos en la memoria ya que se supone que me  quede sin alimentacion .
Título: Re:Ayuda con lcd
Publicado por: KILLERJC en 14 de Octubre de 2015, 21:53:23
No se exactamente el tema del delay.... ( ni idea por que te da eso en un delay )

Pero en la EEPROM es OBLIGACION desactivar las interrupciones al grabarlo. Por lo cual procura antes de grabar en la EEPROM desactivar las interrupciones y habilitarlas cuando termines de grabar. Estoy acostumbrado que normalmente el programa en ASM lo hace, entonces no me di cuenta. Pero bueno. ya estas avisado, intenta ponerle un disable_interrupt(global) y  enable_interrup(global) antes y despues, Y sacale los delays!!! CCS, imagino que debe haber puesto una condicion preguntando para que no intente guardar cuando todavia no termino la anterior

Código: C
  1. disable_interrupt();
  2.           write_int16_eeprom(100, Hora);
  3.           write_int16_eeprom(110, HoraParcial);
  4.           write_eeprom(120, Minuto);
  5.           write_eeprom(130, MinutoParcial);
  6.           enable_interrupt();

Y otra cosa. para evitar que grabe y grabe y grabe, podes hacer un contador que cuando grabe comienze y usas el mismo interrupt del CCP para contar 10 o mas y habilitas nuevamente la interrupcion externa ( antes limpiando el flag) de esa forma a lo sumo guarda 1 ves cada 5 segundos, y el maximo error seria ese con lo guardado.  Y te evitas destrozar la EEPROM
Título: Re:Ayuda con lcd
Publicado por: arielmdq en 15 de Octubre de 2015, 20:15:52
Hola que tal ,bueno estuve haciendo algunas pruebas y les cuento, lo de la interrupcion por ccp funcionó perfecto en realidad no note ningun cambio a lo anterior que era la interrupcion por timer1, pero si de esa manera es mejor entonces asi quedará ,una cosa mas  aprendida  vamos todavia  :) .Ahora lo de grabar en la eeprom despues de varias pruebas terminé haciendo esto:
 
Código: C
  1. short a=0;
  2. #int_ext
  3. void corte()
  4.  {
  5.     a=1;
  6.          
  7.  }
Y luego al comienzo del while :
Código: C
  1. while(1)
  2.     {
  3.          if (a==1)
  4.        {
  5.           write_int16_eeprom(100, Hora);
  6.           delay_ms(15);
  7.           write_int16_eeprom(110, HoraParcial);
  8.           delay_ms(15);          
  9.           write_eeprom(120, Minuto);
  10.           delay_ms(15);
  11.           write_eeprom(130, MinutoParcial);
  12.           delay_ms(15);
  13.           a=0;
  14.          
  15.        }
Poco elegante pero es lo que se me ocurrió   :oops:
Dejando las escrituras dentro de la interrupcion y aún quitando los delays no funcionaba , yo tenia entendido que cuendo se hacian varias escrituras seguidas era recomendable los delays , es esto cierto?
No se si la manera en que lo hice es buena , de todos modos pensé en ponerlo al principio del while para que sea lo primero que chequee despues de la interrupcion , pero no sirve de nada por que despues de la interrupcion el programa vuelve a donde había quedado ,no?
En la plaqueta de pruebas  todavia no tengo hecho un circuito que me detecte la falta de alimentacion y me ponga Rb0 a 0 esta prueba la hice a mano solo para ver si grababa en la memoria ,y sí , lo hacía .Tampoco tengo claro que circuito tendría que hacer exactamente algo de lo mas sencillo y especifico posible ,solo lo del comparador que dijo KILLERJC y supongo que será algo parecido a lo que me explicó chaly29 aca http://www.todopic.com.ar/foros/index.php?topic=15702.15  si tienen algun circuito o algo especifico se los agradeceré. Tambien pensé  en preguntarle a este genio de los circuitos si ya hizo algo parecido para que me tire una idea , el siempre tiene un as bajo la manga   :D obiamente sin menospreciar cualquier idea que uds me propongan .Me gustaría saber que piensan acerca de esto y desde ya muchas gracias por su ayuda .
                                        Saludos !!!
Título: Re:Ayuda con lcd
Publicado por: mariacontenis en 15 de Octubre de 2015, 22:49:08
Excelente tema. Estoy atento a todo lo que comentan y comparten y me a Sedó de gran interés y aprendizaje. Arielmdq será que pudieras subir un vídeo de funcionamiento?. Gracias a todos por compartir.  :-/
Título: Re:Ayuda con lcd
Publicado por: KILLERJC en 15 de Octubre de 2015, 23:54:02
Citar
bueno estuve haciendo algunas pruebas y les cuento, lo de la interrupcion por ccp funcionó perfecto en realidad no note ningun cambio a lo anterior que era la interrupcion por timer1, pero si de esa manera es mejor entonces asi quedará ,una cosa mas  aprendida  vamos todavia

Es que el cambio es muy pequeño, estamos hablando de algunos ciclos entre interrupcion e interrupcion, tambien si tenes 2 interrupciones y se atiende otra primero no vas a tener problema por que le flag queda seteado y ya el CCP lo puso a 0 al Timer1.

Con respecto al codigo sobre la interrupcion externa  es lo mismo que tenias antes. incluso podrias desactivar la interrupcion y preguntar por el flag, se que CCS tiene funciones, no se cuales son, pero es lo equivalente a esto lo que hiciste:
(Hasta diria que es mas eficaz lo que tenias antes)
Código: C
  1. while(1)
  2.     {
  3.          if (flag_activo())
  4.        {
  5.           write_int16_eeprom(100, Hora);
  6.           delay_ms(15);
  7.           write_int16_eeprom(110, HoraParcial);
  8.           delay_ms(15);          
  9.           write_eeprom(120, Minuto);
  10.           delay_ms(15);
  11.           write_eeprom(130, MinutoParcial);
  12.           delay_ms(15);
  13.           borrar_flag();
  14.        
  15.        }
Y ni siquiera necesitarias activar la interrupcion, solo leer el flag, lo cual seguis con lo mismo de antes, nomas que ahora en ves de leer el ADC, estas haciendo caso a una entrada.

Citar
Dejando las escrituras dentro de la interrupcion y aún quitando los delays no funcionaba , yo tenia entendido que cuendo se hacian varias escrituras seguidas era recomendable los delays , es esto cierto?
No entiendo por que no. Escribir la EEPROM no se hace instaneamente como uno escribiria en la RAM por ejemplo, sino que tarda un tiempito mas ( no voy a poner el ASM para no complicarte la vida ), vos cuando le das a escribir al dato, pones un bit en 1, recien se termina de escribir cuando se pone en 0. Pienso que CCS deberia tener en su funcion un control de este bit, o esperando que termine de grabar cuando envia el dato, o cuando se le da la orden de grabar que espere a la anterior orden que termine. Pienso que deberia hacerlo asi.
Lo que puede pasar es que la funcion de escritura desactive y active las interrupciones, y al estar dentro de la interrupcion y no haber limpiado el flag, este continuamente entrando, ya que va a saltar nuevamente al vector de reset, nunca saliendo de la instruccion. Lamentablemente no veo otra solucion mas que hacer tu propio codigo con respecto a esto. Si es que buscas hacerlo de esta forma.

Citar
No se si la manera en que lo hice es buena , de todos modos pensé en ponerlo al principio del while para que sea lo primero que chequee despues de la interrupcion , pero no sirve de nada por que despues de la interrupcion el programa vuelve a donde había quedado ,no?
Exacto, cuando sale de la interrupcion va a donde estaba, si estaba en la mitad de un delay de 3segundos ( 1.5s ) y ocurre la interrupcion, cuando salga de la interrupcion todavia le queda 1.5s + todo el otro codigo que tengas.

Citar
En la plaqueta de pruebas  todavia no tengo hecho un circuito que me detecte la falta de alimentacion y me ponga Rb0 a 0 esta prueba la hice a mano solo para ver si grababa en la memoria ,y sí , lo hacía .Tampoco tengo claro que circuito tendría que hacer exactamente algo de lo mas sencillo y especifico posible ,solo lo del comparador que dijo KILLERJC y supongo que será algo parecido a lo que me explicó chaly29 aca http://www.todopic.com.ar/foros/index.php?topic=15702.15  si tienen algun circuito o algo especifico se los agradeceré.

Creo que Chaly te podria ayudar. Todo depende de que necesites que haga tu circuito. Un comparador es simple, compara las tensiones de entrada de + y -, en la cual 1 de las entradas deberia tener una tension de control y "fija" y la otra es la sensada , segun el estado que esten estas podes tener VCC o GND en la salida de este. Ahora si la tension fluctua entre estos valores por ahi quisieras tener una histeresis, supongamos que medis la tension y deberia haber 9V a la entrada del regulador de tension ( supongamos un 7805 ) si cae la tension a 6.5V queres que actue tu comparador poniendose a GND su salida, pero solo queres que cuando llegue a 8V vuelva a ponerse a VCC la salida asi saber que la tension volvio como debia estar. Eso seria una histeresis. Sin histeresis en 6.49 se pondria a GND y en 6.51 a VCC , fluctua entre esos valores y esarias grabando mil veces. Tambien podes implementar algo con el PIC.
Chaly si no tiene un circuito en su baul de los recuerdos o te podria ayudar.

Título: Re:Ayuda con lcd
Publicado por: arielmdq en 16 de Octubre de 2015, 08:24:16
Muchas gracias KILLERJC por la explicacion ,y claro tenes razon con lo de grabar en eeprom estoy haciendo lo mismo que hacía con el adc  :D , bueno entonces no se bien que hacer , voy a leer un poco   a ver de que otra manera se puede hacer ,de todos modos el circuito para detectar la falta de alimentacion lo voy a tener que hacer ,asi que voy a ir viendo eso tambien .
No tengo muy en claro cuando hablan de flag supongo que es una señal, un parametro ,una palabra a la que se le asigna un valor ? o simplemente  una variable y la llaman flag ,se supone que esto ya lo debería saber pero bue en algun momento lo tenía que preguntar  :oops: disculpame pero no tengo muy incorporado el termino .
A Mariacontenis aca http://www.todopic.com.ar/foros/index.php?topic=15702.60  hay un video con el proyecto pero esta sin numeros grandes despues voy a hacer uno cuando este terminado
                                                                                              Saludos!!!
Título: Re:Ayuda con lcd
Publicado por: MGLSOFT en 16 de Octubre de 2015, 08:50:22
Todos los otros conceptos que expone Killer son correctas, en lo que no coincido es en usar las escrituras eeprom dentro de una interrupción.

Porque??

Las escrituras eeprom necesitan que NO se realicen otras acciones mientras ocurren, porque se malogran y el solo hecho de grabar un byte en eeprom, presupone 18 mseg con un reloj de 4 mhz.
Si ademas grabas mas de un byte, multiplicalo por la cantidad de bytes.

Como el CCS ejecuta una interrupción y al momento borra las banderas (flags) de interrupción, queda listo para ejecutar otra vez la misma interrupción aun estando en ejecución el código de la anterior interrupción (en este caso la escritura en eeprom), lo que ocasiona recursividad, que esta prohibido en un PIC, por eso te avisa el compilador que desactivara esa interrupción para evitar una nueva entrada (reentrancy disabled).

Las tareas de temporización (delay) y tareas de largo plazo, no deben ejecutarse dentro de la interrupción, por las razones expuestas anteriormente.
En la interrupción solo debes operar instrucciones que no impliquen temporizaciones, y escribir en eeprom o usar delay, precisamente es lo que no se debe hacer.

Esta bien que marques una bandera y luego ejecutes esa tarea dentro del main() y una vez ejecutadas, borres la bandera.

Si bien el compilador te ayuda evitando recursividad (reentrancy) el problema es que si tu aplicación tiene mas de una fuente de interrupción, todas quedan deshabilitadas, ya que actúa sobre el bit de interrupciones globales.

En palabras simples, si entra en esa interrupción y deshabilita, no vas a tener comunicaciones serie por interrupciones, se entiende?? :mrgreen: :mrgreen:
Título: Re:Ayuda con lcd
Publicado por: KILLERJC en 16 de Octubre de 2015, 09:38:20
Para MGLSOFT

Citar
Las escrituras eeprom necesitan que NO se realicen otras acciones mientras ocurren, porque se malogran y el solo hecho de grabar un byte en eeprom, presupone 18 mseg con un reloj de 4 mhz.

No pense que era tanto tiempo, es lo unico que no habia pensado, , sobre que no se este haciendo otra cosa es que no se va a hacer otra cosa mas que grabar la EEPROM. Con respecto a lo de reentrante es que estoy acostumbrado a verlo desde el ASM (se que no es ASM pero es el funcionamiento del PIC), yo en ASM no activaria las interrupciones dentro de una interrupcion por simple logica, cuando entra a la interrupcion el PIC se desactivan, pero si el codigo de escribir en la EEPROM (de CCS ) lo activa nuevamente entonces ahi no te queda otra que hacer uno mismo la funcion de la escritura de la EEPROM. Y eso lo nombre en el post anterior. Si uno hiciera el codigo de la EEPROM no activaria las interrupciones, por lo tanto no existiria una "reentrada". Y eso contesta a esto:

Citar
Como el CCS ejecuta una interrupción y al momento borra las banderas (flags) de interrupción, queda listo para ejecutar otra vez la misma interrupción aun estando en ejecución el código de la anterior interrupción (en este caso la escritura en eeprom), lo que ocasiona recursividad, que esta prohibido en un PIC, por eso te avisa el compilador que desactivara esa interrupción para evitar una nueva entrada (reentrancy disabled).

El tema es que el necesita grabar los datos cuando exista una caida de tension para justamente que no se pierdan, la cual no le va a servir para nada asi como esta su programa. En el que hay momentos hasta con 3 segundos de delay. Si supuestamente ocurre este caso, vos no te preocupas por que tu programa "siga" ya que es una condicion por asi decirlo "de parada". Es lo ultimo que harias, y por lo cual no me preocuparia por si llego a retrasar el CCP o perder 0.5s en el contador,  lo cual no va a hacer por que tiene una interrupcion de 0.5s y la grabacion de la EEPROM duraria mucho menos. Supongamos que se activo el flag de caida de tension, entro a la interrupcion y cuando entro y estoy grabando se activa el flag del CCP, no va a haber problema por que estan desactivadas las interrupciones mientras estoy en una interrupcion. Cuando termine de grabar la EEPROM y quiera salir, al activar la interrupcion el micro va a ver la flag del CCP y va a entrar de nuevo. la cual va a hacer el codigo del CCP, limpiar el flag y salir.lo cual estas ante un tiempo de 0.5s a 1s para salir de tu grabada de EEPROM y entrar a la del CCP (si es que sigue y fue una "falsa alarma" ) y no queres perder datos, ( el CCP te borra el timer asi que menos problema con eso )

Mi idea fue la de grabarlo lo mas rapido posible, como decia esta es una condicion de parada en la cual el PIC ya no va a tener mas tension, y mi idea era que aprovechara rapidamente ese ultimo momento para guardar las cosas. Si lo pone en el loop while deberia reformular su codigo, incluso reformulado si te "agarra" en el comienzo de una escritura del LCD tal ves corras la misma suerte que con el delay. Por eso dije de la interrupcion.

Resumiendo por si no me explique:

En caso que sea lo ultimo que haga el PIC por que se corto la tension:
- Entra a la interrupcion (es lo mas rapido 20 ciclos maximo deberia tener), graba la EEPROM ( lo que tarde ), termina de grabar, se sale de la interrupcion (limpia flag, etc) y que continue el programa hasta que no tenga mas tension y se pare.
Comparacion con el metodo de ponerlo en el while:
En el While sos dependiente de donde este el programa y seguro que la mayoria de las veces tenes mas de esos 20 ciclos para comenzar a grabar la EEPROM, comenzas tarde a grabarla, lo cual corres mas riesgo de que a la mitad de la grabacion quedes sin energia y quede corrupto lo guardado, obviamente con la interrupcion corres la misma suerte, pero al comenzar mas rapido es un poco menos el riesgo.

En caso de que sea una falsa alarma:
- Con interrupcion no seria problema, como ya comente el CCP se encarga de poner a 0 el Timer1 y la flag quedaria activada, se grabaria la EEPROM, tomaria el RETFIE ( que activaria la interrupcion global ) y al estar activado el flag del CCP entraria nuevamente a la interrupcion por el CCP, el cual aumentaria sus segundos, borraria el flag y seguiria normalmente. Lo unico que "retrasaste" es el programa principal por que entraste 2 veces a la interrupcion (1 para el CCP y otra para la EEPROM).

Lo que no entendi fue esto:

Citar
En palabras simples, si entra en esa interrupción y deshabilita, no vas a tener comunicaciones serie por interrupciones, se entiende??
Cuando se entra la interrupcion se deshabilita solo las interrupciones globales, el RETFIE es quien las habilita nuevamente. Pero si misteriosamente usas una funcion como escribir en la EEPROM que posee las instrucciones de desactivar y activar las interrupciones dentro como para poder usarlas en el loop while por ejemplo, entonces ahi SI vas a tener problemas y va a ser reentrante. Y es a esto a lo que estoy apuntando.

Grabar la EEPROM en la interrupcion no es el problema, el problema es la funcion de grabado de la EEPROM.
Y ahora te pido que me entiendas a mi :P
O los dos estamos diciendo lo mismo y no nos entendemos  :D

Para arielmdq

Citar
No tengo muy en claro cuando hablan de flag supongo que es una señal, un parametro ,una palabra a la que se le asigna un valor ? o simplemente  una variable y la llaman flag ,se supone que esto ya lo debería saber pero bue en algun momento lo tenía que preguntar  :oops: disculpame pero no tengo muy incorporado el termino .

Flag normalmente es una "variable" de un 1 bit, es 0 o 1, en el cual puede indicar algo, por ejemplo cuando ocurre una interrupcion se pone en 1 una flag llamada CCP1IF indicando que ocurrio la condicion interrupcion del modulo CCP. ( No hace falta que este habilitado la interrupcion para que se ponga en 1 la flag), vos hiciste algo parecido, creaste una "flag" llamada a ( aunque de 8 bits seguro) la cual para vos te indica si entro o no a la interrupcion, eso es una flag, es una bandera ( traduccion ) como para indicar algo
Título: Re:Ayuda con lcd
Publicado por: MGLSOFT en 16 de Octubre de 2015, 10:00:57
No había leído que era para grabar en EEPROM ante un corte de energía.
En ese caso, coincido en que decimos lo mismo. :mrgreen: :mrgreen:

Respecto a eso, creo que hay un tema de Marioguillote donde hizo un circuito + software que le permitía detectar la perdida de energía y grabar un montón de bytes en eeprom antes de apagar el circuito (en realidad no recuerdo si lo apagaba o lo dormía).
Busquenlo en el foro, se discutió mucho ese tema, yo lo tenia grabado pero con el cambio de look del foro perdi todos los temas marcados...
Título: Re:Ayuda con lcd
Publicado por: KILLERJC en 16 de Octubre de 2015, 16:42:08
Citar
Respecto a eso, creo que hay un tema de Marioguillote donde hizo un circuito + software que le permitía detectar la perdida de energía y grabar un montón de bytes en eeprom antes de apagar el circuito (en realidad no recuerdo si lo apagaba o lo dormía).

Hice una busqueda. En la cual busque la palabra eeprom y lo restringi al usuario, pero no habia nada. Solo respuestas a otros usuarios. Estas seguro que era el?
Título: Re:Ayuda con lcd
Publicado por: arielmdq en 16 de Octubre de 2015, 16:52:07
Aca encontre un post donde se toca el mismo tema http://www.todopic.com.ar/foros/index.php?topic=26343.msg215873#msg215873
y se habla de El #fuse NOBROWNOUT que permite que el micro siga operando ante una caida de tension
Y otro post http://www.todopic.com.ar/foros/index.php?topic=36290.msg302456#msg302456 donde mglsoft dice:Puedes usar el Brown down detect, puesto al valor que mas te convenga.
Si ocurre la deteccion de baja tension dejas de hacer todo y disparas la escritura en eeprom, eso deberia ayudar bastante.
Pero no se como usar ninguna de las dos cosas  :D :D :D sigo buscando........
Título: Re:Ayuda con lcd
Publicado por: KILLERJC en 16 de Octubre de 2015, 17:07:38
No era para mi, era para vos xD.
El primer link tiene varias cosas utiles:

- quitar el Brown Out,  esto te resetea el PIC cuando hay una pequeña caida de tension, en elagunos micros es hasta programable el valor.
- Tener una alimentacion separada o aunque sea tener un diodo + una buena capacidad que mantenga alimentado solo al PIC de esa forma la carga del capacitor solo lo usa el PIC.
 Tengo entendido que con capacitores grandes como de 1uF y baja tension si el PIC se pone a dormir ( en modo bajo consumo ) la carga puede durar mucho tiempo.
Igual esto te va a servir para que veas que si conectas el LCD + PIC sin hacer el circuito de diodo + condensador como sugieren, el LCD podria llegar a terminarte la carga del condensador rapidamente.

igual falta la seccion de sensado y grabado de la eeprom.
Y sobre el grabado en la interrupcion, no encuentro nada, todo en ASM xD
Título: Re:Ayuda con lcd
Publicado por: arielmdq en 19 de Octubre de 2015, 22:14:39
Hola KIller ,te cuento que chaly me paso un circuito para hacer lo que veniamos hablando, hoy lo probé y funcionó perfecto  :), detecta el flanco de bajada y me da cerca de 3 segundos para grabar en la memoria ,lo estuve probando en varias situaciones del programa y en la unica que no graba como ya lo habias dicho vos, es cuando esta dentro de los delays de 3 segundos.
Ahora lo que pienso es que  la opcion en la que entra en los delays de 3 segundos es cuando se esta visualizando el cuentavueltas en numeros grandes y se pulsa un boton para visualizar el cuenta horas parcial (3seg) y el total (3seg) y luego vuelve al cuentavueltas con numeros grandes.
Yo pienso que va a ser muy poco probable que se quede sin alimentacion justo en este momento teniendo en cuenta que solo se quedará sin alimentacion ante un cambio de batería ,y esto seguramente ocurrira con el motor parado y el cuentavueltas detenido osea
 el programa solo esperando recibir un pulso para comenzar a contar ,tanto vueltas como segundos.Claro que sería buenisimo
que pudiera guardar los datos bajo cualquier circunstancia ,pero bueno ya veremos como ,por lo pronto voy a reducir esos delay
o ver de que otra forma puedo hacer esa parte para seguir visualizando esa funcion pero que no quede atrapado ahí en caso de un
 corte de alimentacion.Cualquier sugerencia soy todo oidos,  bueno ojos  :D :D :D .
                                                                                                                                      Saludos!!!
Título: Re:Ayuda con lcd
Publicado por: KILLERJC en 20 de Octubre de 2015, 00:15:16
Excelente 3 segundos es bastante para grabar la EEPROM

Como lo veo quedan 2 soluciones, al menos para mi y tal ves hay otra:

- Grabar en la interrupcion, lo cual exigiria que no se activen las interrupciones, y tal ves es crear la funcion de grabar la EEPROM paso a paso como dice el datasheet.
- Modificar todo el programa para que funcione de otra forma. Mas como una maquina de estados y tomar en cada seccion al comienzo el valor del segundero asi de esa forma poder hacer las animacion que se deban realizar.

La primera es simple, es crear una funcion que cargue los valores a los registros en orden y listo.
La segunda llevaria te llevaria modificar mucho mas el programa ya que tendrias que modificar todo el bucle while del main, para que realize la grabacion alli.

Creo que son las 2 optimas, por supuesto prefiero la primera. Pero eso decidiras vos por cual vas.
Título: Re:Ayuda con lcd
Publicado por: arielmdq en 20 de Octubre de 2015, 08:13:50
Hola Killer ,si yo creo que a esta altura ya iría por la primera asi lo terminamos de una vez ,ya me agarro la ansiedad de concluir   :D :D ,pero entonces como creamos esta funcion que cargue los valores en los registros en orden y que pueda grabar en la interrupcion ?por que hasta lo que intente de grabar en la interrupcion me marca los warning con y sin delays .No entiendo como debería hacerlo  :lol:
Título: Re:Ayuda con lcd
Publicado por: KILLERJC en 20 de Octubre de 2015, 08:44:22
Es que justamente no se como hacerlo en CCS, yo use siempre XC8 o directamente ASM. Y lo que hay que hacer es esto:

EEDATA = dato_a_guardar;
EEADR = direccion_del_dato
EECON1 |= 0x04; //WREN = 1
EECON2 = 0x55;  //Proteccion
EECON2 = 0xAA;
EECON1 |= 0x02; // Pedido de escritura de datos
while( EECON1 & ~(0x02) ); // Esto o ver el flag de EEIF, espero que termine, podria ser un bit_test(EECON1,1) !!

Repito eso por cada dato + direccion.
Y finalmente cierro con un :

EECON1 &= ~(0x04); // Pone a 0 el WREN

Eso es en ASM lo que se hace para escribir la EEPROM, ahora como implementar eso en CCS es otro tema. Y pienso que deberia haber una forma de escribir la EEPROM en la interrupcion. Ojo esto unicamente es valido para un programa adentro de la interrupcion, sino deberia desactivar la interrupciones antes.

Codigos encontrados por internet:


Código: C
  1. void Write_EEPROM(
  2.   UINT8 data,            // byte written to eeprom
  3.   UINT8 address)         // EEPROM address to write data
  4. {
  5.   PIR2bits.EEIF = 0;     // Make sure that the int flag is cleared
  6.   EEADRH= 0;             // Load our address
  7.   EEADR = address;       // Load our address
  8.   EEDATA = data;         // Load our data
  9.   EECON1bits.EEPGD = 0;  // Point to data memory
  10.   EECON1bits.WREN = 1;   // Enable writes
  11.  
  12.   // Microchip recommends disabling ints here
  13.   global_int(INT_DISABLED);
  14.   EECON2 = 0x55;         // Write 0x55
  15.   EECON2 = 0xAA;         // Write 0xAA
  16.   EECON1bits.WR=1;       // Set WR to begin write
  17.   _asm
  18.     nop
  19.   _endasm
  20.   global_int(INT_RESTORE);
  21.   while (!PIR2bits.EEIF); // Wait for write to complete
  22.  
  23.   PIR2bits.EEIF = 0;
  24.   EECON1bits.WREN = 0;    // Disable writes
  25.   return;
  26. }

Código: C
  1. int1 eewrite;//flag set in my int_RDA by command to save ram to eeprom
  2.  
  3. #byte      EECON1 = 0xFA6
  4. #define   WR            1
  5. #define   WREN        2
  6. #define   EEPGD       7
  7.  
  8. #inline
  9. void service_eeprom_wr(void) {
  10.     if(!bit_test(EECON1,WR)) {      // was last byte wrote?
  11.         if(eewrite) {         // if 1, save next byte
  12.         if(eecnt<sizeof(cfg)) {
  13.         EEADR = eecnt;
  14.         EEDATA = *(&cfg+eecnt);
  15.         bit_clear(EECON1,EEPGD);      // Point to DATA memory
  16.         bit_set(EECON1,WREN);      // Enable writes
  17.         disable_interrupts(global);      // Disable all interrupts
  18.         EECON2 = 0x55;      // Write 55h
  19.         EECON2 = 0xAA;      // Write AAh
  20.         bit_set(EECON1,WR);      // Set WR to begin write
  21.         enable_interrupts(global);      // Enable all interrupts
  22.                 eecnt++;
  23.                         } else { eewrite=0; }
  24.                 }
  25.         }
  26. }

Ojo con los codigos que habilitan la interrupciones y puede que algunas no te sirvan, yo creo que modificando el 1er codigo deberia funcioanr bien y te creas tu funcion quedando algo asi:

ESTE PROGRAMA ES PARA UN PIC16F628A, tu PIC posee otras direcciones (comienzan en 0x10C y algo mas ), 1 bit mas que es el EEPGD que debes ponerlo en 0 al comienzo, la direccion esta separado en 2 registros y no uno solo y lo demas es igual al ejemplo

Código: C
  1. #define WR      1
  2. #define WREN    2
  3.  
  4. #byte   EEDATA = 0x9A
  5. #byte   EEADR = 0x9B
  6. #byte   EECON1 = 0x9C
  7. #byte   EECON2 = 0x9D
  8.  
  9. void Write_EEPROM(
  10.   UINT8 data,            // byte written to eeprom
  11.   UINT8 address)         // EEPROM address to write data
  12. {
  13.   EEADR = address;       // Load our address
  14.   EEDATA = data;         // Load our data
  15.   bit_set(EECON1,WREN);  // Enable writes
  16.   EECON2 = 0x55;         // Write 0x55
  17.   EECON2 = 0xAA;         // Write 0xAA
  18.   bit_set(EECON1,WR);    // Set WR to begin write
  19.   _asm
  20.     nop
  21.   _endasm
  22.  
  23.   while (bit_test(EECON1,WR); // Wait for write to complete
  24.  
  25.   bit_clear(EECON1,WREN);    // Disable writes
  26.   return;
  27. }

Y lo usas con Write_EEPROM(dato_a_guardar,direccion_donde_guardar);

Creo que este seria el correcto para el PIC16F876, no estoy seguro del While(WR) pero bueno.. es lo que logre hacer sin usar CCS


Código: C
  1. #word   EEDATA = 0x10C
  2. #word   EEADR = 0x10D
  3. #word   EEDATH = 0x10E
  4. #word   EEADRH = 0x10F
  5. #word   EECON1 = 0x18C
  6. #word   EECON2 = 0x18D
  7.  
  8. #bit    WR = EECON1.1
  9. #bit    WREN = EECON1.2
  10. #bit    EEPGD = EECON1.7
  11.  
  12.  
  13. void Write_EEPROM(
  14.   UINT8 data,           // byte written to eeprom
  15.   UINT8 address)        // EEPROM address to write data
  16. {
  17.   EEADR = address;      // Load our address
  18.   EEDATA = data;        // Load our data
  19.   EEDATH = 0;           // Necesario agregar esto, ya que no sabemos los valores que puedan tener
  20.   EEADRH = 0;           // No siempre son cero
  21.   EEPGD = 0;            // Lectura de los EEPROM de datos y no programa
  22.   WREN = 1;             // Enable writes
  23.   EECON2 = 0x55;        // Write 0x55
  24.   EECON2 = 0xAA;        // Write 0xAA
  25.   WR = 1;               // Set WR to begin write
  26.   _asm
  27.     nop
  28.   _endasm
  29.  
  30.   while (WR);           // Wait for write to complete , hasta que WR = 0
  31.   WREN = 0;             // Disable writes
  32.   return;
  33. }
Título: Re:Ayuda con lcd
Publicado por: arielmdq en 20 de Octubre de 2015, 19:35:33
Hola killerjc, muchas gracias por la explicacion y los ejemplos, no me esta siendo tal facil interpretar esto por ahora veo todo nuevo .Espero no defraudarte ,pero quede asi :shock:  :-)   :D voy a necesitar tiempo, cuando tenga algo te cuento.
                                                             Saludos!!!!!
Título: Re:Ayuda con lcd
Publicado por: KILLERJC en 20 de Octubre de 2015, 19:43:27
No es nada nuevo, mira el datasheet y ahi te dice todos los pasos para grabar la EEPROM
Título: Re:Ayuda con lcd
Publicado por: Abner_emanuel en 23 de Octubre de 2015, 14:39:25
Referente a este tema. Como puedo hacer para imprimir en una pantalla 4x20 en lugar de una 2x16?
Título: Re:Ayuda con lcd
Publicado por: arielmdq en 23 de Octubre de 2015, 15:17:50
Hola Abner_emanuel si lo estas haciendo con CCS tenes que incluir la librería  lcd420.c  en vez de  lcd.c :
                                                                                                                                                                    #include <lcd420.c>
Y cuando te referis a donde escribir es igual que en la de 2 x 16 pero cuando marcas la linea le decis si queres escribir en la 1,2,3 o4 asi :
lcd_gotoxy(1,3);
lcd_putc("HOLA");
Aca te va a escribir en la primer posicion de la tercer linea.
Título: Re:Ayuda con lcd
Publicado por: Abner_emanuel en 23 de Octubre de 2015, 15:29:18
Gracias por responder, estoy haciendo un semáforo que ya posyie en otro hilo de aquí y que killer me ayudo en algunas dudas que tenía. Pero quiero ponerle en la LCD números grandes y pequeños de un cronómetro que incluye. Gracias por tu atención. Lo pongo por la tarde y me daré a entender mejor.
Título: Re:Ayuda con lcd
Publicado por: arielmdq en 27 de Octubre de 2015, 09:05:49
Hola que tal ,quería contar lo que hice con el programa, al final me decidi por cambiarle la logica  basandome en ciclos while con condiciones y dos menu,uno principal y uno de configuracion,logrando de esta manera salir de cualquier parte del programa al momento de la interrupcion producida por la deteccion del flanco de bajada por RB0 y asi recurrir a la grabacion de la memoria antes de perder alimentacion.
Para comprobar la efectiva grabacion luego de hacerla, imprimo en pantalla la palabra apagando, pude probarlo en la placa de pruebas en todas las posibilidades y  funciona ,hasta le agregué controlar el backlight con el programa y desactivarlo al momento de la int ext y tambien funciona con lo cual elimino la posibilidad de tener que conectar el backlight con un regulador aparte .
El circuito utilizado es que me paso chaly29 que con un capacitor de 1000uf ya funciona pero creo que para asegurarme lo subiré a 2200uf.
Otra cosa que me gustaría hacer pero que todavía no logro es que cuando este por mas de un tiempo determinado quieto en una parte del programa ,vuelva al while de las RPM ,antes KILLERJC me recomendo hacerlo por interrupcion por rb0 pero ahora ya lo tengo ocupado a Rb0 asi que esto me queda pendiente .Me gustaría saber que opinan del programa ya que si bien funciona ,como siempre nunca estoy seguro si es la manera correcta  :lol: o si de esta manera podré tener problemas a futuro.Desde ya muchas gracias ,los dejo con el programa.Saludos!!!
Código: C
  1. #include <16f876a.h>
  2. #device adc=10
  3. #use delay(clock=4000000)
  4. #fuses HS,NOWDT,NOPROTECT,NOLVP,PUT,NODEBUG,BROWNOUT,NOCPD,NOWRT
  5. #define LCD_ENABLE_PIN  PIN_B3                                    ////
  6. #define LCD_RS_PIN      PIN_B1                                    ////
  7. #define LCD_RW_PIN      PIN_B2                                    ////
  8. #define LCD_DATA4       PIN_B4                                    ////
  9. #define LCD_DATA5       PIN_B5                                    ////
  10. #define LCD_DATA6       PIN_B6                                    ////
  11. #define LCD_DATA7       PIN_B7
  12. #include <lcd.c>
  13. #include <NumGran.C>
  14. #include <internal_eeprom.c>
  15. #use fast_io(B)
  16. #use fast_io(c)
  17. #use fast_io(a)
  18. //****variables del cuneta vueltas***//
  19. int16 contador=0,RPM,i;
  20. float ajuste=10,e;      
  21. //****variables del cuneta horas***//
  22. int8 Segundos=0,SegundosParcial=0,Minuto=0,MinutoParcial=0;
  23. int menu=0,x=0;
  24. int16 b=0,service=0, Hora=0,cont=0, HoraParcial=0,mantenimiento=1;
  25. short grabar=0;
  26. unsigned int16 duty = 0;
  27. //*********Funciones**************************
  28.  
  29. int menus(void)
  30. {
  31.  return (menu+'1');
  32. }
  33.  
  34. #int_ext
  35. void corte()
  36.  {  duty = 0;
  37.     x=0;
  38.     grabar=1;        
  39.  }
  40.  
  41. #int_CCP1
  42. void  CCP1_isr(void)
  43. {
  44.  cont++;
  45.   if (cont==2)
  46.   {
  47.    contador=get_timer0();
  48.    set_timer0(0);
  49.    
  50.    cont=0;
  51.  //  if (rpm>600)
  52.  //  {
  53.     Segundos++;
  54.     SegundosParcial++;
  55.    
  56. //  }
  57. //*********Cuenta Horas Total**********************************/        
  58.       if(Segundos == 60)
  59.       {
  60.           Minuto++;
  61.           Segundos=0;
  62.              
  63.       if(Minuto == 60)
  64.        {
  65.           Hora++;
  66.           Minuto=0;
  67.        }
  68.       }
  69. /**********Cuenta Horas Parcial*********************************/
  70.       if(SegundosParcial == 60)
  71.       {          
  72.           MinutoParcial++;
  73.           SegundosParcial=0;
  74.              
  75.       if(MinutoParcial == 60)
  76.        {
  77.          
  78.           HoraParcial++;
  79.           MinutoParcial=0;
  80.        }
  81.     }
  82.    
  83.   }    
  84. }
  85. //***************************************************
  86. void main()
  87. {
  88.     set_tris_a(0b00010000);
  89.     output_a(0b00000000);
  90.     set_tris_c(0b01111100);
  91.     output_c(0b00000000);
  92.     set_tris_b(0b00000001);
  93.     output_b(0b00000000);
  94.    
  95. //********************pwm2************************************      
  96.    setup_ccp2(CCP_PWM);
  97.    setup_timer_2(T2_DIV_BY_16,255, 1);
  98.    set_pwm2_duty(duty);  
  99.    setup_adc_ports(NO_ANALOGS);
  100. //**************** INT CCP1 ***********************************
  101.     setup_timer_0(rtcc_ext_h_to_l | rtcc_div_2);
  102.     setup_timer_1(T1_INTERNAL|T1_DIV_BY_8);
  103.     setup_ccp1(CCP_COMPARE_RESET_TIMER);
  104.     CCP_1 = 62500;
  105.     set_timer1(0);
  106.     set_timer0(0);
  107. //***************INT EXT**************************************    
  108.     enable_interrupts(int_ext);
  109.     ext_int_edge(h_to_l);
  110.     enable_interrupts(INT_CCP1);
  111.     enable_interrupts(GLOBAL);
  112.  
  113.  //*************Lectura de eeprom ****************************
  114.    Hora=read_int16_eeprom(100);
  115.    delay_ms(15);
  116.    HoraParcial=read_int16_eeprom(110);
  117.    delay_ms(15);  
  118.    Minuto=read_eeprom(120);
  119.    delay_ms(15);
  120.    MinutoParcial=read_eeprom(130);
  121.    delay_ms(15);
  122.    e=read_float_eeprom(140);
  123.    delay_ms(15);
  124.    service=read_int16_eeprom(150);
  125.    delay_ms(15);
  126.    mantenimiento=read_int16_eeprom(160);
  127.    delay_ms(15);
  128. //*************************************************************
  129.     lcd_init();
  130.     NumGran_Init();      
  131.     lcd_gotoxy(1,1);          
  132.     lcd_putc("      RPM       \n  CUENTA HORAS ");          
  133.     delay_ms(2000);              
  134.     lcd_putc("\f");
  135.  
  136.  while(x==0)
  137.     {  
  138.       if(grabar==1)
  139.        {
  140.           write_int16_eeprom(100, Hora);
  141.           write_int16_eeprom(110, HoraParcial);        
  142.           write_eeprom(120, Minuto);
  143.           write_eeprom(130, MinutoParcial);
  144.           grabar=0;
  145.           lcd_putc("\f");          
  146.           lcd_putc("    APAGANDO     ");          
  147.           delay_ms(500);
  148.        }
  149.           lcd_gotoxy(1,1);          
  150.           printf(lcd_putc," MENU PRINCIPAL   ");          
  151.  
  152.        if (input(pin_c2))          //Paso al siguiente menu
  153.          { delay_ms(100);
  154.            while(input(pin_c2));
  155.             x+=1;                          
  156.           }
  157.        if(input(PIN_c4)==1)       //Regula el backlight del lcd
  158.         { delay_ms(100);
  159.           duty +=15;
  160.          
  161.           if (duty >1023){duty = 1023;}  
  162.         }
  163.        if(input(PIN_c5)==1)       //Regula el backlight del lcd
  164.         { delay_ms(100);
  165.           duty -=15;
  166.          
  167.           if (duty > 1023){duty = 0;}  
  168.         }
  169.          lcd_gotoxy(1,2);
  170.          printf(lcd_putc," BACK LIGHT:%04lu  ",duty);        
  171.          set_pwm2_duty(duty);
  172.          menu=0;                // vuelve a cero el menu
  173.          
  174.  while (x==1)                   //Lectura de RPM
  175.   {
  176.        if (input(pin_c2))      //Paso al siguiente menu
  177.          { delay_ms(100);
  178.            while(input(pin_c2));
  179.             x+=1;                          
  180.           }
  181.          mantenimiento=read_int16_eeprom(160);
  182.          delay_ms(15);        
  183.          service=read_int16_eeprom(150);
  184.          delay_ms(15);
  185.          e=read_float_eeprom(140);
  186.          delay_ms(15);
  187.          
  188.          RPM= contador*e;        
  189.          i =RPM;
  190.          
  191.          lcd_send_byte(0,1);
  192.          delay_us(2);
  193.          NumGran(i);
  194.          printf(lcd_putc,"RPM");
  195.          delay_ms(80);    
  196.          
  197.          i = RPM;
  198.          delay_ms(300);                  
  199.          printf(lcd_putc," %04lu",i);    
  200.            
  201.      if ( Minuto>=mantenimiento&&(input(pin_c2)==0))//ATENCION cambiar Minuto por horas
  202.       {    
  203.          
  204.         lcd_gotoxy(13,1);
  205.         lcd_putc("Mant ");//
  206.         delay_ms(500);
  207.      
  208.       }
  209.  //********************pwm2**************************************
  210.  
  211.     }
  212.    
  213.  while (x==2)                    //cuenta horas parcial y total
  214.      {
  215.    
  216.        if (input(pin_c2))
  217.          { delay_ms(50);
  218.            while(input(pin_c2));
  219.             x+=1;                          
  220.          }  
  221.  
  222.          lcd_gotoxy(1,1);
  223.          printf(lcd_putc,"Par  %05lu:%02u:%02u",HoraParcial,MinutoParcial,SegundosParcial);
  224.          
  225.          lcd_gotoxy(1,2);
  226.          printf(lcd_putc,"Tot  %05lu:%02u:%02u",Hora,Minuto,Segundos);
  227.            
  228.       }  
  229.                                  
  230.    while (x==3)                        //Aviso de proximo service
  231.     {
  232.        if (input(pin_c2))             //Paso al siguiente menu
  233.          { delay_ms(50);
  234.            while(input(pin_c2));
  235.             x+=1;                          
  236.           }
  237.            service=read_int16_eeprom(150);
  238.            delay_ms(15);
  239.            lcd_gotoxy(1,1);
  240.            printf(lcd_putc,"Proximo Service \n   %4lu Horas     ",service);          
  241.          
  242.     }
  243.        
  244.  /***********************ENTRA AL  MENU*************************************/
  245.  
  246.    while (x==4)
  247.     {
  248.        if (input(pin_c2))         //Paso al siguiente menu
  249.          { delay_ms(50);
  250.            while(input(pin_c2));
  251.             x=0;                          
  252.           }    
  253.         menus();                //Funcion de menus
  254.              
  255.         if (input(pin_c3))      //desplaza dentro de la configuracion
  256.        {   delay_ms(50);
  257.        while(input(pin_c3));
  258.         {
  259.            menu++;  
  260.        if (menu>6)
  261.            menu=0;            
  262.         }          
  263.        }
  264.      
  265.    switch (menu+1)
  266.    {
  267.      case  1:                    //Aviso de entrada en configuracion
  268.                  
  269.               lcd_gotoxy(1,1);
  270.               printf(lcd_putc," CONFIGURACION    \n                   ");
  271.              
  272.               break;
  273.                  
  274.      case  2 :                  //Service
  275.  
  276.               lcd_gotoxy(1,1);
  277.               printf(lcd_putc,"Programe Service");
  278.  
  279.               if (input(pin_c4)==1)    
  280.              {    delay_ms(200);       // antirebote
  281.                
  282.                     b+=1;        
  283.              }
  284.              if (input(pin_c5)==1)  // Boton que decrementa
  285.              { delay_ms(200);
  286.              
  287.                     b-=1;
  288.              }
  289.              
  290.              lcd_gotoxy(1,2);
  291.              printf(lcd_putc,"   Horas  %4lu    ",b);
  292.              
  293.              if (input(pin_c6)==1)
  294.              { delay_ms(50);
  295.               while(input(pin_c6));            
  296.                write_int16_eeprom(150, b);  // escribe en la memoria
  297.                delay_ms(25);
  298.                service=read_int16_eeprom(150);
  299.                delay_ms(15);
  300.                mantenimiento=Minuto+service;//ATENCION cambiar Minuto por hora
  301.                write_int16_eeprom(160,mantenimiento);  // escribe en la memoria
  302.                delay_ms(15);              
  303.                mantenimiento=read_int16_eeprom(160);
  304.                delay_ms(15);
  305.                lcd_gotoxy(1,2);
  306.                printf(lcd_putc,"    Memorizado     ");
  307.                delay_ms(1000);
  308.              }
  309.               break;
  310.              
  311.      case  3 :                               //CALIBRA RPM
  312.               e=read_float_eeprom(140);
  313.               delay_ms(15);
  314.               RPM= contador*e;
  315.               lcd_gotoxy(1,1);
  316.               printf(lcd_putc,"Actual RPM %lu       ",RPM);
  317.               if (input(pin_c4)==1)
  318.              {  
  319.                    delay_ms(200);                    
  320.                    ajuste+=0.02;          // Incremento
  321.              }
  322.              if (input(pin_c5)==1)
  323.              {  
  324.                  delay_ms(200);
  325.                  ajuste-=0.02;        //Decremento  
  326.              }              
  327.              if (input(pin_c6)==1)
  328.              { delay_ms(50);
  329.               while(input(pin_c6));            
  330.                write_float_eeprom(140, ajuste);  
  331.                delay_ms(15);  
  332.              }              
  333.               RPM= contador*ajuste;
  334.               lcd_gotoxy(1,2);
  335.               printf(lcd_putc,"Ajuste RPM %lu       ",RPM);        
  336.               break;
  337.                
  338.      case  4 :                                
  339.               lcd_gotoxy(1,1);
  340.               printf(lcd_putc,"   RESET TOTAL    ");
  341.               lcd_gotoxy(1,2);
  342.               printf(lcd_putc,"   %05lu:%02u:%02u  ",Hora,Minuto,Segundos);
  343.               if (input(pin_c6)==1) // Reset de cuenta horas parcial
  344.                {  delay_ms(300);
  345.                   Hora=00000;
  346.                   write_int16_eeprom(100, Hora);
  347.                   delay_ms(15);
  348.                   Minuto=00;
  349.                   write_eeprom(120, Minuto);
  350.                   delay_ms(15);
  351.               }
  352.               break;  
  353.  
  354.              
  355.      case  5 :
  356.               lcd_gotoxy(1,1);
  357.               printf(lcd_putc,"  RESET PARCIAL    ");
  358.               lcd_gotoxy(1,2);
  359.               printf(lcd_putc,"   %05lu:%02u:%02u  ",HoraParcial,MinutoParcial,Segundos);
  360.               if (input(pin_c6)==1) // Reset de cuenta horasparcial
  361.                {  delay_ms(300);
  362.                   HoraParcial=00000;
  363.                   write_int16_eeprom(110, HoraParcial);
  364.                   delay_ms(15);              
  365.                   MinutoParcial=00;
  366.                   write_eeprom(130, MinutoParcial);
  367.                   delay_ms(15);
  368.                }
  369.               break;              
  370.       case  6 :
  371.                menu=0;
  372.                break;
  373.    }        
  374.  }        
  375.     }
  376.  
  377. }
Título: Re:Ayuda con lcd
Publicado por: Abner_emanuel en 27 de Octubre de 2015, 13:27:45

Que tal arielmdq te adjunto un code el cual había comentado que requería los números grandes en lcd, cosa que por el momento descarte. Aun que aun asi lo comparto y espero te sirvaen algo, ya que este lleva el grabar datos en la eeprom y menú.

Código: CSS
  1. #include <18F4550.h>
  2.          #priority int_ext
  3.          #fuses PLL1,CPUDIV1,USBDIV,XTPLL,NOFCMEN,NOIESO,PUT,NOBROWNOUT,VREGEN,NOWDT,WDT32768,NOPBADEN,MCLR,NOSTVREN,NOLVP,NODEBUG,PROTECT,NOSTVREN,NOCPB,NOWRT
  4.          #use delay(clock=48000000,RESTART_WDT)
  5.          #byte porta = 0xF80 #byte portb = 0xF81 #byte portc = 0xf82 #byte portd = 0xf83 #byte porte = 0xf84  
  6.        
  7.          #byte pb      = 0xF81
  8.          #bit t_ok     = pb.0
  9.          #bit t_mas    = pb.1
  10.          #bit t_mns    = pb.2
  11.          #byte intcon  = 0xFF2
  12.          #byte intcon3 = 0xFF0
  13.          #bit  intf    = intcon.1
  14.          #bit  intf1   = intcon3.0
  15.          #bit  intf2   = intcon3.1        
  16.          #use fast_io(b)
  17.          #define led_verde    output_e(4);
  18.          #define led_naranja  output_e(2);
  19.          #define led_rojo     output_e(1);
  20.          #define led_off      output_e(0);
  21.          #include <lcd4x20.c>
  22.          #include <menu.h>  
  23.          
  24.          static unsigned int8 seg_tmr0=0, min_tmr0=0, seg_0=0, min_0=0, seg_1=0, min_1=0, seg_2=0, min_2=0, bandera=0;
  25.          void arranque(void);                                        
  26.          void suma_tiempo_eeprom(void);
  27.          
  28.          #int_timer0                                                    // Interrupcion para 1S
  29.          void timer0(void)
  30.          { seg_tmr0++; if(seg_tmr0>59){seg_tmr0=0; min_tmr0++;} if(min_tmr0>59){min_tmr0=0;} set_timer0(18652);}
  31.          
  32.          #INT_EXT1
  33.          void pausa()
  34.          { disable_interrupts(INT_TIMER0); }
  35.          
  36.          #INT_EXT2
  37.          void continua()
  38.          { enable_interrupts(INT_TIMER0);  }
  39.          
  40.          void main(void)
  41.          {        
  42.          port_b_pullups(true);
  43.          setup_adc_ports(NO_ANALOGS);
  44.          lcd_init();
  45.          
  46.          intf=0; intf1=0; intf2=0;        
  47.          setup_timer_0(RTCC_INTERNAL|RTCC_DIV_256);                
  48.          set_timer0(18661);
  49.          
  50.          enable_interrupts(INT_EXT);
  51.          enable_interrupts(INT_EXT1);
  52.          enable_interrupts(INT_EXT2);
  53.          disable_interrupts(INT_TIMER0);
  54.          enable_interrupts(GLOBAL);
  55.          
  56.          seg_tmr0=0,min_tmr0=0,seg_0=0,min_0=0,seg_1=0,min_1=0,seg_2=0,min_2=0,bandera=0;
  57.          eeprom_segundos_0=0,eeprom_minutos_0=0,eeprom_segundos_1=0,eeprom_minutos_1=0,eeprom_segundos_2=0,eeprom_minutos_2=0;    
  58.          
  59.          eeprom_minutos_1=read_eeprom(INT_EEPROMA); eeprom_segundos_1=read_eeprom(INT_EEPROMB); eeprom_minutos_2=read_eeprom(INT_EEPROMC);
  60.          eeprom_segundos_2=read_eeprom(INT_EEPROMD); eeprom_minutos_0=read_eeprom(INT_EEPROME); eeprom_segundos_0=read_eeprom(INT_EEPROMF);
  61.          led_off
  62.          
  63.          while(true)
  64.          {
  65.          lcd_gotoxy(1,1); printf(lcd_putc,"TIME TOTAL = %02u:%02u"minutos_total,segundos_total);
  66.          lcd_gotoxy(1,2); printf(lcd_putc,"TIME1 %02u:%02u  %02u:%02u",min_0,seg_0,eeprom_minutos_0,eeprom_segundos_0);
  67.          lcd_gotoxy(1,3); printf(lcd_putc,"TIME2 %02u:%02u  %02u:%02u",min_1,seg_1,eeprom_minutos_1,eeprom_segundos_1);
  68.          lcd_gotoxy(1,4); printf(lcd_putc,"TIME3 %02u:%02u  %02u:%02u",min_2,seg_2,eeprom_minutos_2,eeprom_segundos_2);        
  69.          arranque(); cgram_reloj_1(); suma_tiempo_eeprom();
  70.          
  71.          }
  72.          }
  73.                  
  74.          void arranque(void)        
  75.          {
  76.          if(!input(pin_b3)) { delay_ms(200); bandera=1; enable_interrupts(INT_TIMER0);}  
  77.          if (bandera==1)   { seg_0=seg_tmr0; min_0=min_tmr0; led_verde   if(eeprom_segundos_0==seg_0 && eeprom_minutos_0==min_0){seg_tmr0=0; min_tmr0=0; bandera=2;}}
  78.          if (bandera==2)   { seg_1=seg_tmr0; min_1=min_tmr0; led_naranja if(eeprom_segundos_1==seg_1 && eeprom_minutos_1==min_1){seg_tmr0=0; min_tmr0=0; bandera=3;}}        
  79.          if (bandera==3)   { seg_2=seg_tmr0; min_2=min_tmr0; led_rojo    if(eeprom_segundos_2==seg_2 && eeprom_minutos_2==min_2){seg_tmr0=0; min_tmr0=0; bandera=4; led_off}}  
  80.          if (seg_0>=2 && !input(pin_b3)) { while(seg_0>=2 && !input(pin_b3)); disable_interrupts(GLOBAL);}
  81.          }
  82.          
  83.          void suma_tiempo_eeprom(void)
  84.          {
  85.          segundos_total = eeprom_segundos_0 + eeprom_segundos_1 + eeprom_segundos_2;
  86.          minutos_total = eeprom_minutos_0 + eeprom_minutos_1 + eeprom_minutos_2;
  87.          aux = segundos_total/60;                                       // Solo divido una ves ya que es lo mas consumidor
  88.          minutos_total += aux;
  89.          segundos_total -= aux*60;
  90.          }


y el menú.h es elsiguiente:


Código: CSS
  1. unsigned int8 INT_EEPROMA = 0;
  2.          unsigned int8 INT_EEPROMB = 1;
  3.          unsigned int8 INT_EEPROMC = 2;
  4.          unsigned int8 INT_EEPROMD = 3;
  5.          unsigned int8 INT_EEPROME = 4;
  6.          unsigned int8 INT_EEPROMF = 5;
  7.          
  8.          void menu_cronometro_1(void);    
  9.          void menu_cronometro_2(void);
  10.          void menu_cronometro_3(void);
  11.          void cgram_reloj(void);
  12.          void cgram_reloj_1(void);
  13.          void cgram_flecha(void);
  14.          
  15.          static unsigned int8 testado,i,k;
  16.          int segundos_total,minutos_total,aux;
  17.          static unsigned int8 eeprom_segundos_0=0, eeprom_minutos_0=0, eeprom_segundos_1=0, eeprom_minutos_1=0, eeprom_segundos_2=0, eeprom_minutos_2=0;  
  18.          int const  relojChar[8]={0,14,19,21,17,14,31,0};
  19.          int const  flechaChar[8]={0,4,8,31,8,4,0,0};
  20.          
  21.          #INT_EXT
  22.          void menu()
  23.          {
  24.          disable_interrupts(GLOBAL);
  25.          disable_interrupts(INT_EXT);
  26.          disable_interrupts(INT_EXT1);
  27.          disable_interrupts(INT_EXT2);
  28.          delay_ms(300);
  29.          testado=0;
  30.          lcd_putc("\f");
  31.          lcd_gotoxy(2,1); lcd_putc("AJUSTE OPCION: [ ]");
  32.          lcd_gotoxy(1,2); lcd_putc("[1] CRONOMETRO 1   ");
  33.          lcd_gotoxy(1,3); lcd_putc("[2] CRONOMETRO 2   ");
  34.          lcd_gotoxy(1,4); lcd_putc("[3] CRONOMETRO 3   ");
  35.          
  36.          for(i=0;i!=255;i++)
  37.          {
  38.          delay_ms(20);
  39.          lcd_gotoxy(18,1);
  40.          printf(lcd_putc,"%u",testado);
  41.          if (!t_ok){delay_ms(300); break;}
  42.          else if (!t_mas){i=0; delay_ms(300); testado++; if(testado>3){testado=0;};}
  43.          else if (!t_mns){i=0; delay_ms(300); testado--; if(testado==255){testado=3;};}        
  44.          if(testado==0){ lcd_gotoxy(18,2); printf(lcd_putc,"  "); lcd_gotoxy(18,3); printf(lcd_putc,"  "); lcd_gotoxy(18,4); printf(lcd_putc,"  "); }
  45.          if(testado==1){ cgram_flecha(); lcd_gotoxy(18,2); lcd_send_byte(1,0); lcd_gotoxy(18,3); printf(lcd_putc,"  "); lcd_gotoxy(18,4); printf(lcd_putc,"  "); }
  46.          if(testado==2){ cgram_flecha(); lcd_gotoxy(18,3); lcd_send_byte(1,0); lcd_gotoxy(18,2); printf(lcd_putc,"  "); lcd_gotoxy(18,4); printf(lcd_putc,"  "); }
  47.          if(testado==3){ cgram_flecha(); lcd_gotoxy(18,4); lcd_send_byte(1,0); lcd_gotoxy(18,2); printf(lcd_putc,"  "); lcd_gotoxy(18,3); printf(lcd_putc,"  "); }        
  48.          };
  49.          if(testado==0)
  50.          {
  51.          intf=0; intf1=0; intf2=0;
  52.          enable_interrupts(GLOBAL);
  53.          enable_interrupts(INT_EXT);
  54.          enable_interrupts(INT_EXT1);
  55.          enable_interrupts(INT_EXT2);
  56.          lcd_putc("\f");
  57.          break;
  58.          }
  59.          else if(testado==1){menu_cronometro_1(); lcd_putc("\f");}
  60.          else if(testado==2){menu_cronometro_2(); lcd_putc("\f");}
  61.          else if(testado==3){menu_cronometro_3(); lcd_putc("\f");}
  62.          }
  63.          
  64. ////////////////////////////////////////////////////////////////////////////////
  65. //    Submenu Ajuste RTC
  66. //
  67. ///////////////////////////////////////////////////////////////////////////////
  68.          
  69.          void menu_cronometro_1(void)
  70.          {
  71.          lcd_putc("\f");        
  72.          lcd_gotoxy(5,1); lcd_putc("CRONOMETRO 1");
  73.          lcd_gotoxy(2,3); printf(lcd_putc,"TIEMPO 1: %02u:%02u",eeprom_minutos_0,eeprom_segundos_0);
  74.          cgram_reloj();
  75.        
  76.          for(i=0;i!=255;i++)
  77.          {
  78.          delay_ms(20);
  79.          lcd_gotoxy(12,3); printf(lcd_putc,"%02u",eeprom_minutos_0); lcd_gotoxy(12,4); printf(lcd_putc,"--");
  80.          if(!t_ok){delay_ms(300); break;}
  81.          else if(!t_mas){i=0; delay_ms(300); eeprom_minutos_0++; if(eeprom_minutos_0>59)  {eeprom_minutos_0=0;}; }
  82.          else if(!t_mns){i=0; delay_ms(300); eeprom_minutos_0--; if(eeprom_minutos_0==255){eeprom_minutos_0=59;};}        
  83.          }; write_eeprom(INT_EEPROMA,eeprom_minutos_0);
  84.        
  85.          for(i=0;i!=255;i++)
  86.          {
  87.          delay_ms(20);
  88.          lcd_gotoxy(15,3); printf(lcd_putc,"%02u",eeprom_segundos_0); lcd_gotoxy(12,4); printf(lcd_putc,"   --");
  89.          if(!t_ok){delay_ms(300); break;}
  90.          else if(!t_mas){i=0; delay_ms(300); eeprom_segundos_0++; if(eeprom_segundos_0>59)  {eeprom_segundos_0=0;}; }
  91.          else if(!t_mns){i=0; delay_ms(300); eeprom_segundos_0--; if(eeprom_segundos_0==255){eeprom_segundos_0=59;};}        
  92.          }; write_eeprom(INT_EEPROMB,eeprom_segundos_0);
  93.          
  94.          intf=0; intf1=0; intf2=0;
  95.          enable_interrupts(GLOBAL);
  96.          enable_interrupts(INT_EXT);
  97.          enable_interrupts(INT_EXT1);
  98.          enable_interrupts(INT_EXT2);
  99.          }
  100.          
  101. ////////////////////////////////////////////////////////////////////////////////
  102.          
  103.          void menu_cronometro_2(void)
  104.          {
  105.          lcd_putc("\f");        
  106.          lcd_gotoxy(5,1); lcd_putc("CRONOMETRO 2");
  107.          lcd_gotoxy(2,3); printf(lcd_putc,"TIEMPO 2: %02u:%02u",eeprom_minutos_1,eeprom_segundos_1);
  108.          cgram_reloj();
  109.          
  110.          for(i=0;i!=255;i++)
  111.          {
  112.          delay_ms(20);
  113.          lcd_gotoxy(12,3); printf(lcd_putc,"%02u",eeprom_minutos_1); lcd_gotoxy(12,4); printf(lcd_putc,"--");
  114.          if(!t_ok){delay_ms(300); break;}
  115.          else if(!t_mas){i=0; delay_ms(300); eeprom_minutos_1++; if(eeprom_minutos_1>59)  {eeprom_minutos_1=0;}; }
  116.          else if(!t_mns){i=0; delay_ms(300); eeprom_minutos_1--; if(eeprom_minutos_1==255){eeprom_minutos_1=59;};}        
  117.          }; write_eeprom(INT_EEPROMC,eeprom_minutos_1);
  118.          
  119.          for(i=0;i!=255;i++)
  120.          {
  121.          delay_ms(20);
  122.          lcd_gotoxy(15,3); printf(lcd_putc,"%02u",eeprom_segundos_1); lcd_gotoxy(12,4); printf(lcd_putc,"   --");
  123.          if(!t_ok){delay_ms(300); break;}
  124.          else if(!t_mas){i=0; delay_ms(300); eeprom_segundos_1++; if(eeprom_segundos_1>59)  {eeprom_segundos_1=0;}; }
  125.          else if(!t_mns){i=0; delay_ms(300); eeprom_segundos_1--; if(eeprom_segundos_1==255){eeprom_segundos_1=59;};}        
  126.          }; write_eeprom(INT_EEPROMD,eeprom_segundos_1);
  127.          
  128.          intf=0; intf1=0; intf2=0;
  129.          enable_interrupts(GLOBAL);
  130.          enable_interrupts(INT_EXT);
  131.          enable_interrupts(INT_EXT1);
  132.          enable_interrupts(INT_EXT2);
  133.          }
  134.          
  135. ////////////////////////////////////////////////////////////////////////////////
  136.  
  137.          void menu_cronometro_3(void)
  138.          {
  139.          lcd_putc("\f");        
  140.          lcd_gotoxy(5,1); lcd_putc("CRONOMETRO 3");
  141.          lcd_gotoxy(2,3); printf(lcd_putc,"TIEMPO 3: %02u:%02u",eeprom_minutos_2,eeprom_segundos_2);
  142.          cgram_reloj();
  143.          
  144.          for(i=0;i!=255;i++)
  145.          {
  146.          delay_ms(20);
  147.          lcd_gotoxy(12,3); printf(lcd_putc,"%02u",eeprom_minutos_2); lcd_gotoxy(12,4); printf(lcd_putc,"--");
  148.          if(!t_ok){delay_ms(300); break;}
  149.          else if(!t_mas){i=0; delay_ms(300); eeprom_minutos_2++; if(eeprom_minutos_2>59)  {eeprom_minutos_2=0;}; }
  150.          else if(!t_mns){i=0; delay_ms(300); eeprom_minutos_2--; if(eeprom_minutos_2==255){eeprom_minutos_2=59;};}        
  151.          }; write_eeprom(INT_EEPROME,eeprom_minutos_2);
  152.          
  153.          for(i=0;i!=255;i++)
  154.          {
  155.          delay_ms(20);
  156.          lcd_gotoxy(15,3); printf(lcd_putc,"%02u",eeprom_segundos_2); lcd_gotoxy(12,4); printf(lcd_putc,"   --");
  157.          if(!t_ok){delay_ms(300); break;}
  158.          else if(!t_mas){i=0; delay_ms(300); eeprom_segundos_2++; if(eeprom_segundos_2>59)  {eeprom_segundos_2=0;}; }
  159.          else if(!t_mns){i=0; delay_ms(300); eeprom_segundos_2--; if(eeprom_segundos_2==255){eeprom_segundos_2=59;};}            
  160.          }; write_eeprom(INT_EEPROMF,eeprom_segundos_2);
  161.          
  162.          intf=0; intf1=0; intf2=0;
  163.          enable_interrupts(GLOBAL);
  164.          enable_interrupts(INT_EXT);
  165.          enable_interrupts(INT_EXT1);
  166.          enable_interrupts(INT_EXT2);
  167.          break;
  168.          }
  169.          
  170.          void cgram_reloj(void)
  171.          {                  
  172.          lcd_send_byte(0,0x40);                                                      
  173.          for (k=0;k<8;k++) {lcd_send_byte(1,relojChar[k]);} lcd_gotoxy(19,3); lcd_send_byte(1,0);          
  174.          }
  175.                
  176.          void cgram_reloj_1(void)
  177.          {
  178.          lcd_send_byte(0,0x48);                                                      
  179.          for (k=0;k<8;k++) {lcd_send_byte(1,relojChar[k]);} lcd_gotoxy(20,2); lcd_send_byte(1,1); lcd_gotoxy(20,3); lcd_send_byte(1,1); lcd_gotoxy(20,4); lcd_send_byte(1,1);  
  180.          }
  181.          
  182.          void cgram_flecha(void)
  183.          {                  
  184.          lcd_send_byte(0,0x40);                                                      
  185.          for (k=0;k<8;k++) {lcd_send_byte(1,flechaChar[k]);} lcd_gotoxy(18,2); lcd_send_byte(1,0);          
  186.          }
  187.            
  188.          
  189. ////////////////////////////////////////////////////////////////////////////////


 
Título: Re:Ayuda con lcd
Publicado por: arielmdq en 27 de Octubre de 2015, 18:17:47
Muchas gracias emanuel lo voy a chequear
Título: Re:Ayuda con lcd
Publicado por: Abner_emanuel en 27 de Octubre de 2015, 18:21:53
Parece que te envíe una versión anterior, en esta que envío esta un poco mas clara y con algunos cambios mas eficientes.

Yo lo realice un semáforo de tiempo configurable que me pidió un amigo. El lo utilizaría para dar clases de oratoria en la que los alumnos tenían cierto tiempo para exponer.
El tiempo es configurable debido a que como van aumentando el nivel van dando mas tiempo de exposición. Bueno espero te sirva de algo y gracias a killerjc por su ayuda.


Título: Re:Ayuda con lcd
Publicado por: KILLERJC en 28 de Octubre de 2015, 05:39:31
arielmdq, a no ser que exista un while grande que encierre a todos los while , nunca va a entrar de nuevo al while(x==0), estas cada vez mas cerca de la solucion que decia antes.


Código: C
  1. while(1)
  2. {
  3.  
  4.    switch(x) {
  5.         case 0:
  6.                 Codigo_while0();  //Aca el codigo de lo que tenes dentro del while x==0
  7.                 break;
  8.         case 1:
  9.                 Codigo_while1();  //Aca el codigo de lo que tenes dentro del while x==1
  10.                 break;
  11.         case 2:
  12.                 Codigo_while2();  //Aca el codigo de lo que tenes dentro del while x==2
  13.                 break;
  14.         case 3:
  15.                 Codigo_while3();  //Aca el codigo de lo que tenes dentro del while x==3
  16.                 break;
  17.         case 4:
  18.                 Codigo_while4();  //Aca el codigo de lo que tenes dentro del while x==4
  19.                 break;
  20.         default:
  21.                 x=1;    //x no termino con un valor correcto, hubo un problema, entonces lo pongo en el valor inicial que corresponda
  22.                 break;
  23.      }
  24. }

A tu codigo lo podes dividir en funciones, asi que no te quedan 2 SUPER SWITCH en el codigo. Y el main te queda limpio y facil de entender.
Sino tu codigo estaria peor que los codigos anteriores. Pensa que nunca deberias tener muchos while o do..while.
Título: Re:Ayuda con lcd
Publicado por: arielmdq en 28 de Octubre de 2015, 09:09:56
Hola killerjc, efectivamente el while (x==0) es el while que encierra todo ,de esta manera tambien puedo hacer todo con pulsadores ,ya no necesito mas el interruptor que antes tenía para pasar del menu principal a la configuracion .Ahora pulsando pin_C2 me desplazo por el menu principal siempre de manera ascendente cuando llega al while(x==4) vuelve a empezar por el while (x==0).
Cuando llega al while(x==4) muestro la palabra  configuracion ,que para no entrar accidentalmente en la configuracion cambio de pulsador,ahora con el pin_C3 me desplazo dentro de la configuracion, con pin_C4 y pin_ C5 incremento o decremento las variables y con pin_C6 grabo en memoria.Cuando me encuentro dentro de configuracion pulsando pin_C2 vuelvo al menu principal .
Esta es la manera en que lo pensé, lo que no quiere decir ni que sea correcta ni que sea prolija  :D :D :D.
Pero bueno la opcion que propones ahora es claramente mas clara valga la redundancia  :D  bien voy a probar con dividirlo en funciones como me decis.
Entonces sería un while y un switch y cada case sea una  funcion ?.
Tengo que armar todas la funciones antes del void main () ?
Y todo el menu de configuracion tambien quedaría dentro de un case ?
Te cuento, no me enrrosque mucho en implementar lo del codigo en asm que me explicaste la otra vez,por que seguí haciendo pruebas y ya no era un problema lo de grabar en la memoria, con lo del circuito de chaly tengo tiempo suficiente para hacerlo hasta imprimo una palabra despues de grabar y antes que se termine la alimentacion y no me ha fallado .Pero lo que si me interesa es lo optimizar el codigo y aprender a hacerlo como corresponde.
Como siempre te agradezco mucho la ayuda .
                                                                                                         Saludos !!! 
Título: Re:Ayuda con lcd
Publicado por: KILLERJC en 28 de Octubre de 2015, 09:22:11
Esta bien. pense que no habia un while que encerrara todo, pero tenes que asegurarte que NO salga de ese while, es decir siempre exista un loop infinito.
Por lo tanto el while(x==0) deberias ser mas un while(1) , asi nunca, bajo ninguna cirscuntancia es posible salir de ese while
Título: Re:Ayuda con lcd
Publicado por: arielmdq en 28 de Octubre de 2015, 09:25:31
Aaa ok te entiendo
Título: Re:Ayuda con lcd
Publicado por: arielmdq en 31 de Octubre de 2015, 08:21:52
Hola Killerjc ,volvi a cambiar el programa mas o menos como me recomendaste y queria subirlo para ver que opinas .Ahora hice un par  funciones ,un bucle infinito y dentro de él 2, while (chiste : no puedo salir de los while  :D ) en uno se encuentra el switch y las condiciones para desplazarme sobre él .Lo hice para poder moverme de la misma forma que el programa anterior ,con un menu principal y uno de configuracion, cuando llego al case 5 que es el ingreso a la configuracion ,para poder entrar tengo que pulsar otro boton sino vuelvo al menu principal.Lo bueno ahora es que pude eliminar otro pulsador ahora solo tengo 4,(antes5).
Y el otro while es el que entra con la interrupcion cuando detecta el flanco de bajada por Rb0 desactivo  la backlight y coloco en 1 la bandera (grabar) y de esta forma me aseguro que se graben los datos en memoria ,cuando termina pongo grabar otra vez en 0.
Preguntas:
                  Tengo partes dentro del switch (case 6,7,8,9 ) donde configuro parametros ,aca tambien tendría que hacer funciones fuera del main y luego llamarlas en los case ? tiene algun sentido ?
                  Tengo dudas en las partes en las que leo la memoria ya sea para luego imprimir en pantalla o para hacer cuentas con ese dato es necesario siempre aclarar :service=read_int16_eeprom(150);antes de usarlo( en este caso service)o con que este declarado dentro del void main() ya esta y no tengo que volver a llamarlo?
Aca esta el codigo:
Código: C
  1. #include <16f876a.h>
  2. #device adc=10
  3. #use delay(clock=4000000)
  4. #fuses HS,NOWDT,NOPROTECT,NOLVP,PUT,NODEBUG,BROWNOUT,NOCPD,NOWRT
  5. #define LCD_ENABLE_PIN  PIN_B3                                    ////
  6. #define LCD_RS_PIN      PIN_B1                                    ////
  7. #define LCD_RW_PIN      PIN_B2                                    ////
  8. #define LCD_DATA4       PIN_B4                                    ////
  9. #define LCD_DATA5       PIN_B5                                    ////
  10. #define LCD_DATA6       PIN_B6                                    ////
  11. #define LCD_DATA7       PIN_B7
  12. #include <lcd.c>
  13. #include <NumGran.C>
  14. #include <internal_eeprom.c>
  15. #use fast_io(B)
  16. #use fast_io(c)
  17. #use fast_io(a)
  18.  
  19. //****variables del cuneta vueltas***//
  20. int16 contador=0,RPM,duty=0;
  21. float ajuste=10,e;      
  22. //****variables del cuneta horas***//
  23. int8 Segundos=0,SegundosParcial=0,Minuto=0,MinutoParcial=0;
  24. int menu=0;
  25. int16 b=0,service=0, Hora=0,cont=0, HoraParcial=0,mantenimiento=0;
  26. short grabar=0,flag=0;
  27.  
  28. //*********Funciones**************************
  29. #int_ext
  30. void corte()
  31.  {
  32.     duty=0;
  33.     grabar=1;        
  34.  }
  35. #int_CCP1
  36. void  CCP1_isr(void)
  37. {
  38.  cont++;
  39.   if (cont==2)
  40.   {
  41.    contador=get_timer0();
  42.    set_timer0(0);
  43.    
  44.    cont=0;
  45.  //  if (rpm>600)
  46.  //  {
  47.     Segundos++;
  48.     SegundosParcial++;
  49. //  }
  50. //*********Cuenta Horas Total**********************************/        
  51.       if(Segundos == 60)
  52.       {
  53.           Minuto++;
  54.           Segundos=0;
  55.              
  56.       if(Minuto == 60)
  57.        {
  58.           Hora++;
  59.           Minuto=0;
  60.        }
  61.       }
  62. /**********Cuenta Horas Parcial*********************************/
  63.       if(SegundosParcial == 60)
  64.       {          
  65.           MinutoParcial++;
  66.           SegundosParcial=0;
  67.              
  68.       if(MinutoParcial == 60)
  69.        {
  70.          
  71.           HoraParcial++;
  72.           MinutoParcial=0;
  73.        }
  74.     }  
  75.   }    
  76. }
  77. int menus(void)
  78. {
  79. return (menu+'1');
  80. }
  81. void leer_memoria()
  82. {
  83.          Hora=read_int16_eeprom(100);
  84.          delay_ms(15);
  85.          HoraParcial=read_int16_eeprom(110);
  86.          delay_ms(15);  
  87.          Minuto=read_eeprom(120);
  88.          delay_ms(15);
  89.          MinutoParcial=read_eeprom(130);
  90.          delay_ms(15);
  91.          mantenimiento=read_int16_eeprom(160);
  92.          delay_ms(15);        
  93.          service=read_int16_eeprom(150);
  94.          delay_ms(15);
  95.          e=read_float_eeprom(140);
  96.          delay_ms(15);
  97. }
  98. void cuenta_horas()
  99. {  
  100.      
  101.          lcd_gotoxy(1,1);
  102.          printf(lcd_putc,"Par  %05lu:%02u:%02u",HoraParcial,MinutoParcial,SegundosParcial);
  103.          
  104.          lcd_gotoxy(1,2);
  105.          printf(lcd_putc,"Tot  %05lu:%02u:%02u",Hora,Minuto,Segundos);
  106. }
  107. void cuenta_vueltas()
  108. {    
  109.                
  110.          RPM= contador*e;
  111.          
  112.          lcd_send_byte(0,1);
  113.          delay_us(2);
  114.          NumGran(RPM);          
  115.          printf(lcd_putc,"RPM");
  116.      
  117.          delay_ms(300);  //aca iban 300ms                
  118.          printf(lcd_putc," %04lu    ",RPM);
  119.      if ( Minuto>=mantenimiento&&mantenimiento>0)//ATENCION cambiar Minuto por horas
  120.       {    
  121.    
  122.         lcd_gotoxy(13,1);
  123.         lcd_putc("Mant ");//
  124.         delay_ms(500);
  125.       }        
  126. }
  127. void back_light()
  128. {
  129.        if(input(PIN_c4))       //Regula el backlight del lcd
  130.         { delay_ms(100);
  131.           duty +=15;
  132.          
  133.           if (duty >1023){duty = 1023;}  
  134.         }
  135.        if(input(PIN_c5))       //Regula el backlight del lcd
  136.         { delay_ms(100);
  137.           duty -=15;
  138.          
  139.           if (duty > 1023){duty = 0;}  
  140.         }
  141.          lcd_gotoxy(1,1);
  142.          printf(lcd_putc,"   BACK LIGHT   \n      %04lu     ",duty);        
  143.          set_pwm2_duty(duty);
  144. }
  145. //***************************************************
  146. void main()
  147. {
  148.     set_tris_a(0b00010000);
  149.     output_a(0b00000000);
  150.     set_tris_c(0b01111110);// 0 = salidas
  151.     output_c(0b00000000);
  152.     set_tris_b(0b00000001);
  153.     output_b(0b00000000);
  154. //********************pwm2************************************      
  155.     setup_ccp2(CCP_PWM);
  156.     setup_timer_2(T2_DIV_BY_16,255, 1);
  157.     set_pwm2_duty(duty);
  158. //************************************************************    
  159.     setup_adc_ports(NO_ANALOGS);    
  160.     setup_timer_0(rtcc_ext_h_to_l | rtcc_div_2);
  161.     setup_timer_1(T1_INTERNAL|T1_DIV_BY_8);
  162.     setup_ccp1(CCP_COMPARE_RESET_TIMER);
  163.     CCP_1 = 62500;
  164.     set_timer1(0);
  165.     set_timer0(0);
  166. //******************INT EXT***********************************    
  167.     enable_interrupts(int_ext);
  168.     ext_int_edge(h_to_l);
  169.     enable_interrupts(INT_CCP1);
  170.     enable_interrupts(GLOBAL);
  171. //************************************************************    
  172.     leer_memoria();           // Funcion para leer la memoria
  173.  
  174.     lcd_init();
  175.     NumGran_Init();      
  176.     lcd_gotoxy(1,1);          
  177.     lcd_putc(" RPM Y HORIMETRO ");          
  178.     delay_ms(2000);              
  179.     lcd_putc("\f");
  180.  
  181.  while(1)
  182.     {
  183.      while(grabar==1)
  184.       {
  185.         write_int16_eeprom(100, Hora);
  186.         write_int16_eeprom(110, HoraParcial);        
  187.         write_eeprom(120, Minuto);
  188.         write_eeprom(130, MinutoParcial);
  189.         grabar=0;
  190.         lcd_putc("\f");          
  191.         lcd_putc("    APAGANDO     ");          
  192.         delay_ms(500);
  193.        }
  194.     while(grabar==0)
  195.       {      
  196.    if(flag==0)               //Si flag ==0 me desplazo por el menu principal
  197.    {
  198.         if (input(pin_c3))
  199.        {   delay_ms(50);
  200.        while(input(pin_c3));
  201.        
  202.            menu++;  
  203.        if (menu>4)
  204.            menu=0;
  205.        }
  206.    }  
  207.     if(flag==1)             //si pulso C6 dentro del case 5 flag==1
  208.    {  
  209.         if (input(pin_c3)) //Si flag ==1 me desplazo por la configuracion
  210.        {   delay_ms(50);
  211.        while(input(pin_c3));
  212.        
  213.            menu++;  
  214.        if (menu>9)            
  215.            menu=0;
  216.        }    
  217.        }
  218.      
  219.    switch (menu+1)
  220.    {
  221.      case  1:cuenta_vueltas();
  222.              break;
  223.              
  224.      case  2:cuenta_horas();
  225.              break;
  226.  
  227.      case  3 :          
  228.               service=read_int16_eeprom(150);
  229.               delay_ms(15);
  230.               lcd_gotoxy(1,1);
  231.               printf(lcd_putc,"Proximo Service \nA las:  %04lu Hs     ",service);
  232.            
  233.               break;
  234.      case  4:
  235.              back_light();
  236.               break;                
  237.  
  238.      case  5 :
  239.               lcd_gotoxy(1,1);
  240.               printf(lcd_putc,"      MENU       \n   Pulse enter  ");
  241.              if (input(pin_c6))
  242.              { delay_ms(50);
  243.               while(input(pin_c6));
  244.               flag=1;
  245.               menu+=1;
  246.              }
  247.               break;
  248.              
  249.              
  250.      case  6 :
  251.               lcd_gotoxy(1,1);
  252.               printf(lcd_putc,"Programe Service \nHoras:  %04lu    ",b);
  253.              
  254.               if (input(pin_c4))    
  255.              {    delay_ms(200);       // antirebote
  256.                
  257.                     b+=1;
  258.                 if(b>9999)b=9999;      
  259.              }
  260.              if (input(pin_c5))  // Pulsador que decrementa
  261.              { delay_ms(200);
  262.              
  263.                     b-=1;
  264.                 if(b>9999)b=0 ;    
  265.              }
  266.              
  267.              if (input(pin_c6))
  268.              { delay_ms(50);
  269.               while(input(pin_c6));            
  270.                write_int16_eeprom(150, b);  
  271.                delay_ms(25);
  272.                service=read_int16_eeprom(150);
  273.                delay_ms(15);
  274.                mantenimiento=Minuto+service;//ATENCION cambiar Minuto por hora
  275.                write_int16_eeprom(160,mantenimiento);  
  276.                delay_ms(15);              
  277.                mantenimiento=read_int16_eeprom(160);
  278.                delay_ms(15);
  279.                lcd_gotoxy(1,1);
  280.                printf(lcd_putc,"Proximo Service  \nA las:  %04lu Hs    ",mantenimiento ) ;
  281.                delay_ms(2000);
  282.              }
  283.               break;
  284.              
  285.      case  7 :                               //CALIBRA RPM
  286.               e=read_float_eeprom(140);
  287.               delay_ms(15);
  288.               RPM= contador*e;
  289.               lcd_gotoxy(1,1);
  290.               printf(lcd_putc,"Actual RPM %04lu       ",RPM);
  291.               if (input(pin_c4))
  292.              {  
  293.                    delay_ms(200);                    
  294.                    ajuste+=0.02;          // Incremento
  295.              }
  296.              if (input(pin_c5))
  297.              {  
  298.                  delay_ms(200);
  299.                  ajuste-=0.02;        //Decremento  
  300.              }              
  301.              if (input(pin_c6))
  302.              { delay_ms(50);
  303.               while(input(pin_c6));            
  304.                write_float_eeprom(140, ajuste);  
  305.                delay_ms(15);  
  306.              }              
  307.               RPM= contador*ajuste;
  308.               lcd_gotoxy(1,2);
  309.               printf(lcd_putc,"Ajuste RPM %04lu       ",RPM);        
  310.               break;
  311.                
  312.      case  8 :                                
  313.               lcd_gotoxy(1,1);
  314.               printf(lcd_putc,"   RESET TOTAL    ");
  315.               lcd_gotoxy(1,2);
  316.               printf(lcd_putc,"   %05lu:%02u:%02u  ",Hora,Minuto,Segundos);
  317.               if (input(pin_c6)) // Reset de cuenta horas parcial
  318.                {  delay_ms(50);
  319.                while(input(pin_c6));
  320.                   Hora=00000;
  321.                   write_int16_eeprom(100, Hora);
  322.                   delay_ms(15);
  323.                   Minuto=00;
  324.                   write_eeprom(120, Minuto);
  325.                   delay_ms(15);
  326.               }
  327.               break;  
  328.            
  329.      case  9 :flag=0;
  330.               lcd_gotoxy(1,1);
  331.               printf(lcd_putc,"  RESET PARCIAL    ");
  332.               lcd_gotoxy(1,2);
  333.               printf(lcd_putc,"   %05lu:%02u:%02u  ",HoraParcial,MinutoParcial,Segundos);
  334.               if (input(pin_c6)) // Reset de cuenta horasparcial
  335.                {  delay_ms(50);
  336.                while(input(pin_c6));
  337.                   HoraParcial=00000;
  338.                   write_int16_eeprom(110, HoraParcial);
  339.                   delay_ms(15);              
  340.                   MinutoParcial=00;
  341.                   write_eeprom(130, MinutoParcial);
  342.                   delay_ms(15);
  343.                }
  344.               break;              
  345.                
  346.      default  :
  347.                menu=0;
  348.                break;
  349.    }        
  350.  }        
  351.     }
 
Bueno espero los comentarios .Saludos!!!!!       
Título: Re:Ayuda con lcd
Publicado por: KILLERJC en 31 de Octubre de 2015, 08:56:28
No vi demasiado el codigo, primero felicitarte por quitar tantos whiles... muchos while/do..while es un codigo normalmente es algo malo, hay excepciones. El unico lugar que usaria varios es un en RTOS por ejemplo, que tenes 1 por tarea + 1 del main.

Te respondo a tus preguntas:

Citar
  Tengo partes dentro del switch (case 6,7,8,9 ) donde configuro parametros ,aca tambien tendría que hacer funciones fuera del main y luego llamarlas en los case ? tiene algun sentido ?

Las funciones te permiten que el codigo se mas legible y no un main super extenso en el que tenes que andar buscandole el "case ..." o si modifica o no tal cosa y sea dificil de ver. Por eso puse este codigo ( lo modifique un poco):

Código: C
  1. while(1)
  2. {
  3.  
  4.    switch(x) {
  5.         case 0:
  6.                 Funcion0();  //Aca el codigo de lo que tenes dentro del while x==0
  7.                 x++;
  8.                 break;
  9.         case 1:
  10.                 Funcion1();  //Aca el codigo de lo que tenes dentro del while x==1
  11.                 x++;
  12.                 break;
  13.         case 2:
  14.                 Funcion2();  //Aca el codigo de lo que tenes dentro del while x==2
  15.                 x++;
  16.                 break;
  17.         case 3:
  18.                 Funcion3();  //Aca el codigo de lo que tenes dentro del while x==3
  19.                 x++;
  20.                 break;
  21.         case 4:
  22.                 Funcion4();  //Aca el codigo de lo que tenes dentro del while x==4
  23.                 x=1;
  24.                 break;
  25.         default:
  26.                 x=1;    //x no termino con un valor correcto, hubo un problema, entonces lo pongo en el valor inicial que corresponda
  27.                 break;
  28.      }
  29. }

Entonces cuando miras rapidamente te das cuenta que cuando el case  es 2 hace XX funcion y aumenta x para acceder al proximo. Y listo, si estas interesado en ver que hace esa funcion te vas alla. Observaras que todo lo relevante al procedimiento, es decir como avanza el programa esta alli. Sin interesarme en que hacen las funciones en si. A eso queria llegar con el switch y las funciones, lamento si no me explique bien antes.
Por supuesto esto es solo para una mejor comprension del codigo, aprender a separar pequeñas tareas, asi de esa forma se puede debuggear mejor cuando algo falla, etc, vos podes seguir como estabas haciendo pero creo que te daras cuenta que es mas simple de ver/analizar lo que puse arriba que un main Super largo con miles de cosas dentro. Ademas si por ejemplo tenes que Funcion2 escribe el LCD dado la bienvenida, y cuando lo probas justamente ESO no funciona, ya sabes que tenes que ver solamente la Funcion2 y te olvidas completamente del switch y esas cosas, el cual estaria bien programado. ¿ Se entiende a lo que voy con division de tareas ? Es mas lindo analizar / corregir una funcion de 20 lineas que una de 300 lineas.
Como esto NO es obligacion, por eso solo conteste de que si tenias un while como loop infinito nomas y no sobre esto en mi anterior respuesta.Ya que no esta mal, es solo hacerlo mas simple de ver/analizar/debuggear.

Por ahi si son muy cortas las funcioens  ( 2 o 3 lineas ) realmente no vale la pena crear una funcion para eso, y conviene ponerla en el switch, pero si son ya de 10/15 lineas por ahi es mejor separarla,

Citar
Tengo dudas en las partes en las que leo la memoria ya sea para luego imprimir en pantalla o para hacer cuentas con ese dato es necesario siempre aclarar :service=read_int16_eeprom(150);antes de usarlo( en este caso service)o con que este declarado dentro del void main() ya esta y no tengo que volver a llamarlo?

Depende... si esta declarado DENTRO del main(), entonces solo vas a poder acceder desde el main(), si llamas a una funcion esa variable no va a estar declarada.
Lo que podes hacer es:
- Si usas la variable en varias funciones, es declararla fuera del main() asi queda como "global" de esa forma todos accederian a la misma variable
- O si unicamente la usas en la funcion esa y no te importa mas, sea por que la proxima ves que lo uses vas a leer de nuevo la eeprom, o no la vas a usar, la podes declarar dentro de la funcion.
Esto es lo que se conoce como scope en C

Código: C
  1. int j;          //Variable con permanencia en la RAM, no se destruye, scope: File , cualquier funcion lo puede usar
  2.  
  3. main() {
  4.         int i=2;                //Creada al entrar al main, se destruye cuando se sale , solo accesible dentro de todo el main, Scope = Funcion
  5.         int m;
  6.         if (ax=4) {
  7.                 int i=3;        // Creado al entrar al if, no es lo mismo que la i de antes!, scope: Block ,   cuando salis del if se pierde
  8.                 i++;            // i = 4
  9.         }
  10.         funcion1();
  11.         i--;                    // i = 1
  12. }
  13.  
  14. funcion1(){
  15.         int i=9;        // Creado al entrar a funcion1, al salir de funcion1 se destruye
  16.         i++;            // i = 10
  17.         j= 10;          // j = 10
  18.         m=5;            // Error, m es una variable de main, aca no esta definida
  19. }

Espero que quede mas claro. Y responda tu pregunta.
Título: Re:Ayuda con lcd
Publicado por: KILLERJC en 31 de Octubre de 2015, 09:28:49
Te dejo esto solo para que lo veas... y por gusto, esto era a lo que me referia cuando decia que debias cambiar todo el programa para que sea mas rapido.

Ahora como estamos mas cerca de hacer algo realmente dinamico y no atrapado en delays sino como una maquina de estados, voy a darte este codigo para que lo veas ( tal ves me equivoque en algo pero es para que te des idea ). Nuevamente no es obligacion, solo para que VEAS

Código: C
  1. int estadoviejo=1,estado=0;
  2.  
  3. while(1)
  4. {
  5.  
  6.         if(grabar==1)
  7.         {
  8.                 grabo_eeprom();
  9.                 grabar = 0;
  10.         }
  11.  
  12.  
  13.         if(botones_presionados())       //Tomo resultado de botones, si observas siempre se estan leyendo, no hay delays en medio, lo maximo que tardaria es si se cambia de estado y entra en alguna funcion, lo mismo con la grabacion de la eeprom
  14.         {
  15.                 //Segun el boton presionado, pregunto el estado que esta y actuo acorde
  16.                 if(estado==2 && boton1_presionado())
  17.                 {
  18.                         estado=2;       //Habilito la muestra de variables
  19.                 }
  20.         }
  21.  
  22.  
  23.         if(estado!=estadoviejo)         //Esto hace que se ejecute solo 1 ves!
  24.         {
  25.  
  26.                 switch(estado) {
  27.                 case 0:
  28.                         Funcion0();     //Muestro en LCD Bienvenido, seteo a contador= 20
  29.                         break;
  30.                 case 1:
  31.                         Funcion1();     // Muestro en LCD el Autor, seteo contador = 10
  32.                         break;
  33.                 case 2:
  34.                         Funcion2();     // Muestra Menu
  35.                         break;
  36.                 case 3:
  37.                         Funcion3();     // Muestro estado de variables en el LCD, contador = 10
  38.                         break;
  39.                 case 4:
  40.                         Funcion4();
  41.                         break;
  42.                 default:
  43.                         estado=1;    
  44.                         break;
  45.                 estadoviejo=estado;
  46.         }
  47.      
  48.         if (contador!=0){               // Temporizador, en ves de usar un delay, estoy haciendo uso de las interrupciones del timer
  49.                 if(timer1_interrupcion_activado()) contador--;
  50.                 if (contador==0)
  51.                 {
  52.                         estado++;       // Podria haber utilizado un array con el valor inicial del estado como indice y a donde apuntar el proximo estado, ejemplo proxestado=[1,2,3,3,4], si estoy en estado 0, el proximo seria el 1 segun mi array
  53.                 }
  54.         }
  55.  
  56. }


Observa que el "delay" creado con el contador que hicimos lo unico que hace es contar interrupciones. Y no ejecuta codigo, solo cambia de "estado", los botones tambien, no ejecutan un codigo, solo cambian de estado. Lo unico que ejecuta codigo es la grabacion de la EEPROM, pero tambien podria haber ejecutado eso como un estado si quisiera. Si quisiera hacer que por ejemplo se refresque el LCD cada tanto, podria hacerlo de 2 formas.. Creando 2 switch, uno bajo el if de la diferencia de estado ( el anterior y el nuevo ) y otro sin este if, dejando el default sin nada. De esa forma uno mostraria y el otro no. O llevar el if dentro de cada case del switch. Ya que de nada sirve que escriba 100 veces "Bienvenida" al LCD. Tambien una cosa a notar es que NO se usan delays dentro de las funciones.
Título: Re:Ayuda con lcd
Publicado por: arielmdq en 31 de Octubre de 2015, 15:34:10
Hola KILLERJC ,te agradezco mucho toda  la explicacion !!!! de a poco voy entendiendo cada vez mas, estoy de acuerdo con que de esa manera es mas legible el codigo y facil de detectar errores,a medida que lo iba modificando me era mas agradable verlo .Entiendo todo lo que me explicas o casi todo ja ja ,seguramente te haré algunas preguntas con respecto al ultimo ejemplo que me mostras por que me intereso esa manera de hacerlo  .Pero antes quiero hacerme un ejemplo con eso, para asimilarlo bien  y hacer las preguntas correspondientes .Nuevamente muchisimas gracias!!!!! ya te daré noticias .
                                                                                           Saludos!!!
Título: Re:Ayuda con lcd
Publicado por: arielmdq en 03 de Noviembre de 2015, 23:56:06
Hola Killerjc , vos sabes que estuve mirando mucho el ultimo ejemplo que me pasaste pero no logro entenderlo,se que lo hiciste para darme una idea pero me complique  :D  hasta empecé a hacer un programita de ejemplo solo para aprender a usar esta manera de leer los botones y usar la interrupcion como temporizador pero estoy trabado y no lo entiendo .
A ver si te puedo ir preguntando por partes y si me puedo hacer entender :
Entiendo que creas una funcion que se llama botones_presionados();pero de que manera estaría leyendo varios botones dentro de la funcion, por ejemplo :
int botones_presionados()
{ if ( input(pin_C0))
  estado++;
}
No me doy cuenta como sería.Supongo que con estado solo te desplazas dentro del switch .Para cambiar de estado no estarías usando solo un boton por que ponerlo dentro de la funcion.
Me confunde tambien que luego creas otra funcion que se llama: boton1_presionado();que hace esta funcion ? no estarías leyendo ya en la funcion anterior cual boton se presionó
Y esta la ultima, en la ultima parte del ejemplo (y aca me recibo de " el novato del año " )  :D :D :D.No entiendo como das el tiempo con esto:
'contador' es la variable que se incrementa con cada interrupcion osea que :

if (contador!=0) //si contador es distinto de 0 es decir que si se esta incrementando
{
 if(timer1_interrupcion_activado())//Entra esta funcion pero  Que debería hacer esta funcion ?

 {             
         contador--;              // Por que decrementa contador ? En que momento entra la funcion anterior para decrementar contador ?

    if (contador==0)             // Por que se incrementa estado cunado contador es == 0 ?
      {
         estado++;              // esto se me mezcla con que 'estado' es la variable que se incrementa con los pulsadores por que ahora se                                              incrementa cuando contador es 0

Todo lo anterior a este ejemplo ,te lo entendi a la perfeccion ,pero como veras de esto no case un palo  :D  :D me interesaría aprender como se hace, pero tal vez este lejos de comprenderlo ,no lo se .Si te parece que hay otra manera en la que lo pueda entender o tal vez un ejemplo concreto soy todo ojos, y si es que esta implicito en esta explicacion ,pero soy muy cuadrado  :D . Puedo entenderlo e igualmente agradecerte por todo lo que me has ayudado  ;-) .No quiero complicarte
                                                                                                 Saludos!!!                     
     








 

 

Título: Re:Ayuda con lcd
Publicado por: KILLERJC en 04 de Noviembre de 2015, 00:10:37
El ejemplo fue bastante resumido.

El programa es simple, estaria siempre dando vueltas en el while, no ejecutaria lo del switch a no ser que exista un cambio en el estado.
Es decir el switch hace eso.

Ahora necesito algo que lo haga cambiar. En este caso tengo 2 formas.
- La primera es por tiempo, en caso que se necesite pasar un tiempo antes de mostrar otra cosa en el LCD por ejemplo, lo que hago es contar la cantidad de interrupciones de un timer, para ese tiempo, observaras que mientras el estado es el mismo ( no cambio ) el ciclo while sigue ejecutandose. Cuando llega a 0 el contador avanza al estado que sigue, en este caso para que sea mas simple solo le puse un simple estado+1.
- La segunda es por botones, esta va a depender del estado actual. Si por ejemplo estoy en el estado 5 que es un menu, y toco el boton 1 , entonces que pase al estado 9 por ejemplo, y si todo el 3 que pase al estado 10 y que lo muestre por un tiempo.

Respecto al codigo:
Código: C
  1. if (contador!=0){               // Contador se selecciona apenas entra a cada estado, esto permite dar un "tiempo"
  2.                 if(timer1_interrupcion_activado()) contador--;     // Se activo la interrupcion del timer? Supongamos timer = 0.5s , con contador = 20 serian 10 segundos ( en realidad 9.5s)
  3.                 if (contador==0)           // Si llego a 0 es por que pasaron los "10 segundos"
  4.                 {
  5.                         estado++;       // Simplificado pero paso al estado siguiente, esto va a depender del estado anterior, por simplicidad puse nomas estado++
  6.                 }
  7.         }

Si no armo un ejemplo en el cual puedas grabarlo y probarlo.
Título: Re:Ayuda con lcd
Publicado por: arielmdq en 04 de Noviembre de 2015, 08:27:44
Sigo sin entender esto : if(timer1_interrupcion_activado()) como es que  preguntas si se activó la interrupcion  :shock: ? yo entiendo que la interrupcion se activa cada vez que contador se incrementa ,no se estoy trabado che no me doy cuenta . Si  pudieras hacer un ejemplito para probarlo te agradecería .
                                                Saludos!!!
Título: Re:Ayuda con lcd
Publicado por: KILLERJC en 04 de Noviembre de 2015, 09:45:04
Escribi mal la funcion, entendela a la funcion que se activa cuando desbordo el timer1, cuando pasaron 0.5s se activa eso.
Cuando tenga un tiempo hago un ejemplito masomenos simple
Título: Re:Ayuda con lcd
Publicado por: mariacontenis en 18 de Marzo de 2020, 02:21:24
Hola a todos... Hoy modifique solo un poquito el código posteado para ponerlo sobre una lcd4x20 y se ve de maravilla.

Sin embargo quiero hacerlo como un cronometro por una necesidad propia, me gustaría que tuviera la siguiente presentación en la LCD ( 00:00 ) y así manejar un cronometro con el formato de ( mseg : seg ) pero encuentro complejo el lograrlo y por ello requiero de su ayuda y colaboración para lograrlo.

Pongo la librería NumGrand y agradezco su ayuda.

Código: C#
  1. #rom  0x2100={28,30,30,30,30,30,30,28, //  Media barra lateral derecha.==> Esta quedo como quería
  2.               7,15,15,15,15,15,15,7,  //  Media barra lateral izquierda.           ==> Esta quedo como quería
  3.               31,31,0,0,0,0,0,0,       //  Barra superior sola.                          ==> Esta quedo como quería
  4.               0,0,0,0,0,0,31,31,       //  Barra inferior sola                            
  5.               31,31,0,0,0,0,31,31,     //  Barra superior e inferior.
  6.               31,30,0,0,0,0,0,0,      //  Flecha Izquierda.
  7.               0,0,0,0,0,0,30,31,    //  Flecha Derecha.
  8.               0,0,0,0,0,0,0,0}         //  Vacio.            
  9.                          
  10. int8 Digito[4],Segmento[3],Linea;
  11. const int16 Grilla[2][10]={{120,770,740,740,130,147,147,720,140,140},
  12.                           {130,770,137,730,770,730,130,770,130,770}};
  13. //llamada CGRAM a numeros = 0 , 1 , 2 , 3 , 4 , 5 , 6 , 7 , 8 , 9
  14.  
  15. Void Desmembra (int16 Dato);
  16. Void Obtiene_Segmento (int16 Dato);
  17. Void NumGran_Init();
  18.  
  19.  
  20. Void NumGran(int16 Numero)
  21. {
  22.    int Dig;
  23.    Desmembra (Numero);
  24.    for (Linea=1;Linea<3;++Linea)
  25.    {
  26.       switch (Linea)
  27.       {
  28.          Case 1: lcd_gotoxy(4,2); for (Dig=0;Dig<4;++Dig){
  29.              Obtiene_Segmento (Grilla[0][Digito[Dig]]);
  30.              printf(LCD_PUTC,"%C%C%C",Segmento[2],Segmento[1],Segmento[0]);
  31.          } break;
  32.          Case 2: lcd_gotoxy(4,3); for (Dig=0;Dig<4;++Dig){
  33.             Obtiene_Segmento (Grilla[1][Digito[Dig]]);
  34.             printf(LCD_PUTC,"%C%C%C",Segmento[2],Segmento[1],Segmento[0]);
  35.          } break;
  36.       }
  37.    }
  38. }
  39.  
  40. Void Desmembra (int16 Dato)      //Esta funcion obtiene el valor de los
  41. {                             // digitos a enviar al display
  42.    Digito[0] = Dato/1000; Dato = Dato%1000;
  43.    Digito[1] = Dato/100;  Dato = Dato%100;
  44.    Digito[2] = Dato/10;   Dato = Dato%10;
  45.    Digito[3] = Dato;
  46. }
  47.  
  48. Void Obtiene_Segmento (int16 Dato)  //Esta funcion obtiene el valor de los
  49. {                                // segmentos a enviar al display
  50.    Segmento[2] = Dato/100;  Dato = Dato%100;
  51.    Segmento[1] = Dato/10;   Dato = Dato%10;
  52.    Segmento[0] = Dato;
  53. }
  54.  
  55. Void NumGran_Init()
  56. {
  57.    int8 posicion;
  58.    lcd_send_byte(0x00,0x40);                 // apunta al inicio de la CGRAM y
  59.    for(posicion=0;posicion<=63;++posicion)   //carga los caracteres en la CGRAM
  60.    lcd_send_byte(1,Read_eeprom(posicion));   //traidos de la EEPROM del PIC
  61. }

Bueno pues como agrego esos ( : ) entre números y mseg y seg?.
 
Título: Re:Ayuda con lcd
Publicado por: KILLERJC en 18 de Marzo de 2020, 11:34:47
Bueno la parte "importante" que es imprimir los numeros va bien...

Lo que tenes que modificar es como mostrarlo. es decir deberias enviar 2 numeros desde una columna, por ejemplo desde la 1, esos numeros te ocuparian, la columna 1 al 6.
Luego la columna 7 poner los dos puntos. El cual si es la misma libreria (y observando la foto del inicio del post) es poner un punto arriba y un punto abajo, es decir repetirlo, luego necesitarias otros 6 columnas mas para tu miliseg. En total 13 columnas ...

Esto exige Varias cosas de modificar en la libreria.... Las ennumero y espero no olvidarme de alguna:

- Limitar en las funciones la cantidad de digitos, ya que no es necesario 4, solo 2 digitos es suficiente... Esto suponiendo que no vas a utilizar lo de poner numeros mas grandes que 99, ejemplo:

Código: C
  1. Void Desmembra (int8 Dato)      
  2. {                            
  3.    if(Dato > 99 ) Dato = 99;
  4.    Digito[0] = Dato/10;
  5.    Digito[1] = Dato%10;
  6. }

- Configura el código para iniciar desde la columna/fila a eleccion, (ya que tenes un display 4x20) algo asi:

Código: C
  1. Void NumGran(int8 Numero, int8 Columna, int8 Fila)
  2. {
  3.   int Dig;
  4.   Desmembra (Numero);
  5.   for (Linea=0;Linea<2;++Linea)
  6.   {
  7.     lcd_gotoxy(Columna,Fila+Linea);
  8.     for (Dig=0;Dig<2;++Dig) {
  9.       Obtiene_Segmento (Grilla[Linea][Digito[Dig]]);
  10.       printf(LCD_PUTC,"%C%C%C",Segmento[2],Segmento[1],Segmento[0]);
  11.     }
  12.   }
  13. }
(PD: Achique el codigo porque era posible hacerlo, no tenia sentido teniendo el for repetir el codigo)

De esa forma si quisiera imprimir 52:88 deberia hacer

Código: C
  1. NumGran(52, 1, 2);
  2. // Aca la funcion para imprimir el ":"
  3. NumGran(88, 7, 2);

Esto tambien permite que puedas actualizar los mseg sin necesidad de los segundos.

- Modificar alguna de las flechas (que no vas a usar) para que queden como puntos De esa forma imprimirlos aparte.
- Crear la funcion para imprimir los puntos

Creo que eso seria todo... Por supuesto el codigo modificado NO esta probado y puede haber errores, ya que no lo probé, ni compile, simplemente lo modifique.
El resto queda en tus manos.
Título: Re:Ayuda con lcd
Publicado por: mariacontenis en 19 de Marzo de 2020, 04:18:35
Mil Gracias KILLERJC por tu ayuda.

Intento el código así como me dices..

Código: C#
  1. #rom  0x2100={28,30,30,30,30,30,30,28, //  Media barra lateral derecha.==> Esta quedo como quería
  2.               7,15,15,15,15,15,15,7,  //  Media barra lateral izquierda.           ==> Esta quedo como quería
  3.               31,31,0,0,0,0,0,0,       //  Barra superior sola.                          ==> Esta quedo como quería
  4.               0,0,0,0,0,0,31,31,       //  Barra inferior sola                            
  5.               31,31,0,0,0,0,31,31,     //  Barra superior e inferior.
  6.               31,30,0,0,0,0,0,0,      //  Flecha Izquierda.
  7.               0,0,0,0,0,0,30,31,    //  Flecha Derecha.
  8.               0,0,0,0,0,0,0,0}         //  Vacio.            
  9.                          
  10. int8 Digito[4],Segmento[3],Linea;
  11. const int16 Grilla[2][10]={{120,770,740,740,130,147,147,720,140,140},
  12.                            {130,770,137,730,770,730,130,770,130,770}};
  13. //llamada CGRAM a numeros = 0 , 1 , 2 , 3 , 4 , 5 , 6 , 7 , 8 , 9
  14.  
  15. Void NumGran(int16 Numero, int16 Columna, int16 Fila);
  16. Void Desmembra (int16 Dato);
  17. Void Obtiene_Segmento (int16 Dato);
  18. Void NumGran_Init();
  19.  
  20.  
  21. Void NumGran(int16 Numero, int16 Columna, int16 Fila)
  22. {
  23.   int Dig;
  24.   Desmembra (Numero);
  25.   for (Linea=0;Linea<2;++Linea)
  26.   {
  27.     lcd_gotoxy(Columna,Fila+Linea);
  28.     for (Dig=0;Dig<2;++Dig) {
  29.       Obtiene_Segmento (Grilla[Linea][Digito[Dig]]);
  30.       printf(LCD_PUTC,"%C%C%C",Segmento[2],Segmento[1],Segmento[0]);
  31.     }
  32.   }
  33. }
  34.  
  35. Void Desmembra (int16 Dato)      
  36. {                            
  37.    if(Dato > 99 ) Dato = 99;
  38.    Digito[0] = Dato/10;
  39.    Digito[1] = Dato%10;
  40. }
  41.  
  42. Void Obtiene_Segmento (int16 Dato)  //Esta funcion obtiene el valor de los
  43. {                                // segmentos a enviar al display
  44.    Segmento[2] = Dato/100;  Dato = Dato%100;
  45.    Segmento[1] = Dato/10;   Dato = Dato%10;
  46.    Segmento[0] = Dato;
  47. }
  48.  
  49. Void NumGran_Init()
  50. {
  51.    int8 posicion;
  52.    lcd_send_byte(0x00,0x40);                 // apunta al inicio de la CGRAM y
  53.    for(posicion=0;posicion<=63;++posicion)   //carga los caracteres en la CGRAM
  54.    lcd_send_byte(1,Read_eeprom(posicion));   //traidos de la EEPROM del PIC
  55. }

Dentro del While principal tengo esto:

Código: C#
  1. lcd_send_byte(0,1); delay_us(2);  //limpiar LCD - Necesario si
  2.          NumGran(Numero, 1, 3);
  3.          NumGran(Numero, 7, 3);
  4.          printf(lcd_putc,"%04lu",Numero);

Y los resultados son como los de la imagen en captura de pantalla, es decir, los (Seg : mSeg) corren al mismo tiempo los dos desde cero hasta 99.

Lo que realmente pretendo es al termino de los 99 mSeg inicien los segundos.

Algo asi: if(mSeg>99){ mSeg=0; Seg++}

Para que de esta manera se pueda hacer un cronometro.

Título: Re:Ayuda con lcd
Publicado por: KILLERJC en 19 de Marzo de 2020, 09:02:09
Citar
corren al mismo tiempo los dos desde cero hasta 99.

y es obvio... ya que estas enviando siempre el mismo numero:
Código: C
  1. NumGran(Numero, 1, 3);
  2.          NumGran(Numero, 7, 3);

Fuera asi:

Código: C
  1. NumGran(Msegundos, 1, 3);
  2.          NumGran(Segundos, 7, 3);

Es otra cosa...

Ademas pretender que valla del 00 a 99 y lo puedas ver es otra cosa que no va a suceder, ya que los tiempos para manejar el LCD seguramente superen algunos milisegundos.
Título: Re:Ayuda con lcd
Publicado por: mariacontenis en 19 de Marzo de 2020, 10:48:04
Gracias KILLERJC

É pensado realizar el incremento de Msegundos, Segundos con el tmr1. Sólo que primero requiero tener el cronometeo y después meterlo a tiempo.

Citar
         NumGran(Msegundos, 1, 3);
         NumGran(Segundos, 7, 3);


Entiendo ahora lo del por que  orden igual.

Entonces necesito agregar variables a las funciones que hiciste.

 (((:-)))
Título: Re:Ayuda con lcd
Publicado por: KILLERJC en 19 de Marzo de 2020, 11:08:47
Citar
Entonces necesito agregar variables a las funciones que hiciste.

A las funcioens que hice no.... Las funciones estan unicamente para "mostrar" (enviar al LCD) un numero, lo unico que se modifico es para que en ves de mostrar 4 por ves, se muestre 2 digitos como maximo. Lo que si vos necesitas crear 2 variables afuera... una para los milisegundos y otro para los segundos... Y que terminara siendo mas simple para vos manejarlo asi..
Título: Re:Ayuda con lcd
Publicado por: mariacontenis en 19 de Marzo de 2020, 23:25:38
Toda tu ayuda me a sido de aprendizaje KILLERJC.

Ahora solo falta poner los dos puntos " : ". ¡¡ Me alegra que todo va sobre ruedas !!.

Ahora tratare con esos dos puntos, sabes como realizar esa función amigo KILLERJC...  :mrgreen:
Título: Re:Ayuda con lcd
Publicado por: KILLERJC en 20 de Marzo de 2020, 07:48:56
De mi anterior post:

Citar
- Modificar alguna de las flechas (que no vas a usar) para que queden como puntos De esa forma imprimirlos aparte.
- Crear la funcion para imprimir los puntos

La funcion es muy simple.. Posiciono el LCD, en la columa y fila que quiero y luego imprimo el caracter:

Código: C
  1. void ImprimirPuntos ( int8 Columna, int8 Fila) {
  2.     lcd_gotoxy(Columna,Fila);
  3.     printf(LCD_PUTC,"%C",Punto)
  4.     lcd_gotoxy(Columna,Fila+1);
  5.     printf(LCD_PUTC,"%C",Punto);
  6. }

Donde Punto es 6 o 7,,, dependen de donde hagas tu punto, 6 si lo haces sobre Flecha izquierda, y 7 si lo haces con flecha derecha... tenes que modificar uno de estos:
Código: C
  1. 31,30,0,0,0,0,0,0,      //  Flecha Izquierda.
  2.               0,0,0,0,0,0,30,31,    //  Flecha Derecha.

Vuelvo a decirtelo, esto te lo dejo a vos.. que investigues como se hace. Y te dejo una ayuda:

(https://os.mbed.com/media/uploads/ncalzadat/lcd_16x2_caracteres_cgram.jpg)
Título: Re:Ayuda con lcd
Publicado por: mariacontenis en 21 de Marzo de 2020, 04:59:55
Listo KILLERJC!!. Para los puntos quedaron así...

Código: C#
  1. 128,128,128,142,142,142,128,128,                                  // Punto

Mil gracias por tu ayuda!!!  :-/ :mrgreen: