Autor Tema: Conflicto entre LCD 16x2 y 3 dispaly 7 seg multiplexados  (Leído 1899 veces)

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

Desconectado cristianpalta1

  • PIC10
  • *
  • Mensajes: 5
Conflicto entre LCD 16x2 y 3 dispaly 7 seg multiplexados
« en: 05 de Marzo de 2016, 02:17:39 »
Muy buenas noches soy nuevo en el foto y tengo un problema con una lcd y 3 7 segmentos catodo comun multiplexados, el problema esta en los delay ya que con el delay de la lcd mis 3 7 segmentos se vuelven mas lentos y si le quito ese delay la lcd no imprimi 100 % bien y la necesito asi. Mi otra alternativa fue una interrupcion interna por Rb0 me funciona pero las variables que necesito que cambien ya no lo hacen y solo recibe solo una y no las 3 ya que es una comunicacion serial por rs232. Ajunto codigo cualquier ayuda seria excelente. Muchas gracias
CODIGO:
#include <16f877a.h>
#device adc = 8 //Valor de la lectura en bit puede ser int y llega hasta int16
#fuses HS, NOPROTECT,NOWDT //HS crystal de 20M

#use delay (clock = 20M)
#use rs232(baud=9600, xmit=pin_c6, rcv=pin_c7)

#define LCD_RS    PIN_B1
#define LCD_E     PIN_B2 //Inicializo mi LCD
#define LCD_DB4   PIN_B4
#define LCD_DB5   PIN_B5
#define LCD_DB6   PIN_B6
#define LCD_DB7   PIN_B7

#include <lcd1.c>
#include <math.h>

#use standard_io(C)
#use standard_io(D)
#use standard_io(B)

float Fotoc, Lm35, Pot,P,x1,x2,x3,F,T;
char dato;
int8 num1,num2,num3;
int16 h=0;

int8 sacaNumero(int8 numero)
{
   int8 valores[] = {
   0b10111111, // 0
   0b10000110, // 1
   0b11011011, // 2
   0b11001111, // 3
   0b11100110, // 4
   0b11101101, // 5
   0b11111100, // 6
   0b10000111, // 7   //Funcion en binario para mostrar los numeros en el 7segmentos
   0b11111111, // 8
   0b11101111, // 9
   };
   return valores[numero];
}

#int_RDA
void int_serie()
{
    dato = getc();
    if(dato == 'F') Fotoc = getc();
    else if(dato == 'T' ) Lm35=getc();
    else if(dato == 'P')  Pot=getc();
}

#INT_EXT
void int_cambio()
{
   h=0;
   do
   {
   h++;
   output_d(0);
   F =  (5 * Fotoc) / 255; //conversion voltaje
   T=Lm35*1.960784314; //conveersion temperatura
   printf(lcd_putc, "\fFotocel: %f V  \nLm35: %f  'C",F,T);
   delay_ms(200);
  output_high(pin_a0);
  delay_ms(200);
  output_low(pin_a0);
  delay_ms(300);
   }while(h<200);
}

void main()
{
  port_b_pullups(true);
  enable_interrupts(INT_RDA); //Habilito la interrupcion de la funcion
  enable_interrupts(int_ext); //indica que la interrupción es externa
  ext_int_edge(L_to_H);
  enable_interrupts(GLOBAL);//Habilito interrupción USART
 
  lcd_init();
  set_tris_D(0x00);
 
  while(TRUE)

{   
   printf(lcd_putc,"\f");
   printf(lcd_putc,"Variacion Potenciometro");
   P = ((5 * Pot) / 255);
   num1=P;
   x1=P-num1;
   x2=x1*10;
   num2=x2;
   x3=x2-num2;
   num3=x3*10;
   
   output_low(PIN_C0);
   output_low(PIN_C2);
   output_high(PIN_C1);
   output_d(sacaNumero(num2));
   delay_ms(5);
 
       
   output_low(PIN_C0);
   output_low(PIN_C1);
   output_high(PIN_C2);
   output_d(sacaNumero(num3));
   delay_ms(5);
   
   output_low(PIN_C1);  //De aqui hacia abajo con mutacion de los transistores
   output_low(PIN_C2);
   output_high(PIN_C0);
   output_d(sacaNumero(num1));
   delay_ms(5);

   }
}

Desconectado KILLERJC

  • Colaborador
  • DsPIC33
  • *****
  • Mensajes: 8242
Re:Conflicto entre LCD 16x2 y 3 dispaly 7 seg multiplexados
« Respuesta #1 en: 05 de Marzo de 2016, 04:20:09 »
3 cosas sin meterme en el codigo:

1-
Código: C
  1. #int_RDA
  2. void int_serie()
  3. {
  4.     dato = getc();
  5.     if(dato == 'F') Fotoc = getc();
  6.     else if(dato == 'T' ) Lm35=getc();
  7.     else if(dato == 'P')  Pot=getc();
  8. }

