Autor Tema: Problema con teclado e Interrupcion RB en CCS y 16F877  (Leído 10355 veces)

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

Desconectado firepic

  • Colaborador
  • PIC24H
  • *****
  • Mensajes: 1130
    • JC Servicios
Re: Problema con teclado e Interrupcion RB en CCS y 16F877
« Respuesta #15 en: 15 de Noviembre de 2010, 22:14:04 »
Qué tal!! Pues listo, listo!  :-/  :-/  :-/
Código funcionando... introduje el código de AngelGris (la función "captura") en la parte de la rutina de interrupción que yo tenía y funcionó de lujo!!  :)
Creo que todavía se puede optimizar un poquito más el código, pero sólo es cuestión de "cursilería", pues este funciona perfecto (por lo menos en proteus, habría que probarlo en vivo a ver qué tal se comporta)...
Por ahora aquí está el código en CCS funcionando:

Código: C
  1. ///////////////////////////////////////////////
  2. //             lee un teclado 4x4                //
  3. //   y envia al pc por puerto serial         //
  4. ///////////////////////////////////////////////
  5.  
  6. #include <16f876.h>
  7. #fuses HS,NOWDT,NOPROTECT,NOLVP,PUT,NOBROWNOUT
  8. #define Tx PIN_C6
  9. #define Rx PIN_C7
  10. #use delay (CLOCK=20000000)
  11. #use rs232 (BAUD=19200,XMIT=Tx,RCV=Rx)
  12. #use fast_io(A)
  13. #use fast_io(B)
  14. #byte port_b = 0x06
  15. #byte tris_b = 0xff
  16. boolean flag;
  17. int fila,columna,tecla;
  18.  
  19. /************************************************
  20. Esta es la rutina que devuelve la tecla pulsada
  21. Los valores devueltos van de 1 a 16
  22. [Esta rutina es cortesía de AngelGris, muchas gracias compañero!]
  23. *************************************************/
  24. unsigned char captura(void)
  25. {
  26.  unsigned char lectura;
  27.  output_b (0b00000001); // activo la primer fila
  28.  lectura = port_b & 0xF0; // leo el puerto B y hago una and porque solo me interesa el nibble alto
  29.  output_b (0x0F); // activo todas las salidas
  30.  if (lectura == 0b00010000) return 1;
  31.  if (lectura == 0b00100000) return 2;
  32.  if (lectura == 0b01000000) return 3;
  33.  if (lectura == 0b10000000) return 4;
  34. output_b (0b00000010); // activo la segunda fila
  35. lectura = port_b & 0xF0; // leo el puerto B y hago una and porque solo me interesa el nibble alto
  36. output_b (0x0F); // activo todas las salidas
  37. if (lectura == 0b00010000) return 5;
  38. if (lectura == 0b00100000) return 6;
  39. if (lectura == 0b01000000) return 7;
  40. if (lectura == 0b10000000) return 8;
  41. output_b (0b00000100); // activo la tercer fila
  42. lectura = port_b & 0xF0; // leo el puerto B y hago una and porque solo me interesa el nibble alto
  43. output_b (0x0F); // activo todas las salidas
  44. if (lectura == 0b00010000) return 9;
  45. if (lectura == 0b00100000) return 10;
  46. if (lectura == 0b01000000) return 11;
  47. if (lectura == 0b10000000) return 12;
  48. output_b (0b00001000); // activo la cuarta fila
  49. lectura = port_b & 0xF0; // leo el puerto B y hago una and porque solo me interesa el nibble alto
  50. output_b (0x0F); // activo todas las salidas
  51. if (lectura == 0b00010000) return 13;
  52. if (lectura == 0b00100000) return 14;
  53. if (lectura == 0b01000000) return 15;
  54. if (lectura == 0b10000000) return 16;
  55. return 0;
  56. }
  57.  
  58. #INT_RB
  59. void tecla_presionada()
  60. {
  61.         int i,puerto_1,puerto_2;
  62.         disable_interrupts(INT_RB);                                                             //deshabilita las interrupciones
  63.         tecla=captura();
  64.         flag=1;
  65.         set_tris_b(0xf0);
  66.         output_b(0x0f);
  67.         clear_interrupt(INT_RB);
  68.         enable_interrupts(INT_RB);
  69. }
  70.  
  71. void main()
  72. {
  73.         output_a(0x00);
  74.         output_b(0x0f);
  75.         set_tris_b(0xf0);
  76.         enable_interrupts(INT_RB);
  77.         enable_interrupts(GLOBAL);
  78.         while(TRUE)
  79.         {
  80.                 if(flag==1)
  81.                 {
  82.                         printf("Tecla presionada: %i\n\r",tecla);
  83.                         flag=0;
  84.                 }
  85.         }
  86. }

