TODOPIC

Microcontroladores PIC => Almacén del Assembler => Mensaje iniciado por: VOLTIO en 08 de Marzo de 2016, 16:01:30

Título: Interrupcion por teclado para 16F877A
Publicado por: VOLTIO en 08 de Marzo de 2016, 16:01:30
Estimados amigos, gracias a este foro y dos personas en especial ( KILLERJC  y  Pinolillo16) pude entender y hacer funcionar un LCD con este micro.
Ahora quiero hacer que mientras el programa esta trabajando normalmente, cuando oprimo un boton deje de trabajar y entre en un menu nuevo para hacer otra cosa por ejemplo en mi caso un entrar a un menu para programar algo .
Espero se entienda lo que quiero hacer , subo diagrama y basandonos en el programa que puse como ejemplo.
Gracias
 - Tienes que ingresar para ver archivos adjuntos -
Título: Re:Interrupcion por teclado para 16F877A
Publicado por: Diego E. en 08 de Marzo de 2016, 16:43:48
Hola, yo estructuro mis programas de esta forma
Es una especie de multitarea, el programa está pasando constantemente por todas las rutinas que requiero, si ocurre un evento entra a la rutina y luego vuelve a al programa general,
si por condición de una tecla debe presentar un mensaje en el LCD en esta se guarda un código en una variable para que cuando llegue a la rutina del LCD lo presente, tengo por tiempo
real eventos que se realizan cada 0,5 ó 1 segundo, etc.

Código: C
  1. ////////////////////////Rutina general
  2. while(true)            
  3.         {
  4.                 restart_wdt();
  5.                
  6. ///////////////////////////////////////        
  7.                 bit_clear(col1);
  8.                 delay_us(100);
  9.  
  10.                 tecla_egreso();
  11.                 tecla_lb();
  12.                 tecla_confi();
  13.                 tecla_enter();
  14. /////////
  15.                 bit_set(col1);
  16.                 bit_clear(col2);
  17.                 delay_us(100);
  18.  
  19.                 tecla_libre();
  20.                 tecla_memorias();
  21.                 tecla_cero();
  22.                 tecla_salir();
  23. /////////
  24.                 bit_set(col2);
  25.                 bit_clear(col3);
  26.                 delay_us(100);
  27.  
  28.                 tecla_encendido();
  29.                 tecla_tiempo();
  30.                 tecla_p_ini();
  31.                 tecla_decre();
  32. /////////
  33.                 bit_set(col3);
  34.                 bit_clear(col4);
  35.                 delay_us(100);
  36.  
  37.                 no_existe_tecla();
  38.                 tecla_mover();
  39.                 tecla_modificar();
  40.                 tecla_incre();
  41.                
  42.                 bit_set(col4);
  43. ///////////////////////////////////////
  44.                 delay_us(100);
  45.                
  46.                 leer_peso_total();             
  47.                
  48.                 /////////////////////////////////////////
  49.                 if(res_con_menu != con_menu)
  50.                 {
  51.                         res_con_menu = con_menu;
  52.                         tiempo_menu = 0;
  53.                         switch(con_menu)
  54.                                 {
  55.                                         case 0: pantalla_ini(); break; 
  56.                                         case 1: menu_cero(); break;
  57.                                         case 2: menu_p_inicial(); break;
  58.                                         case 3: menu_m_peso(); break;
  59.                                         case 4: menu_configurar(); break;
  60.                                         case 8: menu_ver_memorias(); break;    
  61.                                         case 9: pantalla_alarmas(); break;                                                                                                                     
  62.                                 }
  63.                 }
  64.                 /////////////////////////////////////////              
  65.                 if(ban_05seg)
  66.                 {
  67.                         ban_05seg = 0;
  68.                
  69.                         conversion();
  70.                         conver_temperatura();
  71.                         fijar_cero();
  72.                         fijar_ini();
  73.                         fijar_modificar();             
  74.                        
  75.                 /////////////////////////////////////////
  76.  
  77.                 if(ban_1seg)
  78.                 {
  79.                         ban_1seg = 0;
  80.                         decrementar_tempo();
  81.                         salir_menu();
  82.                         comparar_hora();
  83.                         if(con_menu == 0)
  84.                         {
  85.                                 apagar_backligth();
  86.                                 ver_temperatura();
  87.                                 ver_hora(0xce);
  88.                                 if(!bit_test(ban_tempo)) {ver_fecha(0xa0);}                            
  89.                         }      
  90.                 }
  91.         }
  92. }

