TODOPIC

Simuladores, editores de PCB, etc => Simuladores de circuitos => Proteus ISIS => Mensaje iniciado por: PalitroqueZ en 14 de Mayo de 2008, 15:22:22

Título: Teclado matricial Flex 4x4 interrupción RB[7-4] + antirebote int_timer0
Publicado por: PalitroqueZ en 14 de Mayo de 2008, 15:22:22
El hilo surgió del ejemplo que montó pocher en:

Ejemplito 16F876A: Rastreando un Teclado Matricial 4x4 y enviando a la RS232 (http://www.todopic.com.ar/foros/index.php?topic=4807.msg63381#msg63381)

tomé ese ejemplo y con varias modificaciones y adaptaciones lo puse a funcionar tal como reza el titulo.

Teclado_flex_change_portb.C

Código: C
  1. /* Teclado4.c  - Conexiones del teclado.
  2.  
  3.    He realizado unas modificaciones en Teclado3.c (así se llamaba el original)
  4.    para optimizar los recursos del uC PIC
  5.    Entre ellos tenemos:
  6.      - todas las variables concernientes a la identificación del teclado,
  7.        se han llevado a constantes (para desocupar RAM)
  8.      - dichas constantes corresponden a la combinación generada por los valores
  9.        que los pines del teclado deben tener, con ello si queremos identificar
  10.        la tecla en otra parte del programa, solo tenemos que localizar la
  11.        etiqueta de constante correspondiente.
  12.      - una vez que se valida un condicional sale inmediatamente de kbd_getc()
  13.        evitando la demora de preguntar por los otros condicionales y por
  14.        consiguiente sale mas pronto de la interrupción.
  15.  
  16.    Autor: Pocher
  17.    Modificación: PalitroqueZ  14-May-2008 11:10am
  18.    
  19.    Este código puede usarse libremente siempre que se mantenga/n y/o respete/n
  20.    el/los credito/s de/los autor/es
  21. *******************************************************************************
  22.  
  23.                  iColumna2
  24.          iColumna0   ^
  25.              ^       |
  26.              |       |
  27.            |---|---|---|---|
  28.   RB4 ---> | 1 | 2 | 3 | A |
  29.            |---|---|---|---|
  30.   RB5 ---> | 4 | 5 | 6 | B |
  31.            |---|---|---|---|
  32.   RB6 ---> | 7 | 8 | 9 | C |
  33.            |---|---|---|---|
  34.   RB7 ---> | * | 0 | # | D |
  35.            |---|---|---|---|
  36.                  ^       ^
  37.                  |       |
  38.                       iColumna3
  39.              iColumna1
  40.  
  41.                  
  42. RB4 = fila0
  43. RB5 = fila1
  44. RB6 = fila2
  45. RB7 = fila3
  46.  
  47. */
  48.  
  49.  
  50. int8 const iLos_Cuatro_MSB_PORTB=0b11110000; // selecciona los 4 MSB
  51. int8 iPuerto_compuesto;
  52.  
  53. //*****************************************************
  54.    
  55.  
  56. int8 const iTecla1=0B11101110; // 0xEE
  57. int8 const iTecla4=0B11011110; // 0xDE
  58. int8 const iTecla7=0B10111110; // 0xBE
  59. int8 const iTeclaAsterisco=0B01111110; // 0x7E
  60.  
  61. int8 const iTecla2=0B11101101; // 0xED
  62. int8 const iTecla5=0B11011101; // 0xDD
  63. int8 const iTecla8=0B10111101; // 0xBD
  64. int8 const iTecla0=0B01111101; // 0x7D
  65.  
  66. int8 const iTecla3=0B11101011; // 0xEB
  67. int8 const iTecla6=0B11011011; // 0xDB
  68. int8 const iTecla9=0B10111011; // 0xBB
  69. int8 const iTeclaNumeral=0B01111011; // 0x7B
  70.  
  71. int8 const iTeclaA=0B11100111; // 0xE7
  72. int8 const iTeclaB=0B11010111; // 0xD7
  73. int8 const iTeclaC=0B10110111; // 0xB7
  74. int8 const iTeclaD=0B01110111; // 0x77
  75.  
  76. //***********************************************************
  77. void  Configurar_iPuerto_compuesto(void);
  78. //***********************************************************
  79. int8 kbd_getc(){
  80.    int8 tecla;
  81.    
  82.      output_low(iColumna0);
  83.      output_high(iColumna1);
  84.      output_high(iColumna2);
  85.      output_high(iColumna3);
  86.      Configurar_iPuerto_compuesto();
  87.      if(iPuerto_compuesto == iTecla1 ){tecla=iTecla1; return tecla;}
  88.      if(iPuerto_compuesto == iTecla4 ){tecla=iTecla4; return tecla;}
  89.      if(iPuerto_compuesto == iTecla7 ){tecla=iTecla7; return tecla;}
  90.      if(iPuerto_compuesto == iTeclaAsterisco ){tecla=iTeclaAsterisco;  return tecla;}
  91.      
  92.      output_high(iColumna0);
  93.      output_low(iColumna1);
  94.      output_high(iColumna2);
  95.      output_high(iColumna3);
  96.      
  97.      Configurar_iPuerto_compuesto();
  98.      if(iPuerto_compuesto == iTecla2 ){tecla=iTecla2; return tecla;}
  99.      if(iPuerto_compuesto == iTecla5 ){tecla=iTecla5; return tecla;}
  100.      if(iPuerto_compuesto == iTecla8 ){tecla=iTecla8; return tecla;}
  101.      if(iPuerto_compuesto == iTecla0 ){tecla=iTecla0; return tecla;}
  102.  
  103.      output_high(iColumna0);
  104.      output_high(iColumna1);;
  105.      output_low(iColumna2);
  106.      output_high(iColumna3);
  107.      
  108.      Configurar_iPuerto_compuesto();
  109.      if(iPuerto_compuesto == iTecla3 ){tecla=iTecla3; return tecla;}
  110.      if(iPuerto_compuesto == iTecla6 ){tecla=iTecla6; return tecla;}
  111.      if(iPuerto_compuesto == iTecla9 ){tecla=iTecla9; return tecla;}
  112.      if(iPuerto_compuesto == iTeclaNumeral ){tecla=iTeclaNumeral; return tecla;}
  113.      
  114.      output_high(iColumna0);
  115.      output_high(iColumna1);
  116.      output_high(iColumna2);
  117.      output_low(iColumna3);
  118.      
  119.      Configurar_iPuerto_compuesto();
  120.      if(iPuerto_compuesto == iTeclaA ){tecla=iTeclaA; return tecla;}
  121.      if(iPuerto_compuesto == iTeclaB ){tecla=iTeclaB; return tecla;}
  122.      if(iPuerto_compuesto == iTeclaC ){tecla=iTeclaC; return tecla;}
  123.      if(iPuerto_compuesto == iTeclaD ){tecla=iTeclaD; return tecla;}
  124. }
  125.  
  126. //**************************************************************
  127. // Aquí se agrupa los bits concerniente a las columnas 1-4 junto
  128. // con RB[7-4] en un solo registro para manejarlo a posteriori
  129. // iPuerto_compuesto = [RB7,RB6,RB5,RB4,columna3,columna2,columna1,columna0]
  130. //**************************************************************
  131. void  Configurar_iPuerto_compuesto(void){
  132.    iPuerto_compuesto=0;
  133.    iPuerto_compuesto = input_b() & iLos_Cuatro_MSB_PORTB;
  134.    iPuerto_compuesto |= (input_state(iColumna3) << 3);
  135.    iPuerto_compuesto |= (input_state(iColumna2) << 2);
  136.    iPuerto_compuesto |= (input_state(iColumna1) << 1);
  137.    iPuerto_compuesto |= input_state(iColumna0);
  138.    
  139. }
  140. //********************************************************************
  141. // iColumna[3-0]=0
  142. //********************************************************************
  143. void Limpiar_Columnas(void){
  144.    output_low(iColumna0);
  145.    output_low(iColumna1);
  146.    output_low(iColumna2);
  147.    output_low(iColumna3);
  148. }


programa ejemplo particular
Código: C
  1. /* v1.0
  2.    Programa ejemplo que hace uso del teclado matricial
  3.    4x4 mediante interrupciones y liberando 4 pines del portb,
  4.    haciendo posible cambiarlas por cualquier pin del uC PIC.
  5.    Los 4 pines liberados corresponden a las columnas que maneja el teclado
  6.    
  7.    Caracteristicas:
  8.    - Cambio de estado en los pines RB[7-4]
  9.    - Retardo antirrebotes por Timer0
  10.    
  11.    con la interrupción por cambio en PORTB, se gestiona el teclado sin tener
  12.    que encerrar todo el programa principal en un bucle.
  13.    
  14.    la interrupción del timer0 sirve para crear un retardo antirrebotes SIN
  15.    hacer demorar la ejecución del programa principal.
  16.    
  17.    el próposito de ambas interrupciones es detectar la pulsación de una
  18.    tecla y garantizar que no sea un falso contacto todo ello sin "detener"
  19.    el bucle principal.
  20.    
  21.    solo se gestionará el proceso correspondiente cuando se pulsa la tecla
  22.    (está validado para no responder a soltar la tecla o mantenerla
  23.     indefinidamente).
  24.    si quiere ejecutar el proceso asociado a la tecla nuevamente, basta pulsar
  25.    otra vez dicha tecla.
  26.  
  27.  
  28.    Autor: Pocher
  29.    Modificación: PalitroqueZ  14-May-2008 11:10am
  30.    
  31.    Este código puede usarse libremente siempre que se mantenga/n y/o respete/n
  32.    el/los credito/s de/los autor/es
  33.  
  34. */
  35.  
  36. #include <18F4550.h>
  37. #fuses XTPLL,NOMCLR,NOWDT,NOPROTECT,
  38. #fuses NOLVP,NODEBUG,NOPBADEN,USBDIV,PLL1
  39. #fuses CPUDIV1,NOVREGEN,NOIESO // IESO bit ignorado
  40. #use delay(clock=48M)
  41.  
  42. #use rs232(baud=9600, xmit=PIN_C6, rcv=PIN_C7) // opcional
  43.  
  44. #use fast_io(A)   // opcional
  45. #use fast_io(B)   //    "
  46. #use fast_io(C)   //    "
  47. #use fast_io(D)   //    "
  48. #use fast_io(E)   //    "
  49.  
  50. #byte PORTB=0xF81
  51. // declarar la dirección del portb
  52.  
  53. //*********************************
  54. // variables globales
  55. //*********************************
  56.  
  57. int8 const iVeces_iContador_1ms=30;
  58. int8 iFlanco_RB=0;  // bandera que detecta el primer flanco del pulsador
  59. int8 iContador_1ms=0;  // con Fcpu=48MHz, el timer0 cuenta máximo ~ 5ms
  60. int8 iTecla_capturada=0;
  61. int1 fImprimir=0;  // Bandera ejemplo para imprimir tecla presionada
  62.  
  63. #define iColumna0   PIN_D7
  64. #define iColumna1   PIN_C2
  65. #define iColumna2   PIN_A0
  66. #define iColumna3   PIN_D0
  67.  
  68. //*********************************
  69. // archivos a incluir
  70. //*********************************
  71. #include "Teclado_flex_change_portb.C"
  72. //----------------------------------------------------
  73. #int_timer0
  74. void  tmr0_isr(){
  75. int8 temp;
  76.  
  77.    if(iContador_1ms==iVeces_iContador_1ms){  
  78.       // retardo antirebotes = 1ms * iVeces_iContador_1ms
  79.       // ya pasaron 30 ms después de la interrupción
  80.       // por cambio de PORTB (el retardo puede variarse)
  81.       temp = input_b() & iLos_Cuatro_MSB_PORTB;
  82.       if(iFlanco_RB == temp){
  83.       // pregunta si realmente la tecla se pulsó
  84.       // o por el contrario es un falso contacto
  85.      
  86.       // aqui es donde se procesa la tecla para lo que queramos hacer
  87.          iTecla_capturada=kbd_getc();
  88.          fImprimir=1;
  89.        }
  90.       Limpiar_Columnas();
  91.       iContador_1ms=0;
  92.       disable_interrupts(INT_TIMER0);
  93.       #asm movf PORTB,0 #endasm
  94.       clear_interrupt(int_rb); // RBIF = 0 limpia la bandera
  95.       enable_interrupts(int_rb);
  96.    }else{
  97.       iContador_1ms++;
  98.       // continua el miniretardo que es multiplo de retardo deseado
  99.    }
  100. }
  101. //----------------------------------------------------
  102. #int_rb // Interrupcion cambio de estado RB[4-7]
  103. void control_rb() {
  104.    iFlanco_RB = input_b() & iLos_Cuatro_MSB_PORTB;
  105.    // almacena el valor de RB[7-4] inicial
  106.    if(iFlanco_RB != iLos_Cuatro_MSB_PORTB){
  107.       // este condicional sirve para validar cuando se pulsa
  108.       // la tecla (mas NO cuando se suelta).
  109.       // consume 4 lineas de asm.
  110.       disable_interrupts(INT_RB);
  111.       // deselecciona la interrupción por cambio en PORTB
  112.       // para comenzar el retardo antirebote
  113.       iContador_1ms=0;
  114.       setup_timer_0(RTCC_INTERNAL|RTCC_DIV_64|RTCC_8_BIT);
  115.       // configura el Timer0 base de tiempo interno, pre-escaler=1:256
  116.       set_timer0(68); // retardo de ~ 1ms
  117.       enable_interrupts(INT_TIMER0);
  118.    }
  119.    #asm movf PORTB,0 #endasm
  120.    Limpiar_Columnas();
  121. }
  122.  
  123. //--------------------------------------------------
  124. void main() {
  125.    output_a(0);
  126.    output_b(0);
  127.    output_c(0);
  128.    output_d(0);
  129.    output_e(0);
  130.    
  131.    set_tris_a(0x0);
  132.    set_tris_b(0b11110000);  // RB[7-4] son entradas
  133.    set_tris_c(0x0);
  134.    set_tris_d(0x0);
  135.    set_tris_e(0x0);
  136.    
  137.    port_b_pullups(true);  
  138.    // no es obligatorio. Si es false, se colocan pull-up externas en RB[7-4]
  139.    disable_interrupts(global);
  140.    disable_interrupts(INT_TIMER0);
  141.  
  142.    printf("Preparando al teclado por interrupcion (int_RB)\n\r");
  143.  
  144.    Limpiar_Columnas();
  145.    
  146.    enable_interrupts(int_rb);
  147.    #asm movf PORTB,0 #endasm  // con estas 2 lineas, se borra
  148.    clear_interrupt(INT_RB);   // RBIF al inicio del programa
  149.    enable_interrupts(global);
  150.    
  151.    while(1){
  152.       if(fImprimir){
  153.          printf("interrupcion: %x\n\r",iTecla_capturada);
  154.          iTecla_capturada=0;
  155.          fImprimir=0;
  156.       }
  157.    }
  158.    
  159. }

plantilla de ejemplo (template)

Código: C
  1. #include <1xFxxxx.h>
  2. #fuses XT,NOMCLR,NOWDT,NOPROTECT,
  3. #fuses NOLVP,NODEBUG,PUT
  4.  
  5. #use delay(clock=4M)
  6.  
  7. #byte PORTB=0xAAA
  8. // buscar en la datasheet el valor correspondiente a la dirección del portb
  9.  
  10. //*********************************
  11. // variables globales
  12. //*********************************
  13.  
  14. int8 const iVeces_iContador_1ms=30;  // 30ms. Varía de acuerdo a Fosc
  15. int8 iFlanco_RB=0;  // bandera que detecta el primer flanco del pulsador
  16. int8 iContador_1ms=0;  
  17. int8 iTecla_capturada=0;
  18.  
  19. #define iColumna0   PIN_Xn  // defina los pines de elección
  20. #define iColumna1   PIN_Xn
  21. #define iColumna2   PIN_Xn
  22. #define iColumna3   PIN_Xn
  23.  
  24. //*********************************
  25. // archivos a incluir
  26. //*********************************
  27. #include "Teclado_flex_change_portb.C"
  28. //----------------------------------------------------
  29. #int_timer0
  30. void  tmr0_isr(){
  31. int8 temp;
  32.    if(iContador_1ms==iVeces_iContador_1ms){  
  33.       // retardo antirebotes = 1ms * iVeces_iContador_1ms
  34.       // ya pasaron 30 ms después de la interrupción
  35.       // por cambio de PORTB (el retardo puede variarse)
  36.       temp = input_b() & iLos_Cuatro_MSB_PORTB;
  37.       if(iFlanco_RB == temp){
  38.       // pregunta si realmente la tecla se pulsó
  39.       // o por el contrario es un falso contacto
  40.      
  41.       // aqui es donde se procesa la tecla para lo que queramos hacer
  42.          iTecla_capturada=kbd_getc();
  43.        }
  44.       Limpiar_Columnas();
  45.       iContador_1ms=0;
  46.       disable_interrupts(INT_TIMER0);
  47.       #asm movf PORTB,0 #endasm
  48.       clear_interrupt(int_rb); // RBIF = 0 limpia la bandera
  49.       enable_interrupts(int_rb);
  50.    }else{
  51.       iContador_1ms++;
  52.       // continua el miniretardo que es multiplo de retardo deseado
  53.    }
  54. }
  55. //----------------------------------------------------
  56. #int_rb // Interrupcion cambio de estado RB[4-7]
  57. void control_rb() {
  58.    iFlanco_RB= PORTB & iLos_Cuatro_MSB_PORTB;
  59.    // almacena el valor de RB[7-4] inicial
  60.    if(iFlanco_RB != iLos_Cuatro_MSB_PORTB){
  61.       // este condicional sirve para validar cuando se pulsa
  62.       // la tecla (mas NO cuando se suelta).
  63.       // consume 4 lineas de asm.
  64.       disable_interrupts(INT_RB);
  65.       // deselecciona la interrupción por cambio en PORTB
  66.       // para comenzar el retardo antirebote
  67.       iContador_1ms=0;
  68.       setup_timer_0(RTCC_INTERNAL|RTCC_DIV_64|RTCC_8_BIT);
  69.       // configura el Timer0 base de tiempo interno, pre-escaler=1:256
  70.       set_timer0(68); // retardo de ~ 1ms. Varía de acuerdo a Fosc
  71.       enable_interrupts(INT_TIMER0);
  72.    }
  73.    #asm movf PORTB,0 #endasm
  74.    Limpiar_Columnas();
  75. }
  76.  
  77. //--------------------------------------------------
  78. void main() {
  79.    //...
  80.    output_b(0);
  81.    //...
  82.    set_tris_b(0b11110000);  // RB[7-4] son entradas
  83.    // los pines correspondiente a las columnas deben ser salidas
  84.    //...
  85.    port_b_pullups(true);  
  86.    // no es obligatorio. Si es false, se colocan pull-up externas en RB[7-4]
  87.    disable_interrupts(global);
  88.    disable_interrupts(INT_TIMER0);
  89.  
  90.    Limpiar_Columnas();
  91.    
  92.    enable_interrupts(int_rb);
  93.    #asm movf PORTB,0 #endasm  // con estas 2 lineas, se borra
  94.    clear_interrupt(INT_RB);   // RBIF al inicio del programa
  95.    enable_interrupts(global);
  96.    //...
  97.    //...
  98.    while(1){
  99.         //...
  100.         // aquí se procesa a iTecla_capturada
  101.         //...
  102.       }
  103. }


imagen del circuito:

(http://img519.imageshack.us/img519/2745/tecladointerruptal0.th.jpg) (http://img519.imageshack.us/my.php?image=tecladointerruptal0.jpg)

pura interrupción, ahora lo tengo de moda, nada de perdedera de tiempo metido en bucles "inutiles" cuando se cuenta con herramientas como int_rb e int_timer. Hace todo el rastreo del teclado CUANDO DEBE HACERLO, y luego el contador de programas vuelve a su bucle principal y deja el sistema (int_rb and int_timer) listo y calentito para cuando algún humano se le ocurra presionar una tecla otra vez jijiji

y otra cosa super importante, libera los 4 pines LSB del portb que suponen las columnas del teclado, y se pueden definir como cualquier otros pines independientes y de cualquier puerto (siempre que sean salidas)

Hasta la fecha NO he probado este código en Físico, puesto que no cuento con las 16 teclas necesarias. Pero hice una variante de este programa para 7 teclas y con el mismo método de interrupción RB[7-4] + timer0 y funcionó correctamente en el protoboard.

bajar adjunto (http://www.4shared.com/file/47590791/ee40dc99/Teclado_4x4_Flex_INTRB.html)
     
pd: Disfruté escribiendo este programa y el agradecimiento al maestro pocher por su programa ;)
Título: Re: Teclado matricial Flex 4x4 interrupción RB[7-4] + antirebote int_timer0
Publicado por: jfh900 en 14 de Mayo de 2008, 16:49:36
Excelente trabajo Pedro.

Una cuestión: ¿no se podría incluir la/s interrupción/es dentro de la librería?.

La idea es mediante el preprocesador verificar que no se ha asignado las interrupciones (y si esto sucede dar un mensaje de error) y asignar la interrupción dentro de la librería.

Un saludo
Título: Re: Teclado matricial Flex 4x4 interrupción RB[7-4] + antirebote int_timer0
Publicado por: PalitroqueZ en 15 de Mayo de 2008, 15:03:43
podría ser.

Al driver le hecho como una docena de cambios. Siempre tratando de mejorarla.

int_rb puede entrar bien en el driver, el timer si y no. porque si lo vamos a utilizar en otros procesos, debería ser visible en el main.

no creo que ocurran choques entre interrupciones, ya que se desactiva uno justo cuando comienza el otro.

hay que pensar en todos los casos posibles para hacerlo generalizado, uff.  :)



Título: Re: Teclado matricial Flex 4x4 interrupción RB[7-4] + antirebote int_timer0
Publicado por: Nocturno en 15 de Mayo de 2008, 15:09:04
Me encanta; muchas gracias Pedro.

La sugerencia de Jesús es muy buena, pero también te entiendo a ti: siempre se puede mejorar algo, pero en ese caso nunca acabarías  :D
Título: Re: Teclado matricial Flex 4x4 interrupción RB[7-4] + antirebote int_timer0
Publicado por: pocher en 16 de Mayo de 2008, 04:15:00
Gracias por el programa Pali.

Ayer lo descargué y le hice algunas modificaciones para probarlo en un teclado real, con un 16F876 y una LCD.

Hoy por la mañana he terminado de hacer todas las pruebas tanto con PROTEUS como físicamente y va muy bien. Solo un pequeño pero, para que aparezca la tecla debes de estar apretando demasiado tiempo, ocurre tanto con PROTEUS como en real.

Me pongo y subo el archivo con la simulación: con un 16F876, un teclado de 16 teclas y una LCD. Tanto el teclado como la LCD, todo conectado al PORTB.

Un saludo
Título: Re: Teclado matricial Flex 4x4 interrupción RB[7-4] + antirebote int_timer0
Publicado por: pocher en 16 de Mayo de 2008, 05:59:46
Me he demorado un poco en subirlo porque estaba dándole vueltas a lo del retraso y ya lo solucioné.

Lo estaba probando con un cristal de 4Mhz (el que tengo aquí) y con este va lento. He hecho la prueba en PROTEUS cambiando en la programación a 20MHZ y va como un tiro. :-/

Aquí debajo os dejo todos los archivos.
Título: Re: Teclado matricial Flex 4x4 interrupción RB[7-4] + antirebote int_timer0
Publicado por: PalitroqueZ en 19 de Mayo de 2008, 12:32:16
pocher revisé lo que subiste, dejame decirte que está interesante ese caso ;)