Ok saludos a todos, nos leemos!  :mrgreen:
"Por la presunción solo se ocasiona una lucha, pero con los que consultan juntos hay sabiduría" (Proverbios 13:10).
Visita Mi Sitio Web

Desconectado AngelGris

  • Colaborador
  • PIC24H
  • *****
  • Mensajes: 2480
Re: Problema con teclado e Interrupcion RB en CCS y 16F877
« Respuesta #16 en: 16 de Noviembre de 2010, 09:05:01 »
Hola FirePic

  Sería conveniente que antes de "leer la tecla", es decir, antes de ejecutar la función captura pongas un delay de unos 10mS (en mi ejemplo lo había llamado Antirrebote) porque en muchas ocasiones la teclas generan ( "rebote"  ) falsos presionados.
  También sería conveniente hacer primero una lectura del puerto, luego el delay (10mS) y otra vez una lectura, entonces si ambas lecturas son iguales (y distinto de 0 ) es porque realmente tenés presionada una tecla, y ahí si activás el flag y ejecutás la función captura. Si la lectura da 0, quiere decir que no hay tecla presionada.

  En mi ejemplo activo directamente el flag (en la rutina de itnerrupción), pero luego en el bucle principal sólo ejecuto captura si al hacer 2 lecturas consecutivas (con el AntiRebote de por medio) en el puerto tengo el mismo valor.

 
De vez en cuando la vida
nos besa en la boca
y a colores se despliega
como un atlas

Desconectado firepic

  • Colaborador
  • PIC24H
  • *****
  • Mensajes: 1130
    • JC Servicios
Re: Problema con teclado e Interrupcion RB en CCS y 16F877
« Respuesta #17 en: 16 de Noviembre de 2010, 12:10:53 »
Qué tal!
Bueno ahora creo que sí ya listo!  :-/

Agregué lo que me dices AngelGris, gracias por tus sugerencias! También acomodé un poco más  a mi gusto el código de rastrear la tecla...  :-)
En proteus funciona correctamente, ahí se los dejo:

Código: C
  1. ///////////////////////////////////////////////
  2. //             lee un teclado 4x4                //
  3. //   y envia al pc por puerto serial         //
  4. ///////////////////////////////////////////////
  5.  
  6. #include <16f876.h>
  7. #fuses HS,NOWDT,NOPROTECT,NOLVP,PUT,NOBROWNOUT
  8. #define Tx PIN_C6
  9. #define Rx PIN_C7
  10. #use delay (CLOCK=20000000)
  11. #use rs232 (BAUD=19200,XMIT=Tx,RCV=Rx)
  12. #use fast_io(A)
  13. #use fast_io(B)
  14. #byte port_b = 0x06
  15. #byte tris_b = 0xff
  16. boolean flag_teclado;
  17. int tecla,fila,columna;
  18.  
  19. /********************************
  20. Esta Rutina permite rastrear el teclado
  21. y devuelve el valor de la tecla que se
  22. ha presionado
  23. ************************************/
  24. int captura(void)
  25. {
  26.         int const teclado[4][4] = {{1,2,3,4},
  27.                                             {5,6,7,8},
  28.                                             {9,10,11,12},
  29.                                             {13,14,15,16}};
  30.         int tecla,lectura,i;
  31.         for(i=0;i<4;i++)
  32.         {
  33.                 output_b(0);
  34.                 bit_set(port_b,i);
  35.                 lectura = port_b & 0xf0;
  36.                 switch(lectura)
  37.                 {
  38.                         case 0b00010000: columna=0;
  39.                                                   fila=i;      
  40.                                                   break;       
  41.                         case 0b00100000: columna=1;
  42.                                                   fila=i;      
  43.                                                   break;
  44.                         case 0b01000000: columna=2;
  45.                                                   fila=i;      
  46.                                                   break;
  47.                         case 0b10000000: columna=3;
  48.                                                   fila=i;      
  49.                                                   break;
  50.                 }
  51.         }
  52.         tecla = teclado[fila][columna];
  53.         return(tecla);
  54. }
  55.  
  56. /***************************************
  57. Rutina de Interrupci&#243;n.
  58. - Antirebote.
  59. - Llama a rutina "captura" para saber
  60.    la tecla presionada.
  61. - Activa la bandera "flag_teclado"
  62.    a usar en el main o en otra parte
  63.    del programa.
  64. ***************************************/
  65. #INT_RB
  66. void tecla_presionada()
  67. {
  68.         int lectura_1,lectura_2;
  69.         lectura_1 = port_b & 0b11110000;                //lee portb4:7 y lo guarda en lectura_1
  70.         delay_ms(10);                                   //Funci&#243;n AntiRebotes:   - Espero 10ms.
  71.         lectura_2 = port_b & 0b11110000;                //                               - Vuelvo a leer el puerto.
  72.         if(lectura_1==lectura_2 && lectura_1!=0) //                               - Si el valor es igual y distinto de 0
  73.         {                                                       //                                  es porque en realidad se presion&#243; una tecla.
  74.                 tecla = captura();
  75.                 flag_teclado=1;
  76.         }
  77.         set_tris_b(0xf0);
  78.         output_b(0x0f);
  79.         clear_interrupt(INT_RB);
  80. }
  81.  
  82. void main()
  83. {
  84.         set_tris_b(0xf0);
  85.         enable_interrupts(INT_RB);
  86.         enable_interrupts(GLOBAL);
  87.         while(TRUE)
  88.         {
  89.                 if(flag_teclado==1)
  90.                 {
  91.                         printf("Tecla presionada: %i\n\r",tecla);
  92.                         flag_teclado=0;
  93.                 }
  94.         }
  95. }

Quiero dejarlo como una librería para futuros usos, por eso preferí dejar el antirebote y todo lo demás en la misma rutina de interrupción en lugar de en el main. También tomé la idea original de redpic de usar una constante para definir las teclas del teclado, así como también lo estaba haciendo diploko... por cierto, qué será de diploko, que dió origen al hilo??  :?  :shock:

Bueno cualquier sugerencia para pulir más el código es bienvenida!
Y pues como siempre digo, nos leemos!  :mrgreen:
"Por la presunción solo se ocasiona una lucha, pero con los que consultan juntos hay sabiduría" (Proverbios 13:10).
Visita Mi Sitio Web

Desconectado Diploko

  • PIC10
  • *
  • Mensajes: 9
Re: Problema con teclado e Interrupcion RB en CCS y 16F877
« Respuesta #18 en: 16 de Noviembre de 2010, 16:15:50 »
Hola! aquí estoy!,
Gracias a los 2 por seguir interesados en la lectura del teclado mediante interrupción y no escribía nada porque no tenía nada más válido que lo existente para aportar a la conversación pero no lo he dejado de lado el asunto ni mucho menos... no os librareis de mí tan facilmente jeje.

No he probado tu programa en Proteus porque no lo tengo ni instalado... (lo tengo anotado como tarea pdte).
Donde sí acabo de probar este último código que has puesto es en una "protoboard" y siento decirlo pero no funciona. Del cableado no es porque con el código inicial que puse sí funciona, pero claro, sin interrupción...
Hay un par de detalles que he corregido en tu código porque creo que hacen falta:
- habilitar las resistencias pull-ups en el port_b
- cambiar la configuración del tris_b no es 0xff si no 0x86 tal y como indica el datasheet.
Pero con estos y otros cambios sigue sin funcionar  :?.