Muchos getc(), deberias tener unicamente 1 solo. Vos tenes que pensar que cada ves que entra alli es por que llego un caracter, asi como lo tenes entraria y luego se quedaria esperando que llegue otro caracter DENTRO de la interrupcion (por que existe la posibilidad de que se ejecuten 2 getc() ), rompiendo toda la ventaja de usar la interrupcion.

Citar
This function waits for a character to come in over the RS232 RCV pin and returns the character.

2-

El multiplexado del display se ve cortado por el LCD. Entonces lo mejor es que crees una interrupcion con un Timer de 5ms, y cada ves que entra cambias el anodo y cambias el dato a mostrar. Es decir en ves de usar delays lo haces por interrupcion.

3-

Jamas de los JAMAS metas un delay dentro de una interrupcion, o uses el LCD, o tengas un while/do..while adentro de una interrupcion:

Código: C
  1. #INT_EXT
  2. void int_cambio()
  3. {
  4.    h=0;
  5.    do
  6.    {
  7.    h++;
  8.    output_d(0);
  9.    F =  (5 * Fotoc) / 255; //conversion voltaje
  10.    T=Lm35*1.960784314; //conveersion temperatura
  11.    printf(lcd_putc, "\fFotocel: %f V  \nLm35: %f  'C",F,T);
  12.    delay_ms(200);
  13.   output_high(pin_a0);
  14.   delay_ms(200);
  15.   output_low(pin_a0);
  16.   delay_ms(300);
  17.    }while(h<200);
  18. }

Recorda una cosa, la interrupcion debe ser lo mas rapido posible. Ya que si entra a esa interrupcion, y se queda esperando ahi por los delays, no te van a funcionar las demas interrupciones ( UART,Timer, etc ) ya que no se vuelven a activar hasta que salga.

En fin, eso lo deberias sacar SI o SI de alli.

Desconectado cristianpalta1

  • PIC10
  • *
  • Mensajes: 5
Re:Conflicto entre LCD 16x2 y 3 dispaly 7 seg multiplexados
« Respuesta #2 en: 05 de Marzo de 2016, 11:15:19 »
Gracias por la información de las interrupciones ya las omiti al hacer esos procesos, ahora entonces mi duda es killer me dices que hacer una interrupcion de timer implemente el timer0 pero dices que cambiar el anodo como podria si mis 7seg son catodo comun. Y por otra hay otra forma de ejecutar dos acciones en ciclos infinitos por separado para que me siga leyendo y convitiendo los valores analogos a digitales ?

Desconectado KILLERJC

  • Colaborador
  • DsPIC33
  • *****
  • Mensajes: 8242
Re:Conflicto entre LCD 16x2 y 3 dispaly 7 seg multiplexados
« Respuesta #3 en: 05 de Marzo de 2016, 12:35:43 »
Todo lo que tenes es la interrupcion externa lo pasas al while principal. Y sobre los displays puede ser anodo/catodo, no importa es simplemente lo mismo.

Desconectado cristianpalta1

  • PIC10
  • *
  • Mensajes: 5
Re:Conflicto entre LCD 16x2 y 3 dispaly 7 seg multiplexados
« Respuesta #4 en: 05 de Marzo de 2016, 15:43:37 »
De que forma podria separar esas 2 sentencias para hacerlas dentro del while(true) pero que se hagan tambien infinitamente tanto la una como la otra ? Estoy aprendiendo micro y he buscado muchas cosas para arreglar ese problema pero aun no lo logro hacer ya quite la int. externa como lo dijiste

Desconectado KILLERJC

  • Colaborador
  • DsPIC33
  • *****
  • Mensajes: 8242