lo digo porque usas RB[7-4] para enviar datos a la lcd, en tal condición el flag RBIF se activará a partir del primer cambio portb originado por el primer nibble enviado a la pantalla.

no se cuál seran las consecuencias si cuando manda a imprimir al lcd, presiono una tecla. Por si las moscas, es mejor deshabilitar INT_RB al momento de usar lcd_putc y limpiar las columnas.

quedaría así:

Código: C
  1. ...
  2.    while(1){
  3.       if(fImprimir){
  4.          printf("interrupcion: %x\n\r",iTecla_capturada);
  5.          
  6.          disable_interrupts(INT_RB);
  7.          set_tris_b(0x0F);         //Activar LCD
  8.          lcd_gotoxy(1,1);
  9.          printf(lcd_putc,"interrupcion: %x",iTecla_capturada);
  10.          lcd_gotoxy(1,2);
  11.          for(n=0;n<16;n++)
  12.          {
  13.                if(iTecla_capturada==a[n])      printf(lcd_putc,"Tecla=%c",b[n]);
  14.              }
  15.          set_tris_b(0xF0);         //Activar teclado
  16.          
  17.          iTecla_capturada=0;
  18.          fImprimir=0;
  19.          Limpiar_Columnas();
  20.          #asm movf PORTB,0 #endasm  // con estas 2 lineas, se borra
  21.          clear_interrupt(INT_RB);   // RBIF al inicio del programa
  22.          enable_interrupts(int_rb);
  23.  
  24.       }
  25.    }