El programa que estoy casi acabando manejo entradas y salidas de pulsos, analógicas, 6 dispositivos en I2C... hay cosas que me cuestan pero gracias al las conversaciones existentes de este foro voy avanzando sin problemas excepto con esto de la interrupción del teclado  :x. Este programa tiene que funcionar si o si y si no lo consigo (en breve) mediante interrupción acabaré haciendo la gran chapuza de poner otro pic solo para el teclado y que éste genere una interrupción externa al pic principal controlando tb la detección de "tecla mantenida" para acelerar los cambios de parámetros. Esto ya lo he probado y vá como un fuego! pero desde luego es una chapuza que hasta me da verguenza comentarla  :oops:...

Ánimo lo conseguiremos! A ver si puedes hacer el pequeño montaje en una protoboard y lo compruebas y si hay alguien que tenga ya solucionado y probado este problema (con un PIC y en CCS) que se apiade de nosotros!

Salu2!


Desconectado firepic

  • Colaborador
  • PIC24H
  • *****
  • Mensajes: 1130
    • JC Servicios
Re: Problema con teclado e Interrupcion RB en CCS y 16F877
« Respuesta #19 en: 16 de Noviembre de 2010, 17:01:54 »
Qué bueno saber que estás ahí diploko!  :)

Lamentablemente tenía tiempo alejado de los pics y ahorita no tengo ni micro ni teclado para probar...
A mí cuando me funcionan las cosas en proteus generalmente me funcionan en físico salvo que falten algunos detalles que proteus no toma en cuenta, como los fuses y ese tipo de cosas...

Te sugiero que añadas al programa en la rutina de interrupción unas líneas que prendan y apaguen un led, eso para saber si el micro está ejecutando la interrupción... eso tiene que funcionar, yo he probado antes esa interrupción en RB con CCS y me ha funcionado perfecto... cuando te funcione lo de la interrupción pues lo demás debería funcionar automáticamente...

Por cierto, qué circuito estás usando? Porque si no tienes el proteus instalado entonces no pudiste ver el diagrama que te coloqué...
Ahí te lo adjunto en imagen...

Lo del trisb si fue una burrada de error  :D ... pero en todo caso no afectaría porque si te fijas bien estoy usando la instrucción set_tris_b del ccs.

Recuerda que al programa que te mandé tienes que cambiarle los fuses, yo le puse 20MHz, y tú estás trabajando con un cristal de 4MHz...
A ver si AngelGris u otra persona si puede probarlo en físico y nos echa una mano...

Ok nos leemos!  :mrgreen:
"Por la presunción solo se ocasiona una lucha, pero con los que consultan juntos hay sabiduría" (Proverbios 13:10).
Visita Mi Sitio Web

Desconectado Diploko

  • PIC10
  • *
  • Mensajes: 9
Re: Problema con teclado e Interrupcion RB en CCS y 16F877
« Respuesta #20 en: 16 de Noviembre de 2010, 18:04:16 »
Hola firepic!
Pues la verdad es que daba por supuesto que tendríamos el mismo esquema.... la diferencia es que yo no estoy usando resistencias externas, uso las pull-up internas del pic que por cierto éstas creo que estan conectadas a + en vez de a gnd.
Pero tanto dá, sigue sin funcionar de una forma u otra hace cosas sin sentido, con tus resistencias entra en interrupción constantemente y solo reacciona a las 2 filas de abajo y con las pull-up solo entra en interrupción cuando pulsas una tecla de las 2 filas de abajo y el printf responde con la tecla "14" siempre....

Este es tu código con el pic que tengo ahora montado 16F873:

Código: C
  1. ///////////////////////////////////////////////
  2. //             lee un teclado 4x4                //
  3. //   y envia al pc por puerto serial         //
  4. ///////////////////////////////////////////////
  5.  
  6. #include <16f873.h>
  7. #fuses XT,NOWDT,NOPROTECT,NOLVP,PUT,NOBROWNOUT
  8. #define Tx PIN_C6
  9. #define Rx PIN_C7
  10. #use delay (CLOCK=4000000)
  11. #use rs232 (BAUD=19200,XMIT=Tx,RCV=Rx,bits=8)
  12. #use fast_io(A)
  13. #use fast_io(B)
  14.  
  15. #byte port_b=0x06      
  16. #byte tris_b=0x86      
  17. #byte port_c=0x07      
  18. #byte tris_c=0x87      
  19.  
  20.  
  21. boolean flag_teclado;
  22. int tecla,fila,columna;
  23.  
  24. /********************************
  25. Esta Rutina permite rastrear el teclado
  26. y devuelve el valor de la tecla que se
  27. ha presionado
  28. ************************************/
  29. int captura(void)
  30. {
  31.         int const teclado[4][4] = {     {1,2,3,4},
  32.                                                                 {5,6,7,8},
  33.                                                                 {9,10,11,12},
  34.                                                                 {13,14,15,16}   };
  35.         int tecla,lectura,i;
  36.  
  37.         for(i=0;i<4;i++)
  38.         {
  39.                 output_b(0);
  40.                 bit_set(port_b,i);
  41.                 lectura = port_b & 0xf0;
  42.                 switch(lectura)
  43.                 {
  44.                         case 0b00010000: columna=0;
  45.                         fila=i;
  46.                         break; 
  47.                         case 0b00100000: columna=1;
  48.                         fila=i;
  49.                         break;
  50.                         case 0b01000000: columna=2;
  51.                         fila=i;
  52.                         break;
  53.                         case 0b10000000: columna=3;
  54.                         fila=i;
  55.                         break;
  56.                         }
  57.                 }
  58.                 tecla = teclado[fila][columna];
  59.                 return(tecla);
  60. }
  61.  
  62. /***************************************
  63. Rutina de Interrupción.
  64. - Antirebote.
  65. - Llama a rutina "captura" para saber la tecla presionada.
  66. - Activa la bandera "flag_teclado" a usar en el main o en otra parte del programa.
  67. ***************************************/
  68.  
  69. #INT_RB
  70. void tecla_presionada()
  71. {
  72.         // Para comptrobar que entra en la interrupcion
  73.         output_bit(PIN_C0,1);
  74.        
  75.         int lectura_1,lectura_2;
  76.        
  77.         lectura_1 = port_b & 0b11110000;                        // Lee portb4:7 y lo guarda en lectura_1
  78.         delay_ms(10);                                                           // AntiRebotes: Espero 10ms.
  79.         lectura_2 = port_b & 0b11110000;                        // Vuelvo a leer el puerto.
  80.        
  81.         if(lectura_1==lectura_2 && lectura_1!=0)        // Si el valor es igual y distinto de 0
  82.         {                                                                                       // es porque en realidad se presiona una tecla.
  83.                 tecla = captura();
  84.                 flag_teclado=1;
  85.         }
  86.        
  87.         set_tris_b(0xf0);
  88.         output_b(0x0f);
  89.         clear_interrupt(INT_RB);       
  90. }
  91.  
  92. void main()
  93. {
  94.         printf("Inicio main\n");
  95.        
  96.         set_tris_b(0xF0);              
  97.         set_tris_c(0x00);                      
  98.        
  99.         port_b=0;
  100.         port_c=0;
  101.        
  102.         port_b_pullups(true);
  103.        
  104.         enable_interrupts(INT_RB);
  105.         enable_interrupts(GLOBAL);
  106.        
  107.         printf("Inicio bucle\n");
  108.        
  109.         while(TRUE)
  110.         {
  111.                 if(flag_teclado==1)
  112.                 {
  113.                         printf("Tecla presionada: %i\n\r",tecla);
  114.                         flag_teclado=0;
  115.                 }
  116.                
  117.                 delay_ms(500);                          // Para que me dé tiempo a ver el led activado
  118.                 output_bit(PIN_C0,0);           // Desactivo led
  119.                
  120.         }
  121. }

Si este código te funciona en Proteus se me quitan las ganas de instalarlo jeje  ;-).

Gracias y salu2!

Desconectado AngelGris

  • Colaborador
  • PIC24H
  • *****
  • Mensajes: 2480