Saludos
Título: Re:Interrupcion por teclado para 16F877A
Publicado por: VOLTIO en 08 de Marzo de 2016, 17:08:00
Hola Diego pero tiene que ser en asm , sino estoy al horno ,jajajajaaj
gracias
Título: Re:Interrupcion por teclado para 16F877A
Publicado por: Diego E. en 08 de Marzo de 2016, 17:44:00
Pero el principio es el mismo, yo lo hacía antes en ASM, obviamente es más dispendioso, pero lo importante es el concepto de "multitarea"
Título: Re:Interrupcion por teclado para 16F877A
Publicado por: KILLERJC en 08 de Marzo de 2016, 20:10:59
Creo que antes de meternos con el programa que tenes VOLTIO, deberias crear un programa muy simple, es decir solo la interrupcion + loop principal ( tambien simple ), para entender el funcionamiento. Despues procedes a tratar de incorporarlo a tu programa.

En tu loop principal, encender y apagar un led, con una velocidad de 500ms encendido y 500ms apagado.
Tu interrupcion tiene que detener/poner en marcha lo del loop principal.

Trata de hacer eso.
Título: Re:Interrupcion por teclado para 16F877A
Publicado por: VOLTIO en 09 de Marzo de 2016, 13:40:32
Yo hice esto en mi programa , es bastante sencillo cuando arranca muestra un msj , cuando se oprime la tecla SW1 muestra en pantalla el msj ENTRANDO AL MENU, para luego seguir

; Subrutina "ServicioInterrupcion" -----------------------------------------------------
;
;
; Subrutina de servicio a la interrupción. Una vez apretado Menu muestra en pantalla ENTRADA A MENU
;
ServicioInterrupcion
call Retardo_20ms          ; Espera a que se estabilice el nivel de tensión.
btfss SW1                ; Comprueba si es un rebote.
goto FinInterrupcion      ; Era un rebote y por tanto sale.
CALL   MENSAJE_MENU      ; voy a ver el msj MENU
FinInterrupcion
bcf INTCON,INTF            ; Limpia flag de reconocimiento (INTF).
retfie                   ; Retorna y rehabilita las interrupciones (GIE=1).
 - Tienes que ingresar para ver archivos adjuntos -
Título: Re:Interrupcion por teclado para 16F877A
Publicado por: KILLERJC en 09 de Marzo de 2016, 18:06:26
Lo repito por que estas muy lejos de lo que es una interrupcion, y de comprender aunque sea lo basico:

Creo que antes de meternos con el programa que tenes VOLTIO, deberias crear un programa muy simple, es decir solo la interrupcion + loop principal ( tambien simple ), para entender el funcionamiento. Despues procedes a tratar de incorporarlo a tu programa.

En tu loop principal, encender y apagar un led, con una velocidad de 500ms encendido y 500ms apagado.
Tu interrupcion tiene que detener/poner en marcha lo del loop principal.

Trata de hacer eso.
Título: Re:Interrupcion por teclado para 16F877A
Publicado por: VOLTIO en 10 de Marzo de 2016, 13:42:36
Crees que me podran ayudar con ejemplos sobre proteus para entenderlo ?? tal como hicimos con lo anterior ?'


gracias
Título: Re:Interrupcion por teclado para 16F877A
Publicado por: KILLERJC en 10 de Marzo de 2016, 14:16:40
Pero esta ves no te voy a dar el codigo. Lo vas a tener que hacer vos.