lo otro: Se te olvidó configurar el timer0 para el nuevo cristal (1 ms -> TMR0=6 con prescaler: 4 )

podría ponerse una ecuación para que el mismo programa calcule el dato en timer0, pero lo veo dificil, porque también involucra al prescaler, y todas las combinaciones que conlleva (sin sumar todos los distintos cristales que el usuario vaya usar)

Cuando tengas un tiempito, pruéba el programa modificado en físico, a ver que tal.

bajar adjunto:
Título: Re: Teclado matricial Flex 4x4 interrupción RB[7-4] + antirebote int_timer0
Publicado por: pocher en 20 de Mayo de 2008, 08:47:22
Sí, se me olvidó ... a los programas solo los entiende la madre (padre) que los parió.  :D

Oye que lo he probado en físico con 4 Mhz y ahora sí que va bien, la tecla aparece rápidamente en pantalla. Totalmente de acuerdo con las mejoras que le has introducido ahora, más vale prevenir.

Un saludo Pali.
Título: Re: Teclado matricial Flex 4x4 interrupción RB[7-4] + antirebote int_timer0
Publicado por: jfh900 en 21 de Mayo de 2008, 04:57:33
lo otro: Se te olvidó configurar el timer0 para el nuevo cristal (1 ms -> TMR0=6 con prescaler: 4 )