Re: Problema con teclado e Interrupcion RB en CCS y 16F877
« Respuesta #21 en: 16 de Noviembre de 2010, 19:27:39 »
Hola! aquí estoy!,
Gracias a los 2 por seguir interesados en la lectura del teclado mediante interrupción y no escribía nada porque no tenía nada más válido que lo existente para aportar a la conversación pero no lo he dejado de lado el asunto ni mucho menos... no os librareis de mí tan facilmente jeje.

..........

- habilitar las resistencias pull-ups en el port_b
- cambiar la configuración del tris_b no es 0xff si no 0x86 tal y como indica el datasheet.
Pero con estos y otros cambios sigue sin funcionar  :?.

............


  Para el programa que hizo FirePic, el tris tiene que estar configurado como él lo muestra (0xF0). Y con respecto a las resistencias del pull-up no son necesarias ya que es el nibble bajo el que va a generar el estado alto en las distintas salidas. Y sí son necesarias las resistencias de pull-down para asegurar que cuando ninguna tecla esté presionada haya un estado bajo en todos los pines del nibble alto del puerto B.

  En el main, antes del whle, es conveniente hacer "1" todas las salidas del nibble bajo del puerto B.
De vez en cuando la vida
nos besa en la boca
y a colores se despliega
como un atlas

Desconectado firepic

  • Colaborador
  • PIC24H
  • *****
  • Mensajes: 1130
    • JC Servicios
Re: Problema con teclado e Interrupcion RB en CCS y 16F877
« Respuesta #22 en: 17 de Noviembre de 2010, 15:14:34 »
Diploko prueba más bien haciendo un "toggle" en la interrupción, de esa manera podrás saber realmente cuándo entra o no a la interrupción... encendiendo en al rutina de interrupción y apagando en el while no lo veo muy bueno...

Código: C
  1. ///////////////////////////////////////////////
  2. //             lee un teclado 4x4                //
  3. //   y envia al pc por puerto serial         //
  4. ///////////////////////////////////////////////
  5.  
  6. #include <16f873.h>
  7. #fuses XT,NOWDT,NOPROTECT,NOLVP,PUT,NOBROWNOUT
  8. #define Tx PIN_C6
  9. #define Rx PIN_C7
  10. #use delay (CLOCK=4000000)
  11. #use rs232 (BAUD=19200,XMIT=Tx,RCV=Rx,bits=8)
  12. #use fast_io(A)
  13. #use fast_io(B)
  14.  
  15. #byte port_b=0x06      
  16. #byte tris_b=0x86      
  17. #byte port_c=0x07      
  18. #byte tris_c=0x87      
  19.  
  20.  
  21. boolean flag_teclado;
  22. int tecla,fila,columna;
  23.  
  24. /********************************
  25. Esta Rutina permite rastrear el teclado
  26. y devuelve el valor de la tecla que se
  27. ha presionado
  28. ************************************/
  29. int captura(void)
  30. {
  31.         int const teclado[4][4] = {     {1,2,3,4},
  32.                                                                 {5,6,7,8},
  33.                                                                 {9,10,11,12},
  34.                                                                 {13,14,15,16}   };
  35.         int tecla,lectura,i;
  36.  
  37.         for(i=0;i<4;i++)
  38.         {
  39.                 output_b(0);
  40.                 bit_set(port_b,i);
  41.                 lectura = port_b & 0xf0;
  42.                 switch(lectura)
  43.                 {
  44.                         case 0b00010000: columna=0;
  45.                         fila=i;
  46.                         break; 
  47.                         case 0b00100000: columna=1;
  48.                         fila=i;
  49.                         break;
  50.                         case 0b01000000: columna=2;
  51.                         fila=i;
  52.                         break;
  53.                         case 0b10000000: columna=3;
  54.                         fila=i;
  55.                         break;
  56.                         }
  57.                 }
  58.                 tecla = teclado[fila][columna];
  59.                 return(tecla);
  60. }
  61.  
  62. /***************************************
  63. Rutina de Interrupción.
  64. - Antirebote.
  65. - Llama a rutina "captura" para saber la tecla presionada.
  66. - Activa la bandera "flag_teclado" a usar en el main o en otra parte del programa.
  67. ***************************************/
  68.  
  69. #INT_RB
  70. void tecla_presionada()
  71. {
  72.         int lectura_1,lectura_2;
  73.         lectura_1 = port_b & 0b11110000;                        // Lee portb4:7 y lo guarda en lectura_1
  74.         delay_ms(10);                                                           // AntiRebotes: Espero 10ms.
  75.         lectura_2 = port_b & 0b11110000;                        // Vuelvo a leer el puerto.
  76.         if(lectura_1==lectura_2 && lectura_1!=0)        // Si el valor es igual y distinto de 0
  77.         {                                                                                       // es porque en realidad se presiona una tecla.
  78.                 tecla = captura();
  79.                 // Para comptrobar que entra en la interrupcion
  80.                 output_toggle(PIN_C0);
  81.                 flag_teclado=1;
  82.         }
  83.        
  84.         set_tris_b(0xf0);
  85.         output_b(0x0f);
  86.         clear_interrupt(INT_RB);       
  87. }
  88.  
  89. void main()
  90. {
  91.         printf("Inicio main\n");
  92.         set_tris_b(0b11110000); //nible alto entradas, nible bajo salidas.             
  93.         set_tris_c(0b10000000); //el bit 7 es recepción (Rx)                  
  94.         port_b_pullups(false); //no se usarán las pullups, usa las resistencias de 1k o 10k a GND.
  95.         port_b=0x0f; //ESENCIAL: coloca el nible bajo del puerto b a 1, para que pueda monitorear todas las filas del teclado.
  96.         port_c=0;      
  97.         enable_interrupts(INT_RB);
  98.         enable_interrupts(GLOBAL);
  99.         printf("Inicio bucle\n");
  100.         while(TRUE)
  101.         {
  102.                 if(flag_teclado==1)
  103.                 {
  104.                         printf("Tecla presionada: %i\n\r",tecla);
  105.                         flag_teclado=0;
  106.                 }
  107.                
  108.         }
  109. }

