Autor Tema: Ayuda con lcd  (Leído 23601 veces)

0 Usuarios y 1 Visitante están viendo este tema.

Desconectado arielmdq

  • PIC16
  • ***
  • Mensajes: 166
Re:Ayuda con lcd
« Respuesta #60 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 !!! 
El tiempo es una ilusión ,solo existe el presente................

Desconectado KILLERJC

  • Colaborador
  • DsPIC33
  • *****
  • Mensajes: 8242
Re:Ayuda con lcd
« Respuesta #61 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

Desconectado arielmdq

  • PIC16
  • ***
  • Mensajes: 166
Re:Ayuda con lcd
« Respuesta #62 en: 28 de Octubre de 2015, 09:25:31 »
Aaa ok te entiendo
El tiempo es una ilusión ,solo existe el presente................

Desconectado arielmdq

  • PIC16
  • ***
  • Mensajes: 166
Re:Ayuda con lcd
« Respuesta #63 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!!!!!       
El tiempo es una ilusión ,solo existe el presente................

Desconectado KILLERJC

  • Colaborador
  • DsPIC33
  • *****
  • Mensajes: 8242
Re:Ayuda con lcd
« Respuesta #64 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.
« Última modificación: 31 de Octubre de 2015, 09:12:04 por KILLERJC »

Desconectado KILLERJC

  • Colaborador
  • DsPIC33
  • *****
  • Mensajes: 8242
Re:Ayuda con lcd
« Respuesta #65 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.
« Última modificación: 31 de Octubre de 2015, 09:35:11 por KILLERJC »

Desconectado arielmdq

  • PIC16
  • ***
  • Mensajes: 166
Re:Ayuda con lcd
« Respuesta #66 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!!!
El tiempo es una ilusión ,solo existe el presente................

Desconectado arielmdq

  • PIC16
  • ***
  • Mensajes: 166
Re:Ayuda con lcd
« Respuesta #67 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!!!                     
     








 

 

El tiempo es una ilusión ,solo existe el presente................

Desconectado KILLERJC

  • Colaborador
  • DsPIC33
  • *****
  • Mensajes: 8242
Re:Ayuda con lcd
« Respuesta #68 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.

Desconectado arielmdq

  • PIC16
  • ***
  • Mensajes: 166
Re:Ayuda con lcd
« Respuesta #69 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!!!
El tiempo es una ilusión ,solo existe el presente................

Desconectado KILLERJC

  • Colaborador
  • DsPIC33
  • *****
  • Mensajes: 8242
Re:Ayuda con lcd
« Respuesta #70 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
« Última modificación: 04 de Noviembre de 2015, 10:32:10 por KILLERJC »

Desconectado mariacontenis

  • PIC16
  • ***
  • Mensajes: 116
Re:Ayuda con lcd
« Respuesta #71 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?.
 
« Última modificación: 18 de Marzo de 2020, 02:27:04 por mariacontenis »

Desconectado KILLERJC

  • Colaborador
  • DsPIC33
  • *****
  • Mensajes: 8242
Re:Ayuda con lcd
« Respuesta #72 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.
« Última modificación: 18 de Marzo de 2020, 11:38:13 por KILLERJC »

Desconectado mariacontenis

  • PIC16
  • ***
  • Mensajes: 116
Re:Ayuda con lcd
« Respuesta #73 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.

« Última modificación: 19 de Marzo de 2020, 04:25:43 por mariacontenis »

Desconectado KILLERJC

  • Colaborador
  • DsPIC33
  • *****
  • Mensajes: 8242
Re:Ayuda con lcd
« Respuesta #74 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.