podría ponerse una ecuación para que el mismo programa calcule el dato en timer0, pero lo veo dificil, porque también involucra al prescaler, y todas las combinaciones que conlleva (sin sumar todos los distintos cristales que el usuario vaya usar)

¿Por qué no utilizais el preprocesador para seleccionar el reloj y el preescalar?

Un saludo
Título: Re: Teclado matricial Flex 4x4 interrupción RB[7-4] + antirebote int_timer0
Publicado por: PalitroqueZ en 21 de Mayo de 2008, 12:55:38
tendré que averiguar que significa


Título: Re: Teclado matricial Flex 4x4 interrupción RB[7-4] + antirebote int_timer0
Publicado por: pocher en 21 de Mayo de 2008, 13:38:29
Sí, supongo que Jesús se refiere a sentencias #IFDEF #IFNDEF #ELSE etc

Sería una mejora más.

Aprovecho ahora Pali para comentarte que pensaré lo del fallo del antirebotes software, a ver si lo sacamos.

Un saludo
Título: Re: Teclado matricial Flex 4x4 interrupción RB[7-4] + antirebote int_timer0
Publicado por: jfh900 en 21 de Mayo de 2008, 16:46:11
Efectivamente a eso me refería, que definiendo una variable del preprocesador, se ajustaran los parámetros y no se tenga que variar medio programa.