Bueno compañero sigue probando, no te desanimes que lo lograrás!!  :wink:
Generalmente para que algo nuevo te funcione con los pics tienes que grabar y probar no menos de unas cuantas decenas de veces!  :D

Ánimo y no dejes de publicar tus resultados! Nos leemos!  :mrgreen:

"Por la presunción solo se ocasiona una lucha, pero con los que consultan juntos hay sabiduría" (Proverbios 13:10).
Visita Mi Sitio Web

Desconectado AngelGris

  • Colaborador
  • PIC24H
  • *****
  • Mensajes: 2480
Re: Problema con teclado e Interrupcion RB en CCS y 16F877
« Respuesta #23 en: 17 de Noviembre de 2010, 16:02:56 »
Les cuento, hice las pruebas físicas sobre un 16f628A porque no tengo otro. Con el primer programa que subí funcionó bien, luego tomé el de FirePic y lo adapté a HiTech, lo probé y también me funcionó bien.

Por las dudas aquí les dejo el código tal cual lo grabé al pic.

Código: C
  1. #include <htc.h>
  2.  
  3. __CONFIG (LVPDIS & WDTDIS & MCLRDIS & INTIO);
  4.  
  5. #include "Def16f62xa.h"                 // algunas definiciones propias para esta familia de PICs
  6. #define PIC_CLK 4000000         // defino la velocidad de trabajo
  7. #include "delayhd.h"                    // rutinas de retardo
  8.  
  9. #define set_tris_b(x)   TRISB=x
  10. #define output_b(x)             PORTB=x
  11. #define set_tris_a(x)   TRISA=x
  12. #define output_a(x)             PORTA=x
  13.  
  14.  
  15. /************************************************************************************************
  16. Todos esos include y define son para poder trabajar con el pic, estoy usando el compilador HiTech
  17. pero tratando de dejar el código lo más parecido posible a CCS
  18.  
  19. Hay que adaptar la cabecera y parte del programa para que trabaje correctamente con CCS
  20.  
  21. También la línea __CONFIG (xxxx) hay que cambiarla por el tipo soportado por CCS
  22. **************************************************************************************************/
  23.  
  24.  
  25.  
  26. unsigned char flag_teclado = 0; // variable para saber si se presionó una tecla
  27. unsigned char tecla_pulsada;
  28.  
  29. /*****************************************
  30.   Rutina de delay de aproximadamente 10mS
  31. para usar como anti-rebote
  32. ******************************************/
  33. void AntiRebote (void)
  34. {
  35.   unsigned char tiempo;
  36.  
  37.   for (tiempo = 40; tiempo > 0; tiempo--)
  38.   {
  39.     DelayUs (250);
  40.   }
  41. }
  42.  
  43. /************************************************
  44.  Esta es la rutina que devuelve la tecla pulsada
  45. Los valores devueltos van de 1 a 16
  46. *************************************************/
  47. unsigned char captura(void)
  48. {
  49.   unsigned char teclado[4][4] = {1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16};
  50.   int tecla,lectura,i;
  51.   unsigned char fila, columna;
  52.  
  53.   for(i=0;i<4;i++)
  54.   {
  55.     output_b(0);
  56.  
  57. //    bit_set(port_b,i);
  58.  
  59.     PORTB = (1 << i);                   // utilizo esto en lugar de bit_set, porque Hitech no tiene dicha funcion
  60.     lectura = PORTB & 0xf0;
  61.     switch(lectura)
  62.     {
  63.       case 0b00010000: columna=0;
  64.                        fila = i;
  65.                        break;
  66.       case 0b00100000: columna=1;
  67.                        fila = i;
  68.                        break;
  69.       case 0b01000000: columna=2;
  70.                        fila = i;
  71.                        break;
  72.       case 0b10000000: columna=3;
  73.                        fila = i;
  74.                        break;
  75.     }
  76.   }
  77.   tecla = teclado[fila][columna];
  78.   return(tecla);
  79. }
  80.  
  81.  
  82. /****************************************************************
  83.  Esta es la rutina de atención de interrupción que permite Hitech
  84. hay que cambiarla y adaptarla al formato de CCS
  85. ******************************************************************/
  86. void interrupt isr (void)
  87. {
  88.   unsigned char temporal;
  89.  
  90.   temporal = PORTB & 0xF0;
  91.   if (temporal != 0)
  92.   {
  93.     AntiRebote();
  94.         temporal = PORTB & 0xF0;
  95.     if (temporal != 0)
  96.         {
  97.           flag_teclado = 1;  // si hay tecla pulsada activo el flag
  98.       tecla_pulsada = captura();
  99.     }
  100.   }
  101.   PORTB = 0x0F;                 // todo el nibble bajo del puerto B en "1"
  102.   temporal = PORTB;             // leo el puerto B para que ya no exista condición de cambio
  103.   RBIF = 0;                             // borro el flag de cambio de RB. (Adaptar a CCS)
  104.  
  105. /*
  106.   No deshabilito ni vuelvo a habilitar las interrupciones por que
  107. de ello ya se encarga el compilador. Adaptar a CCS si es necesario
  108. */
  109.  
  110. }
  111.  
  112.  
  113. void main (void)
  114. {
  115.   //setup_adc (ADC_OFF);
  116.   setup_comparator (NC_NC_NC_NC);
  117.   set_tris_a (0);                                       // Puerto A como salida
  118.   output_a (0);                                         // todo en 0
  119.   set_tris_b (0b11110000);                      // Nibble alto como entrada, nibble bajo como salida
  120.   output_b (0x0F);                                      // Todas las salidas en 1
  121.   RBIF = 0;                                                     // borro el flag que indica cambio en RB4..RB7
  122. /*
  123.  Creo que en CCS se usa clear_interrupt (INT_RB)
  124. */
  125.   enable_interrupt (INT_RB);            // habilito interrupción por cambio
  126.   enable_interrupt (GLOBAL);            // habilito todas las interrupciones
  127.   while (1)
  128.   {
  129.     if (flag_teclado == 1)                      // si se presionó alguna tecla...
  130.     {
  131.       output_a (tecla_pulsada); // la muestro en formato binario por el puerto A
  132.       flag_teclado = 0;
  133.     }
  134.   }
  135. }
De vez en cuando la vida
nos besa en la boca
y a colores se despliega
como un atlas