Código: ASM
  1. ; Vectores de interrupcion
  2.  
  3. Setup:
  4.  
  5.         ;Configuracion de los modulos
  6.  
  7. Main:
  8.         ;Encendido y apagado del led
  9.  
  10.         GOTO    Main
  11.  
  12.  
  13. Interrupcion:
  14.         ;Guardo contexto ( STATUS, W , PCLATH )
  15.         ;Pregunto si el flag esta activo y actuo en consecuencia
  16.  
  17.         ;Devuelvo el contexto ( STATUS, W , PCLATH )
  18.         RETFIE
Título: Re:Interrupcion por teclado para 16F877A
Publicado por: VOLTIO en 10 de Marzo de 2016, 16:18:24
Mientras vos me subias la sugerencia yo empece con unas hojas que baje de la web a hacer algo, anda pero no me apaga el led , lo estoy entendiendo bastante mejor pero no se porque no se apaga el led cuando oprimo MENU .

ahi va lo que hice
 - Tienes que ingresar para ver archivos adjuntos -
Título: Re:Interrupcion por teclado para 16F877A
Publicado por: KILLERJC en 10 de Marzo de 2016, 17:43:35
Por si no quedo claro, te lo voy a repetir VOLTIO, al menos yo no voy a aplicarlo en el codigo que ya tenes realizado.
Si queres una ayuda de como entender lo que es una interrupcion entonces deberias crear y comenzar con un ejemplo muy sencillo.

Y es eso lo que te estoy pidiendo que realices. No por capricho mio, sino por que es la unica forma de realmente aprender y ver que lo que falla sea de eso y no por alguna "interaccion" con el programa que tenias antes.
Título: Re:Interrupcion por teclado para 16F877A
Publicado por: VOLTIO en 10 de Marzo de 2016, 18:16:00
lo deje lo mas sencillo posible, entonces le saco el lcd tambien ?? solo dejo el led y el pulsador ?
Título: Re:Interrupcion por teclado para 16F877A
Publicado por: KILLERJC en 10 de Marzo de 2016, 18:19:08
Comenza un ejemplo nuevo, un programa totalmente nuevo para solo la interrupcion. Luego cuando entiendas realmente lo que hace la interrupcion vas al programa con el LCD y lo agregas.
Título: Re:Interrupcion por teclado para 16F877A
Publicado por: VOLTIO en 10 de Marzo de 2016, 22:20:50
Como decia el CHAVO DEL 8  "bueno pero no te enojes" jajajaja aca hice hasta donde me da mi coco , pero no apago el led con el boton que esa es la meta con la interrupcion.
Pero noto en proteus que al oprimir el boton se ponen algunas lineas en amarillo no se que es
Título: Re:Interrupcion por teclado para 16F877A
Publicado por: VOLTIO en 11 de Marzo de 2016, 15:49:43
este es el diagrama

 - Tienes que ingresar para ver archivos adjuntos -
Título: Re:Interrupcion por teclado para 16F877A
Publicado por: KILLERJC en 11 de Marzo de 2016, 16:05:37
Comenza un ejemplo nuevo, un programa totalmente nuevo para solo la interrupcion. Luego cuando entiendas realmente lo que hace la interrupcion vas al programa con el LCD y lo agregas.

Respecto al diagrama esta bien, recorda que si activas los Pull-ups del puertoB podes omitir las resistencias esas.
Título: Re:Interrupcion por teclado para 16F877A
Publicado por: VOLTIO en 11 de Marzo de 2016, 18:54:55
y porque no me funciona ? podes ayudarme ? en el archivo anterior esta el asm que hice solo para esto
gracias
Título: Re:Interrupcion por teclado para 16F877A
Publicado por: KILLERJC en 11 de Marzo de 2016, 19:18:39
y porque no me funciona ? podes ayudarme ? en el archivo anterior esta el asm que hice solo para esto
gracias

No, en el archivo anterior hay codigo de LCD, hay delays que no se usan alli, hay muchas cosas que ni siquiera deben estar alli. Para ser un "programa nuevo" como te habia pedido. En resumen pase a hacerte el favor y eliminar todo lo que no necesitas. Aunque falta de completar varias cosas, algunas señaladas y otras no tanto :P