Un saludo
Título: Re: Teclado matricial Flex 4x4 interrupción RB[7-4] + antirebote int_timer0
Publicado por: PalitroqueZ en 21 de Mayo de 2008, 17:37:33
ah entonces ya me pongo a ello.  :mrgreen:



Título: Re: Teclado matricial Flex 4x4 interrupción RB[7-4] + antirebote int_timer0
Publicado por: PalitroqueZ en 02 de Junio de 2008, 16:48:30
Hola, me he puesto ha mejorar el "driver" para escribir menos a la hora de usarlo en un programa particular.

he tomado la sugerencia de Jesús, en cuanto a pre-procesar las interrupciones, pero no he hallado una solución.

por ejemplo: se pretende que el compilador detecte una segunda #int_rb

siguiendo la ayuda, coloqué

Código: C
  1. ...
  2. #if defined(INT_RB)
  3.    #error  La Interrupcion por cambio en PORTB, viene incluida en Teclado_flex_change_portb
  4. #else
  5. #int_rb
  6. void control_rb() {
  7.    iFlanco_RB = input_b() & iLos_Cuatro_MSB_PORTB;
  8. ..
  9. #endif
  10. ...

pero siempre va directo al error, probé con #ifndef, igual. si no coloco eso, el compilador si detectará la doble interrupción (error 92) pero no me indicará donde está la otra (que era precisamente que señalaría #error).

Título: Re: Teclado matricial Flex 4x4 interrupción RB[7-4] + antirebote int_timer0
Publicado por: Cryn en 11 de Octubre de 2008, 12:02:18
es una muy buena aplicacion, he estado intentando hacer uno parecido, tb por interrupcion en RB, y usando el timer 1 para rotar un cero para que sea recibido en el nible alto de RB.

Segun he visto tu codigo no hace rotar ningun cero, solamente explora la interrupcion RB y ahí directamente analiza donde ha sido pulsado, es esto correcto o me equivoco?

Si fuera así sería muy interesante, pues usas 2 interrupciones (rb y tmr0 antirrebote); ya que yo usaría 3, rb, tmr1 para rotar y tmr2 para antirrebote, que me parece un desperdicio de recursos por mi parte.

Cuentame un detalle más, que pasa en el antirrebote, me parecio entender que hay un retardo de una cantidad x de milisegundos, y despues recien se ejecuta la detección de la tecla pulsada. Y como reacciona tu codigo ante teclas manteniendose presionadas??

Muchas gracias por el aporte, está buenísimo.
Título: Re: Teclado matricial Flex 4x4 interrupción RB[7-4] + antirebote int_timer0
Publicado por: PalitroqueZ en 11 de Octubre de 2008, 18:46:32
Saludos de nuevo Cryn  8)