Re:Conflicto entre LCD 16x2 y 3 dispaly 7 seg multiplexados
« Respuesta #5 en: 05 de Marzo de 2016, 16:33:06 »
Código: C
  1. #include <16f877a.h>
  2. #device adc = 8 //Valor de la lectura en bit puede ser int y llega hasta int16
  3. #fuses HS, NOPROTECT,NOWDT //HS crystal de 20M
  4.  
  5. #use delay (clock = 20M)
  6. #use rs232(baud=9600, xmit=pin_c6, rcv=pin_c7)
  7.  
  8. #define LCD_RS    PIN_B1
  9. #define LCD_E     PIN_B2 //Inicializo mi LCD
  10. #define LCD_DB4   PIN_B4
  11. #define LCD_DB5   PIN_B5
  12. #define LCD_DB6   PIN_B6
  13. #define LCD_DB7   PIN_B7
  14.  
  15. #include <lcd1.c>
  16. #include <math.h>
  17.  
  18. #use standard_io(C)
  19. #use standard_io(D)
  20. #use standard_io(B)
  21.  
  22. float Fotoc, Lm35, Pot,P,x1,x2,x3,F,T;
  23. char dato;
  24. int8 num1,num2,num3;
  25. int16 h=0;
  26.  
  27. enum Estado {
  28.         LETRA,
  29.         DATO_FOTO,
  30.         DATO_LM35,
  31.         DATO_POT
  32. };
  33.  
  34. enum Displaynum {
  35.         UNIDADES,
  36.         DECENAS,
  37.         CENTENAS
  38. };
  39.  
  40. enum Estado EstadoUART = LETRA;
  41. enum Displaynum display = UNIDADES;
  42.  
  43. int8 BCDto7seg[10] = {
  44.    0b10111111, // 0
  45.    0b10000110, // 1
  46.    0b11011011, // 2
  47.    0b11001111, // 3
  48.    0b11100110, // 4
  49.    0b11101101, // 5
  50.    0b11111100, // 6
  51.    0b10000111, // 7   //Funcion en binario para mostrar los numeros en el 7segmentos
  52.    0b11111111, // 8
  53.    0b11101111, // 9
  54.    };
  55.  
  56.  
  57. #int_RDA
  58. void int_serie()
  59. {
  60.         dato = getc();
  61.         switch(EstadoUART)
  62.         {
  63.         case LETRA:
  64.                 if(dato == 'F') EstadoUART = DATO_FOTO;
  65.                 else if(dato == 'T' ) EstadoUART = DATO_LM35;
  66.                 else if(dato == 'P')  EstadoUART = DATO_POT;
  67.                 break;
  68.         case DATO_FOTO:
  69.                 Fotoc = dato;
  70.                 EstadoUART = LETRA;
  71.                 break;
  72.         case DATO_LM35:
  73.                 Lm35 = dato;
  74.                 EstadoUART = LETRA;
  75.                 break;
  76.         case DATO_POT:
  77.                 Pot = dato;
  78.                 EstadoUART = LETRA;
  79.                 break;
  80.         }
  81. }
  82.  
  83. #INT_TMR
  84. void int_timer(void)
  85. {
  86.         switch(displaynum)
  87.         {
  88.         case UNIDADES:
  89.                 output_low(PIN_C1);
  90.                 output_low(PIN_C2);
  91.                 output_high(PIN_C0);
  92.                 output_d(BCDto7seg[num1]);
  93.                 break;
  94.         case DECENAS:
  95.                 output_low(PIN_C0);
  96.                 output_low(PIN_C2);
  97.                 output_high(PIN_C1);
  98.                 output_d(BCDto7seg[num2]);
  99.                 break;
  100.         case CENTENAS:
  101.                 output_low(PIN_C1);
  102.                 output_low(PIN_C0);
  103.                 output_high(PIN_C2);
  104.                 output_d(BCDto7seg[num3]);
  105.                 break;
  106.         }
  107. }
  108.  
  109. void main(void)
  110. {
  111.         port_b_pullups(true);
  112.         enable_interrupts(INT_RDA); //Habilito la interrupcion de la funcion
  113.         ext_int_edge(L_to_H);
  114.         enable_interrupts(GLOBAL);//Habilito interrupción USART
  115.  
  116.         lcd_init();
  117.         set_tris_D(0x00);
  118.  
  119.         while(TRUE)
  120.         {  
  121.                 printf(lcd_putc,"\f");
  122.                 printf(lcd_putc,"Variacion Potenciometro");
  123.                 P = ((5 * Pot) / 255);
  124.                 num1=P;
  125.                 x1=P-num1;
  126.                 x2=x1*10;
  127.                 num2=x2;
  128.                 x3=x2-num2;
  129.                 num3=x3*10;
  130.  
  131.                 delay_ms(1000);
  132.  
  133.                 F =  (5 * Fotoc) / 255; //conversion voltaje
  134.                 T=Lm35*1.960784314; //conveersion temperatura
  135.                 printf(lcd_putc, "\fFotocel: %f V  \nLm35: %f  'C",F,T);
  136.  
  137.                 delay_ms(200);
  138.                 output_high(pin_a0);
  139.                 delay_ms(200);
  140.                 output_low(pin_a0);
  141.                 delay_ms(300);
  142.         }
  143. }

Por favor toma este codigo con pinzas, no todo es correcto ni siquiera va a funcionar como vos queres, yo solo cambie algunas cosas para que funcionaran y me faltaron varias cosas mas como la configuracin de los timers etc. Pero ahi tenes masomenos una idea de lo que te decia, lo hice solamente para que lo veas y entiendas a que me refiero.

Creo que tanto la interrupcion del timer como la de la UART , me refiero al codigo dentro es correcto a lo que intentabas hacer vos.
Y por ultima ves repito, Este codigo NO VA a funcionar si es que no ves que tiene de malo o que le falta. Pero es un buen comienzo para que lo veas.


 

anything