Código: ASM
  1. ;
  2. ;PROPIETARIO:                   RUBEN DARIO FIGUEREDO
  3. ;                                              
  4. ;FECHA:                                 10 DE MARZO DE 2016 15:49
  5. ;PROFESOR:                              FORO TODO PIC
  6. ;VERSION DEFINITIVA:            MICRO 16F877A
  7. ;GRABAR CON:                    WDT=                            OFF
  8. ;                                               POWER UP TIMER=         OFF
  9. ;                                               BROWN OUT DETECT=       OFF
  10. ;                                               CODE PROTECT=           ON
  11. ;**************************************************************************
  12.                                  list p=16f877a
  13.                      #include <p16f877a.inc>
  14.  
  15.  #define                FOSC    D'4000000'  
  16.  
  17. ;**************************************************************************************************************
  18. ;FUSIBLES DE PROGRAMACIÓN, EVITA TENER QUE ESCRIBIRLOS CADA VEZ QUE SE EJECUTA EL PROGRAMA WINPICPROG O IC-PROG
  19. ;*************************************************************************************************************
  20.  
  21. __CONFIG _BODEN_OFF & _CP_OFF & _WRT_OFF & _PWRTE_ON & _WDT_OFF & _XT_OSC & _DEBUG_OFF & _CPD_OFF & _LVP_OFF
  22.  
  23. ;*************************************************************************************************************
  24.  
  25. CBLOCK  0X20
  26.         TEMP1
  27.         TEMP2
  28.         W_TEMP
  29.         STATUS_TEMP
  30.         PCLATH_TEMP
  31.         ENDC
  32.  
  33. ;*****************************************************************************         
  34.  
  35.                 ORG             000H            ;VECTOR DE RESET
  36.                 GOTO    SETUP
  37.                 ORG             0X04            ;VECTOR DE INTERRUPCION
  38.  
  39.  
  40. ;**********************************************************************************************
  41. ;                       CONFIGURACION DE PUERTOS
  42. ;**********************************************************************************************
  43.  
  44. SETUP
  45.  
  46.                 BANKSEL         TRISA                   ;SUBO A BANCO1
  47.        
  48.                 MOVLW           B'00000110'     ;1 input, 0 output
  49.                 MOVWF           TRISA                   ;DESCARGO EN TRISA
  50.                 MOVLW           B'00000000'     ;1 input, 0 output
  51.                 MOVWF           TRISB                   ;DESCARGO EN TRISB
  52.                 MOVLW           B'00000000'     ;1 input, 0 output
  53.                 MOVWF           TRISC                   ;DESCARGO EN TRISD
  54.                 MOVLW           B'00000000'     ;1 input, 0 output
  55.                 MOVWF           TRISD                   ;DESCARGO EN TRISE
  56.                 MOVLW           B'00000000'     ;1 input, 0 output
  57.                 MOVWF           TRISE
  58.                
  59.                 MOVLW           .7
  60.                 MOVWF           ADCON1
  61.  
  62.  
  63.                 BANKSEL         PORTA                           ;BAJO A BANCO 0
  64.        
  65.                 CLRF            PORTA                   ;LIMPIO PORTA
  66.                 CLRF            PORTB                   ;LIMPIO PORTB
  67.                 CLRF            PORTC                   ;LIMPIO PORTC
  68.                 CLRF            PORTD                   ;LIMPIO PORTD
  69.                 CLRF            PORTE                   ;LIMPIO PORTE
  70.  
  71. ;****************************************************************************************************
  72. ;                       CONFIGURACION DE INTEERRUPCIONES
  73. ;****************************************************************************************************
  74.  
  75. CONF_INTERRUPCION
  76.  
  77.                 BSF INTCON,RBIE                         ; HABILITAR INTERRUPCION RBIE
  78.                 BCF INTCON,RBIF                         ; LIMPIAR LA BANDEERA DE INTERRUPCION
  79.                 BSF INTCON,GIE                  ; HABILITAR INTERRUPCION
  80.  
  81. ;******************************************************************************************************
  82. ;                       RUTINA PRINCIPAL PRENDE UN LED Y MUESTRA UN MENSAJE
  83. ;******************************************************************************************************
  84.  
  85. PRINCIPAL
  86.                 ;Aca crear el codigo del LED
  87.                 GOTO            PRINCIPAL
  88.  
  89. ;*****************************************************************************************
  90. ;                        RUTINA DE SERVICIO DE INTERRUCION
  91. ;*****************************************************************************************
  92.  
  93. ISR
  94.         ; Aca arreglar todo.
  95.                 BCF             INTCON,GIE                               ; DESHABLITAR INTERRUPCIONES
  96.        
  97. ;CHEQUEO BOTONES
  98.  
  99.                 BTFSS           MENU
  100.                 BCF                     LED
  101.                 CALL            DEMORA
  102.                 CALL            PRINCIPAL
  103.                
  104.  
  105. SALIDA_ISR
  106.  
  107.                 BCF                     INTCON,RBIF                             ; LIMPIA LA BANDERA DE INTERRUPCION
  108.                 BSF             INTCON,GIE                              ; HABILITAR INTERRUPCIONES
  109.                 RETFIE                                                          ; REGRESAR DE LA INTERRUPCION
  110.  
  111.        
  112.  
  113. DEMORA  
  114.  
  115.                 MOVLW           .255    ;CARGO 255 A W
  116.                 MOVWF           TEMP1   ;DESCARGO 4 EN GRAL1   
  117. BN              MOVLW           .255            ;CARGO 255 A W
  118.                 MOVWF           TEMP2   ;DESCARGO EN GRAL2
  119. NM              NOP                                     ;NOP, UN CICLO DE MÁQUINA, UN BYTE
  120.                 DECFSZ          TEMP2   ;DECREMENTO GRAL2, SALTO SI ES CERO
  121.                 GOTO            NM              ;VOY A NM
  122.                 DECFSZ          TEMP1   ;DECREMENTO GRAL1 SALTO SI ES CERO
  123.                 GOTO            BN              ;VOY A BN
  124.                 RETURN                          ;RETORNO
  125.  
  126.  
  127. END