Sip, uso el desplazamiento de bits, mira un extracto de teclado_flex_change_portb.c

Código: C
  1. ...
  2. void  Configurar_iPuerto_compuesto(void){
  3.   iPuerto_compuesto=0;
  4.   iPuerto_compuesto = input_b() & iLos_Cuatro_MSB_PORTB;
  5.   iPuerto_compuesto |= (input_state(iColumna3) << 3);
  6.   iPuerto_compuesto |= (input_state(iColumna2) << 2);
  7.   iPuerto_compuesto |= (input_state(iColumna1) << 1);
  8.   iPuerto_compuesto |= input_state(iColumna0);
  9. }
  10. ...

El funcionamiento sigue así:

- interrupción timer0 = deshabilitada
- interrupción por cambio de flanco en RB[7-4] (int_rb) = habilitada
- bucle prinicipal activo
- al producirse una pulsación, ocurre un cambio de flanco en RB, por lo que ocurrirá una interrupción int_rb

- En la función void control_rb(), configuro y activo el timer0 no sin antes haber guardado el dato que corresponde a la tecla pulsada.

- se deshabilita int_rb

- a partir de allí, seguirá el bucle principal activo, ocurriendo una interrupción timer0 cada milisegundo.

- En cada interrupción timer0, se incrementará un contador, cuando dicho contador llegue a 30, es porque han transcurrido ~30ms desde que se pulsó la tecla, entonces hago una nueva lectura de los pines asociados al teclado matricial.

- Si esa nueva lectura coincide con la lectura que tomé al inicio de int_rb, quiere decir que efectivamente es una pulsación válida y la tomo como tal para procesar futuros eventos.

- el resto es limpiar las variables asociadas al timer, deshabilitarlo y habilitar el int_rb para una futura pulsación.


notas:
- ten en cuenta que en el intervalo de los 30ms, si pulsas una tecla, no ocurrirá nada, porque int_rb es deshabilitada.

- se toman las previsiones respectivas de limpiar el puerto, etc. para permitir una int_rb a posteriori.

- La finalidad del timer0 es antirebotes unicamente (base de tiempo de 1ms).


Título: Re: Teclado matricial Flex 4x4 interrupción RB[7-4] + antirebote int_timer0
Publicado por: Cryn en 14 de Octubre de 2008, 15:45:25
Entendido Pali, muchas gracias por tu explicación, ahora lo entiendo mejor.

Disculpa ser tan abusivo, pero me podrías explicar como es qeu funciona la detección de la tecla presionada?? osea los desplazamietos de bits??

y que me dices con las teclas que se presionan y se mantienen presionadas por un tiempo indefinido, tu sabes usuarios locos que las gusta mantener presionadas las teclas por ganas de...  :D tu sabes.

un abrazo Pali
Título: Re: Teclado matricial Flex 4x4 interrupción RB[7-4] + antirebote int_timer0
Publicado por: PalitroqueZ en 15 de Octubre de 2008, 13:16:33
Una de las funciones de teclado_flex_change_portb.c es traducir la tecla pulsada a un número constante, y con dicho numero podemos procesar esa tecla en otra función.

si pulsas mas de un tecla, entonces se leerá un número que no corresponde a las constantes declaradas y por tanto no tendrá efecto.

si mantienes una tecla pulsada indefinidamente, el programa correrá igual como si la pulsas regularmente, (de no ser así habrá una rutina que añadir para evitar los posibles efectos)
Título: Re: Teclado matricial Flex 4x4 interrupción RB[7-4] + antirebote int_timer0
Publicado por: Cryn en 17 de Octubre de 2008, 13:36:11
saludos Pali, gracias por la respuesta, he estado viendo tu codigo y tengo unas nuevas dudas:

1. para q usas #asm movf PORTB,0 #endasm ? osea que significará para el programa?

2. si uso netamente el puerto B, ya no hace falta hacer puerto compuesto, no?

3. una vez que la tecla es reconocida, que pasa si se mantiene el cero por un instante y ocurre otra interrupcion por cambio de estado de 0 a 1.

4. Haz hech multiplezacion con un LCD, si no donde crees q puedan ir algunas modificaciones, para que no se interfieran entre si.

Muchas gracias por la ayuda, un saludo.
Título: Re: Teclado matricial Flex 4x4 interrupción RB[7-4] + antirebote int_timer0
Publicado por: PalitroqueZ en 18 de Octubre de 2008, 13:14:08
Hola Cryn

Respuestas:

1.)

Código: C
  1. #asm movf PORTB,0 #endasm  // con estas 2 lineas, se borra
  2.  clear_interrupt(INT_RB);   // RBIF al inicio del programa

"The input pins (of RB7:RB4)
are compared with the old value latched on the last
read of PORTB. The “mismatch” outputs of RB7:RB4
are OR’ed together to generate the RB port change
interrupt with flag bit RBIF (INTCON<0>).

This interrupt can wake the device from Sleep. The
user, in the Interrupt Service Routine, can clear the
interrupt in the following manner:


a) Any read or write of PORTB. This will end the
mismatch condition.

b) Clear flag bit RBIF.

A mismatch condition will continue to set flag bit RBIF.
Reading PORTB will end the mismatch condition and
allow flag bit RBIF to be cleared
"

Este texto que lo puedes conseguir en la mayoría de los datasheet cuyos pics poseen sistema de interrupción por cambio de flanco en RB[7-4]

2.)

 nop, si no usas iPuerto_compuesto, entonces el programa no funcionará

3.)
 
Código: C
  1. #int_rb
  2. ...
  3. if(iFlanco_RB != iLos_Cuatro_MSB_PORTB){
  4. // este condicional sirve para validar cuando se pulsa
  5. // la tecla (mas NO cuando se suelta).
  6. ...

precisamente este condicional rechaza el flanco ascendente. La única manera que entre a ese if, es cuando se pulsa la tecla (si la tecla se suelta, no entrará y saldrá al final de la función int_rb:

Código: C
  1. ...
  2. #asm movf PORTB,0 #endasm
  3. Limpiar_Columnas();
  4. ...

4.)

 No lo he probado, pero según el gran pocher le ha funcionado bien:

http://www.todopic.com.ar/foros/index.php?topic=21747.msg170680#msg170680



...
si mantienes una tecla pulsada indefinidamente, el programa correrá igual como si la pulsas regularmente, (de no ser así habrá una rutina que añadir para evitar los posibles efectos)

quiero hacer una correción: si dejas una tecla pulsada indefinidamente, no ocurrirá nada, si quieres que esa misma tecla tenga el efecto deseado, tendras que soltarla y volverla a presionar.

Título: Re: Teclado matricial Flex 4x4 interrupción RB[7-4] + antirebote int_timer0
Publicado por: Cryn en 21 de Octubre de 2008, 19:04:16
ok muchísimas gracias por las respuestas Pali, tardé en responder pero ya las había leído, las estaba analizando y aplicando :mrgreen:

y pues ahora me doy cuenta de porque entraba a la rutina de interrupcion rb al comienzo de mi programa sin presionar ninguna tecla, no sabia porque, gracias por la "quote" de la hoja de datos, ya lo he corregido.
Pero como soy testarudo y me gusta qe todo este en C, he puesto esta instruccion: output_b(input_b()); que hace lo mismo y en asm me genera esto:
....................    output_b(input_b());
29C0:  MOVFF  F81,F8A
....................    clear_interrupt(INT_RB);
29C4:  BCF    FF2.0

sobre el lcd lo estoy viendo, por ahora he tenido unos resultados más o menos buenos, tengo una rutina donde atiendo a la tecla que se ha presionado, y cuando termino hago el tris, para ponerlo a teclado, y en la lib del lcd siempre hace el tris que necesita para manejar correctamente el lcd.

tengo todavía algunos problemas, pero creo qeu ya son menores.

muchas gracias por la ayuda, es muy buena esta tecnica, gracias a pocher, y a ti Pali por el desarrollo y la excelente explicación
Título: Re: Teclado matricial Flex 4x4 interrupción RB[7-4] + antirebote int_timer0
Publicado por: PalitroqueZ en 22 de Octubre de 2008, 13:24:35
Mira seria conveniente que miraras el flag del timer cuando lo configures dentro de void control_rb(), debe estar a cero al salir de esa interrupción, sino entonces no pasaran los 30ms sino un tiempo mucho menor y no funcionará y te producirá el efecto de que cuando presiones una tecla, se procesará mas de una vez (incluso 3 o 4 veces).

También intenta bajar el retardo antirebotes e.j: 15ms
o puedes poner 3 comprobaciones del puerto_compuesto, en fin, debes ajustar en caso que hayas problemas.


Título: Re: Teclado matricial Flex 4x4 interrupción RB[7-4] + antirebote int_timer0
Publicado por: Cryn en 22 de Octubre de 2008, 16:47:59
Mira seria conveniente que miraras el flag del timer cuando lo configures dentro de void control_rb(), debe estar a cero al salir de esa interrupción, sino entonces no pasaran los 30ms sino un tiempo mucho menor y no funcionará y te producirá el efecto de que cuando presiones una tecla, se procesará mas de una vez (incluso 3 o 4 veces).

eh?? si en la int rb se activa la int timer como podrá ser inmediatamente 0 su flag al salir de la interrupcion rb?


descarte los defines, ya que uso directamente el puerto b para todo, de ahi iba mi pregunta si el puerto compuesto era necesario, hice sin ello (sin el puerto_compuesto) y me ha funcionado, utilizando directamente el puertoB.

donde colocarías las 3 comprobaciones?

thxs
Título: Re: Teclado matricial Flex 4x4 interrupción RB[7-4] + antirebote int_timer0
Publicado por: PalitroqueZ en 24 de Octubre de 2008, 15:56:57

#int_rb // Interrupcion cambio de estado RB[4-7]

void control_rb() {

  iFlanco_RB = input_b() & iLos_Cuatro_MSB_PORTB;

  // almacena el valor de RB[7-4] inicial
  if(iFlanco_RB != iLos_Cuatro_MSB_PORTB){
     // este condicional sirve para validar cuando se pulsa
     // la tecla (mas NO cuando se suelta).
     // consume 4 lineas de asm.
     disable_interrupts(INT_RB);
     // deselecciona la interrupción por cambio en PORTB
     // para comenzar el retardo antirebote
     iContador_1ms=0;
     clear_interrupt(int_timer0);   // borrar el flag del timer0 por precaución
     setup_timer_0(RTCC_INTERNAL|RTCC_DIV_64|RTCC_8_BIT);
     // configura el Timer0 base de tiempo interno, pre-escaler=1:256
     set_timer0(68); // retardo de ~ 1ms
     enable_interrupts(INT_TIMER0);#
  }
...



Título: Re: Teclado matricial Flex 4x4 interrupción RB[7-4] + antirebote int_timer0
Publicado por: Cryn en 24 de Octubre de 2008, 16:04:27
ahhh disculpa el mal entendido, te referías a eso. vale lo estaré probando, muchas gracias Pali
Título: Re: Teclado matricial Flex 4x4 interrupción RB[7-4] + antirebote int_timer0
Publicado por: hard8507 en 26 de Agosto de 2009, 02:32:42
alguien q pueda poner alguna simulacion del teclado matricial y el lcd gracias
Título: Re: Teclado matricial Flex 4x4 interrupción RB[7-4] + antirebote int_timer0
Publicado por: PalitroqueZ en 26 de Febrero de 2011, 14:04:50
una proyectico que estoy haciendo y utilizando la librería Teclado_flex_change_portb.C



en este caso, se hace uso de los pines RB[7-4] y RA[3-1] para comandar las teclas dispuestas en filas y columnas respectivamente
Título: Re: Teclado matricial Flex 4x4 interrupción RB[7-4] + antirebote int_timer0
Publicado por: Diamel en 07 de Junio de 2011, 15:06:06
Buenos dias estoy intentando adapatar la libreria para el PIC18F252 en C18 y actualmente estoy teniendo problemas con respecto a los pulsos que me envia el teclado al presionar una tecla.
adjunto una imagen de como estoy intentando simularlo, el problema para ser mas especifico es que el puerto RB4-7 en la simulacion del ejemplo se encuentran en 1 y al presionar la tecla se va a 0 dependiendo de la fila que se presiono. he intendado hacer lo  mismo en C18 y no funciona ya que todo el puerto se queda en 0 siempre.


Este es el main del original:
Código: [Seleccionar]
void main() {
   //...
   output_b(0);
   //...
   set_tris_b(0b11110000);  // RB[7-4] son entradas
   // los pines correspondiente a las columnas deben ser salidas
   //...
   port_b_pullups(true); 
   // no es obligatorio. Si es false, se colocan pull-up externas en RB[7-4]


Este es el main de C18:

Código: [Seleccionar]
void main()
{

PORTB=0; //puerto B en 0
TRISB=0x11110000; //RB7-4 Entradas
INTCON2bits.RBPU = 0; //Pullup Puerto B activada


La razon por lo que se queda todo el puerto B la se ya que yo mismo lo estoy poniendo en 0, pero en el otro codigo no veo ninguna parte donde hagan algo diferente.

Espero alguien me pueda ayudar :-p, Salu2.
Título: Re: Teclado matricial Flex 4x4 interrupción RB[7-4] + antirebote int_timer0
Publicado por: PalitroqueZ en 08 de Junio de 2011, 00:11:17
Hola Diamel.

te puedo ayudar con la lógica del programa, mas no con el C18  :(

casi al inicio del main, hice blanquear al puerto, por cuestiones de prevención (según lo dicta microchip).

pero, el hecho de que quede el portb=0, no es algo propio del programa.

al menos RB[7-4], deben estar a 1 todo el tiempo, porque el programa realiza un barrido y en cada paso, uno de los 4 pines altos del portb se coloca a 0 (el que corresponde a la tecla pulsada).

la única forma de que RB[7-4] sea 0, es que presiones las 4 filas simultáneamente, (y aún así, habrá un intervalo de tiempo donde los otros pines altos del portb se colocan en alto)

el control de los pines bajos del portb, depende de la selección que hayas hecho para las columnas, no se me ocurre porque lo tengas en cero todo el tiempo, harían falta mas detalles de la programación que llevas

Título: Re: Teclado matricial Flex 4x4 interrupción RB[7-4] + antirebote int_timer0
Publicado por: Suky en 08 de Junio de 2011, 00:31:57
Si quieres escribir en el puerto utiliza los registros LATx... Aunque aquí no sea el problema, es mejor que lo adoptes. Luego podrías probarlo con el micro, puede ser un problema de simulación.



Saludos!
Título: Re: Teclado matricial Flex 4x4 interrupción RB[7-4] + antirebote int_timer0
Publicado por: bondadoso en 05 de Agosto de 2011, 20:02:28
una preguntota esta libreria es para ccs verdad yo necesito una para c18! ojala alguien se anime a compartirla!
Título: Re: Teclado matricial Flex 4x4 interrupción RB[7-4] + antirebote int_timer0
Publicado por: PalitroqueZ en 06 de Agosto de 2011, 21:26:20
una preguntota esta libreria es para ccs verdad ...

sip