En ese codigo, tenes los siguientes problemas:

- No tenes definido la instruccion en el vector de interrupcion, que te llevaria a la rutina de interrupcion.
- No guardas el contexto ( STATUS, W , PCLATH ) al entrar a la interrupcion ni lo repones cuando salis, esto podes buscarlo en el datasheet, busca por W_TEMP que seguro tenes el codigo.
- Activas la interrupcion dentro de la interrupcion, eso no se hace, el mismo RETFIE lo hace por si solo ( activa GIE ).
- Usas una demora dentro de la interrupcion
- Haces un CALL a la rutina Principal.. NO NO y NO, pensa la interrupcion como algo aislado, NUNCA pero NUNCA hagas eso. Por ahora lo que es de la interrupcion NUNCA deberia estar en el camino del programa Principal y viceversa. Una ves que entiendas mejor como es que funciona una interrupcion podes llegar a "mezclar un poco las cosas". Para que quede mas claro pensalo como 2 programas apartes, uno es la interrupcion y el otro es el principal, ninguno se pueden llamar entre uno u otros, solo usar registros.
- Al entrar a la interrupcion se dehsabilita por si sola la interrupcion global ( GIE ), por lo tanto el BCF esta por demas.
- Usaste un CALL a PRINCIPAL sin haber un RETURN. ( Aunque dije que era incorrecto hacer eso, lo que quiero apuntar es que si usas un CALL asegurate que en algun momento llegue a un RETURN).

Resolve estos problemas y luego podemos seguir  :mrgreen:
Título: Re:Interrupcion por teclado para 16F877A
Publicado por: VOLTIO en 11 de Marzo de 2016, 19:59:02
Bueno KILLERJC lo voy a intentar y comento .gracias !!!!!!!!!!!!!!!!!!!!!!!!!!