TODOPIC

Microcontroladores PIC => Primeros pasos - Iniciación a los microcontroladores => Mensaje iniciado por: cimi2020 en 12 de Noviembre de 2020, 15:34:48

Título: PROGRAMACION EN ASSEMBLER - INTERRUPCION POR RB0
Publicado por: cimi2020 en 12 de Noviembre de 2020, 15:34:48



Dicho este contexto, me gustaria pedirles ayuda para realizar una actividad basada en el microcontrolador PIC16F628A.-

- La actividad es bastante sencilla: se trata de un circuito con un pulsador conectado al terminal RB0 y dos LEDs conectados uno al terminal RB1 y otro al terminal RB2.
- Les comparto un link de una captura del circuito para que puedan verlo --> https://ibb.co/YT9S2N1
- De todas maneras les adjunto tambien un zip con el archivo del circuito y del .asm, por si las dudas.

Las consignas son la siguientes:
En base a un circuito compuesto por un PIC16F628A con un pulsador en el terminal RB0 y un led en los terminales RB1 y RB2 desarrollar los programas que permitan:
a) Prender ambos leds cuando se presione el botón.
b) Prender los leds cuando se presione y botón y apagarlos cuando se presione de nuevo.
c) Realizar la siguiente secuencia a medida que se presiona el botón: prender RB1, prender RB2, apagar RB1, apagar RB2.
d) Idem punto [c] con interrupción por RB0.


Ahora bien, con los puntos a, b y c no he tenido ningun problema en entender cómo se hace, el inconveniente que tengo es el de realizar el punto d, que básicamente pide lo mismo que el punto c:
- presiono el boton: se enciende el primer led (rb1)
- vuelvo a presionar el boton: se enciende el segundo led (rb2)
- vuelvo a presionar el boton: se apaga el primer led (rb1)
- vuelvo a presionar el boton: se apaga el segundo led (rb2)

Honestamente me cansé de googlear y buscar en foros cómo funciona el asunto de las interrupciones y no poder comprender la lógica, así que si podrían ayudarme a resolver ese ultimo que falta les estaría muy agradecido, y de paso podré entender como funciona y cómo se desarrolla el codigo.


Les comparto el codigo tal cual me quedo hasta el punto C, para que puedan verlo y en base a eso decirme qué hace falta agregar:

Código: ASM
  1. #INCLUDE    <P16F628A.INC>
  2.                 __CONFIG    3F10
  3.  
  4. ;--------------------------------------PUNTO 2-C---------------------------------------
  5.  
  6. cont     equ    0x20
  7. cont1    equ    0x21
  8. cont2    equ    0x22
  9.  
  10.                 ORG             0X00
  11. inicio
  12.                 BSF             STATUS, RP0
  13.                 BCF             OPTION_REG, NOT_RBPU                    ; habilito el pulsador
  14.                 MOVLW           b'00000001'                             ; activo el pulsador ubicado en RB0
  15.                 MOVWF           TRISB
  16.                 BCF             STATUS, RP0
  17.                 CLRF            PORTB
  18.                 CALL            espera_encendido1
  19.                 CALL            espera_encendido2
  20.                 CALL            espera_apagado1
  21.                 CALL            espera_apagado2
  22.                 GOTO            inicio
  23.  
  24.  
  25.  
  26. ;----------------------ESPERAS------------------------
  27. espera_encendido1
  28.                 btfsc           PORTB, 0
  29.                 goto            espera_encendido1
  30.                 call            demora_250ms
  31.                 btfsc           PORTB, 0
  32.                 goto            espera_encendido1
  33.                 bsf             PORTB, 2
  34.                 return
  35. espera_encendido2
  36.                 btfsc           PORTB, 0
  37.                 goto            espera_encendido2
  38.                 call            demora_250ms
  39.                 btfsc           PORTB, 0
  40.                 goto            espera_encendido2
  41.                 bsf             PORTB, 1
  42.                 return
  43. ;----------------------------------------------------
  44. espera_apagado1
  45.                 btfsc           PORTB, 0
  46.                 goto            espera_apagado1
  47.                 call            demora_250ms
  48.                 btfsc           PORTB, 0
  49.                 goto            espera_apagado1
  50.                 bsf             PORTB, 2
  51.                 return
  52. espera_apagado2
  53.                 btfsc           PORTB, 0
  54.                 goto            espera_apagado2
  55.                 call            demora_250ms
  56.                 btfsc           PORTB, 0
  57.                 goto            espera_apagado2
  58.                 bsf             PORTB, 1
  59.                 return
  60. ;-----------------------------------------------------
  61.  
  62.  
  63.  
  64. ;----------------------DEMORAS------------------------
  65. delay_1ms      
  66.                 movlw           .250
  67.                 movwf           cont
  68. loop1           nop
  69.                 decfsz          cont,f
  70.                 goto            loop1
  71.                 return
  72.                                                                        
  73.  
  74. demora_20ms
  75.                 movlw           .20
  76.                 movwf           cont1
  77. loop2           call            delay_1ms
  78.                 decfsz          cont1,f
  79.                 goto            loop2
  80.                 return
  81.  
  82. demora_250ms
  83.                 movlw           .250
  84.                 movwf           cont2
  85. loop3           call            delay_1ms
  86.                 decfsz          cont2,f
  87.                 goto            loop3
  88.                 return
  89.                
  90.                
  91.                 END

- Sé que hay otras instrucciones que tengo que agregar al inicio del codigo cuando voy a utilizar interrupcion externa por RB0, pero sinceramente no sé en qué orden colocarlas dentro del codigo que ya tengo, les comparto esas instrucciones que las copié tal cual del ppt que nos dio el profesor:

Código: ASM
  1. ;-------------Instrucciones a usar para trabajar con interrupcion por RB0---------------
  2.  
  3. ;Al utilizar interrupciones debemos definir nuestra rutina de interrupción.
  4. ;Es una buena práctica que esto se haga al inicio del código de la siguiente manera:
  5.  
  6.                 org     0x00
  7.                 goto    inicio
  8.                 org     0x04
  9.                 bcf     INTCON, GIE     ; inhabilito las interrupciones globales
  10.                 bcf     INTCON, INTF    ; bajo el flag de la interrupción
  11.                 bsf     PORTB, RB0      ; realizo la rutina, en este caso prender el LED
  12.                 bsf     INTCON, GIE     ; habilito nuevamente las interrupciones
  13.                 retfie                  ; Return especial para las rutinas de interrupción
  14.  
  15.  
  16. ;El programa principal quedaría conformado únicamente por la configuración de los puertos
  17. ;y las interrupciones, ya que el encendido del LED se hace en la interrupción:
  18.  
  19. Inicio          bsf     INTCON,GIE              ; habilito las interrupciones globales
  20.                 bsf     INTCON,INTE             ; habilito la interrupción por RB0
  21.                 bsf     STATUS,RP0              ; me muevo al Banco 1
  22.                 movlw   b'00000001'             ; configuro el TRISB: RB0 entrada y el resto salida
  23.                 movwf   TRISB
  24.                 bcf     STATUS, RP0             ; regreso al Banco 0
  25.                 goto    $                       ; esto indica que se hace un loop en la misma posición
  26.                 end

Esto ultimo es toda la informacion que nos dio para trabajar con interrupcio por RB0. Así que si puede ayudarme a resolver este problema como dije antes les voy a estar muy agradecido

Desde ya muchas gracias!
Título: Re:PROGRAMACION EN ASSEMBLER - INTERRUPCION POR RB0
Publicado por: KILLERJC en 12 de Noviembre de 2020, 17:31:20
Te explico como funciona la interrupcion..

El microcontrolador al resetearse comienza en la direccion 0x0000 (vector de reset), de allí uno configura los puertos, interrupciones, etc, y como paso final activa las interrupciones.

Luego como todo programa tiene un main, o un loop infinito, el cual va a estar ejecutandose continuamente. Supongamos que tenes este programa y las direcciones que ocupan las instrucciones, voy a intentar simplificarlo:

Código: ASM
  1. MAIN:
  2.    BSF PORTB,5            ;Direccion de la instruccion 0x100
  3.    CALL DELAY            ;Direccion de la instruccion 0x101
  4.    BCF PORTB,5            ;Direccion de la instruccion 0x102
  5.    CALL DELAY            ;Direccion de la instruccion 0x103
  6.    GOTO MAIN            ;Direccion de la instruccion 0x104

Si esta activada la interrupcion al momento de que el micro detecta una, guarda la direccion donde se estaba ejecutando y salta al vector interrupcion. Por ejemplo digamos que estaba en el BCF del programa de arriba (ya lo ejecuto), entonces guarda el 0x103 en un registro interno al micro. Y salta a la direccion 0x0004 que es el vector de reset.

En el momento que llega alla, desactiva las interrupciones, Aca vos vas a tener que revisar cual es la interrupcion que se activo (leyendo los flags) y actuar en consecuencia, una ves finalizada tu rutina limpias la bandera y salis de la interrupcion con un RETFIE, la difernecia entre este y un return es que ademas activa nuevamente las interrupciones. Y devuelve al contador de programas ( PCL ) el valor 0x103. continuando el main desde donde lo dejo..

Como es tan rapido, parece como si estuvieran ejecutandose en "paralelo". Y los podrias considerar casi independientes uno de otro.

Y esta es la esencia de la interrupcion.

Hay otras cosas que tener en cuenta:

- Los registros STATUS y W no se guardan, asi que es necesario guardarlos al comienzo de la interrupcion y luego reponerlos al final de la interrupcion para que el programa principal no cambie en nada.
- Nunca deberias poner delays en una interrupcion, siempre tiene que ser lo mas rapido posible, a no ser que no te importe lo que esta en el main, Ya que como dije mientras estas en la interrupcion las interrupciones estan deshabilitadas! Y si tenes grandes demoras, otras interrupciones se pueden superponer, por ejemplo, podrian llegar 2 caracteres por la UART y debido a que esta trabado en la interrupcion de tu boton, no las atenderia. El programa seria:


Código: ASM
  1. org     0x00
  2.                 goto    Inicio
  3.                 org     0x04
  4.                 ; Aca agregar las instrucciones de guardar W y STATUS
  5.                 btfss   INTCON, INTF    ; pregunto si es por el RB0 la interrupcion
  6.                 goto   fin_interrupcion
  7.                 bcf     INTCON, INTF    ; limpio el flag de la interrupción
  8.                 ;Aca tu rutina de encender lo que deba encederse o apagar.
  9.  
  10. fin_interrupcion:
  11.                 ; Aca agregar las instrucciones de volver a su estado original W y STATUS
  12.                 retfie                  ; Return especial para las rutinas de interrupción
  13.  
  14. Inicio        
  15.                 bsf     STATUS,RP0              ; me muevo al Banco 1
  16.                 movlw   b'00000001'             ; configuro el TRISB: RB0 entrada y el resto salida
  17.                 movwf   TRISB
  18.                 bcf     STATUS, RP0             ; regreso al Banco 0
  19.  
  20.                 ; Siemrpe al ultimo esto, primer habilito los modulos, limpio la banderas y luego habilito el global
  21.                 bsf     INTCON,INTE             ; habilito la interrupción por RB0
  22.                 bcf     INTCON, INTF            ; bajo el flag de la interrupción
  23.                 bsf     INTCON,GIE              ; habilito las interrupciones globales
  24.  
  25.  
  26. main:
  27.                 goto    $                       ; Tu loop infinito
  28.                 end

Q&A que te pueden surgir:
- ¿Dónde puedo conseguir el codigo para guardar el W y el STATUS sin que se modifiquen estos?
   EN el datasheet del micro busca por W_TEMP y seguramente esta el codigo, algunos hasta guardan el registro PCLATH

- ¿Por que mi profesor no nos dijo de este codigo?
  Por que si observas en tu main, o loop principal, no tenes NADA, es decir no vas a cambiar W, no vas a depender del valor de alguna bandera, entonces tiene poca o ninguna importancia usar este codigo, pero es buena practica enseñarselos para que lo tengan en cuenta.

- ¿Por que desactivo las interrupciones y las volvió a habilitar?
  Por que no conoce como funciona el nucleo del microcontrolador. Al entrar a la interrupción se desactiva, y si buscas por la instrucción RETFIE en el datasheet, vas a ver que no solo hace como un RETURN sino que ademas pone un 1 en GIE.

- ¿Por que mi profesor no lee con el BTFSS/C si es la flag activada la correcta?
  Seguramente por que es el unico modulo que tenes activo la interrupcion, entonces si entra a la interrupcion no queda mas que es esa. Si tuvieras varias harias algo asi:

Código: ASM
  1. ;Guardo W y STATUS
  2. BTFSC FLAG_INT_1
  3. CALL  INT_1_RESPUESTA
  4. BTFSC FLAG_INT_1
  5. CALL  INT_1_RESPUESTA
  6. BTFSC FLAG_INT_1
  7. CALL  INT_1_RESPUESTA
  8. ;Reponer W y STATUS
  9. RETFIE

- ¿Porque limpias las banderas antes de activarlo?
 Precaucion, ya que las banderas pueden estar en 1, debido a que ocurrio un flanco mientras nosotros estabamos configurando los puertos. Entonces para no tomar como un error un posible flanco en ese momento, limpiamos y comenzamos desde ese punto a escuchar por interrupciones.

- ¿Que pasa si no limpio el flag?
  Apenas sale de la interrupcion, al ejecutarse el RETFIE y activar nuevamente la interrupcion global, accede NUEVAMENTE a la interrupcion.

- Al estar desactivadas las interrupciones, ¿Que pasa con interrupciones que ocurran en ese momento?
  Lo mismo que antes, los flags van a cambiar a 1, pero no van a ser atendidos, cuando salga de la otra interrupcion y se activen la interrupcion global, al tener alguna flag en 1 (y obviamente habilitada para ese modulo) va a re-entrar a la interrupcion.

- ¿Las flags pueden estar en 1 sin activar las interrupciones?
  SI, nada evita que las flags cambien a 1. Pero sino estan activas las interrupciones del modulo Y global no va a saltar al vector de interrupcion

PD: Perdon por todos los horrores ortográficos, es que lo hago rápido mientras tengo un tiempito libre.
PD2:
Citar
los explica de una forma bastante superficial incluyendo los apuntes que él mismo preparó.
No se en que nivel estas. Soy docente de secundaria, pero no de electronica, sino de matematica y Fisica, no te imaginas el dolor de cabeza que es desarrollar todo para que luego no te lo lean o te digan "no entiendo". Incluso con clases virtuales. Por supuesto esto no es valido para todos los alumnos.


Cualquier otra pregunta es bienvenida.
Título: Re:PROGRAMACION EN ASSEMBLER - INTERRUPCION POR RB0
Publicado por: cimi2020 en 12 de Noviembre de 2020, 19:08:44
-muy buena explicacion!!

-desde ya que MIL gracias por tomarte este tiempo de explicarme con ejemplos y adelantarte con posibles dudas!

-voy a leerlo y bien desmenuzar cada cosa que dijiste asi voy entendiento, tengo que ir a mi ritmo ya que esta materia para mi es nueva (estoy en primer año de lic en sistemas, esta materia se
llama arquitectura de computadoras)

-necesitaba mucho esta explicacion de como funcionan las interrupciones y cual es su sentido, ya que de lo que me dijiste, en mis apuntes lo tenia explicado medio por arriba y se me hacia muy abstracto en mi cabeza la forma de proceder de este mecanismo

-te cuento que luego de publicar mi duda segui investigando un poco mas y pude lograr lo mas basico, que es hacer que los leds queden encendidos luego de presionar el boton, y el codigo me quedo de esta manera:
Código: ASM
  1. #INCLUDE    <P16F628A.INC>
  2.                 __CONFIG    3F10
  3.  
  4. #define         LED1                    portb,2         ; defino un led en el pin 2
  5. #define         LED2                    portb,1         ; defino un led en el pin 1
  6. #define         BANK1   bsf             status,RP0      ; instruccion para ir al banco 1
  7. #define         BANK0   bcf             status,RP0      ; instruccion para ir al banco 0
  8.  
  9. AUXW            equ             0x20
  10. AUXSTATUS       equ             0x21
  11.  
  12.                 ORG             0x00
  13.                 goto            inicio
  14.  
  15. ;----------------------------------------
  16. ;Programo la interrupción ENCENDIDO:
  17.  
  18.                         ORG             0x04
  19.                         bcf             INTCON, GIE             ; inhabilito las interrupciones globales
  20.                         bcf             INTCON, INTF            ; bajo el flag de la interrupción
  21.  
  22.                         movwf   AUXW                    ; guardo el valor de w en un registro auxiliar
  23.                         movf    STATUS,w
  24.                         movwf   AUXSTATUS               ; guardo el valor del STATUS en un registro auxiliar
  25.                         movf    AUXSTATUS,w             ; regreso el valor del STATUS
  26.                         movwf   STATUS
  27.                         movf    AUXW,w                  ; regreso el valor de w
  28.  
  29.                         bsf     LED1                            ; prender el LED 1
  30.                         bsf     LED2                            ; prender el LED 2
  31.                         BSF     INTCON, GIE                     ; habilito nuevamente las interrupciones
  32.                         retfie
  33.  
  34. ;----------------------------------------
  35. ;Programo la interrupción APAGADO:
  36.  
  37. ;                       ORG             0x05
  38. ;                       bcf             INTCON, GIE             ; inhabilito las interrupciones globales
  39. ;                       bcf             INTCON, INTF            ; bajo el flag de la interrupción
  40. ;
  41. ;                       movwf   AUXW                    ; guardo el valor de w en un registro auxiliar
  42. ;                       movf    STATUS,w
  43. ;                       movwf   AUXSTATUS               ; guardo el valor del STATUS en un registro auxiliar
  44. ;                       movf    AUXSTATUS,w             ; regreso el valor del STATUS
  45. ;                       movwf   STATUS
  46. ;                       movf            AUXW,w                  ; regreso el valor de w
  47. ;
  48. ;                       bcf             LED1                            ; apago el LED 1
  49. ;                       bcf             LED2                            ; apago el LED 2
  50. ;                       BSF     INTCON, GIE                     ; habilito nuevamente las interrupciones
  51. ;                       retfie
  52. ;----------------------------------------
  53.  
  54.  
  55.  
  56. ;Programa principal:
  57. Inicio
  58.                         bsf     INTCON,GIE                              ; habilito las interrupciones globales
  59.                         bsf     INTCON,INTE                             ; habilito la interrupción por RB0
  60.                         BANK1                                                   ; selección del banco 1
  61.                         BCF     OPTION_REG, NOT_RBPU    ; habilito el pulsador en RB0
  62.                         MOVLW   b'00000001'
  63.                         MOVWF   TRISB                                   ; pongo el RB0 como entrada
  64.                         BANK0                                                   ; selección de banco 0
  65.                         CLRF    PORTB                                   ; apago los leds
  66.                         goto    $
  67.  
  68.                         end
  69.  
  70. ;espera_encendido1;-------------------
  71. ;                       btfsc   PORTB, 0
  72. ;                       goto    espera_encendido1
  73. ;                       call    demora_250ms
  74. ;                       btfsc   PORTB, 0
  75. ;                       goto    espera_encendido1
  76. ;                       bsf     PORTB, 2
  77. ;                       return
  78. ;espera_encendido2;------------------
  79. ;                       btfsc   PORTB, 0
  80. ;                       goto    espera_encendido2
  81. ;                       call    demora_250ms
  82. ;                       btfsc   PORTB, 0
  83. ;                       goto    espera_encendido2
  84. ;                       bsf     PORTB, 1
  85. ;                       return
  86. ;------------------------------------
  87.  
  88. ;espera_apagado1;--------------------
  89. ;                       btfsc   PORTB, 0
  90. ;                       goto    espera_apagado1
  91. ;                       call    demora_250ms
  92. ;                       btfsc   PORTB, 0
  93. ;                       goto    espera_apagado1
  94. ;                       bcf     PORTB, 2
  95. ;                       return
  96. ;espera_apagado2;--------------------
  97. ;                       btfsc   PORTB, 0
  98. ;                       goto    espera_apagado2
  99. ;                       call    demora_250ms
  100. ;                       btfsc   PORTB, 0
  101. ;                       goto    espera_apagado2
  102. ;                       bcf     PORTB, 1
  103. ;                       return
  104. ;------------------------------------
  105.  
  106. ;--------------RETARDOS--------------
  107. ;delay_1ms                                                     
  108. ;               movlw   .250                   
  109. ;               movwf   cont                   
  110. ;loop1          nop                                            
  111. ;               decfsz  cont,f                 
  112. ;               goto    loop1                  
  113. ;               return                         
  114. ;demora_20ms;-----------------------
  115. ;               movlw   .20                            
  116. ;               movwf   cont1                  
  117. ;loop2  call    delay_1ms              
  118. ;               decfsz  cont1,f                
  119. ;               goto    loop2                  
  120. ;               return                                 
  121. ;demora_250ms;----------------------
  122. ;               movlw   .250                   
  123. ;               movwf   cont2                  
  124. ;loop3          call    delay_1ms              
  125. ;               decfsz  cont2,f                
  126. ;               goto    loop3                  
  127. ;               return                                 
  128. ;------------------------------------

-segun pude entender sobre lo que me explicaste, solo con una interrupcion alcanza para hacer la rutina de encendido y apagado puede ser?? yo deje comentado lo de "interrupcion apagado" porque cuando lo pobre me tiraba error al compilar, claramente algo estaba haciendo mal...

-no me estaria saliendo lo de apagar los leds luego de prenderlos, calculo que habria que agregarlas instrucciones bsf LED1 y bsf LED2, dentro de la misma interrupcion? ahi es donde me trabe

-y lo de los delays me dijiste que van fuera de la interrupcion

-con respecto a lo que me dijiste de guardar los registros STATUS y W, puse lo siguiente dentro de la interrupcion:

Código: ASM
  1. movwf   AUXW                    ; guardo el valor de w en un registro auxiliar
  2.                         movf    STATUS,w
  3.                         movwf   AUXSTATUS               ; guardo el valor del STATUS en un registro auxiliar
  4.                         movf    AUXSTATUS,w             ; regreso el valor del STATUS
  5.                         movwf   STATUS
  6.                         movf    AUXW,w                  ; regreso el valor de w

-no se si es eso a lo que te referias, lo tenia en una de las filminas del ppt


PD: este profe que tenemos no explica mal, solo que tuvimos la mala suerte de que varias de sus clases cayeran dias feriados, lo que hizo que nos atrasemos con los contenidos, inclusive este ultimo tp que nos mando lo tuvo que "recortar" ya que no tuvimos el tiempo suficiente para que nos explique bien todos los temas, algunas cosas no llego a explicarlas y por eso no las considero en las tareas, pero bueno, imagino que es un dolor de cabeza realmente, mi mama es docente universitaria de programacion y tambien se vuelve loca con esta modalidad, inclusive hasta para corregir los parciales le lleva mucho mas tiempo que si fuera presencial! Este año fue complicado para docente como alumnos, pero bueno uno va aprendiendo y amoldandose con la experiencia  :)
Título: Re:PROGRAMACION EN ASSEMBLER - INTERRUPCION POR RB0
Publicado por: KILLERJC en 12 de Noviembre de 2020, 20:43:35
Citar
-segun pude entender sobre lo que me explicaste, solo con una interrupcion alcanza para hacer la rutina de encendido y apagado puede ser?? yo deje comentado lo de "interrupcion apagado" porque cuando lo pobre me tiraba error al compilar, claramente algo estaba haciendo mal...

Si, estaria todo dentro de una misma interrupcion, adentro de la interrupcion vas a tener que llevar algun registro para identificar dodne estas parado. Concretamente yo lo haria con tablas, te dejo un ejemplo al final.

Lo unico que tenes que ser consciente es que al programar en ASM cada micro es "distinto" y ni hablar si cambias de arquitecturas lo cual es MUCHO mas distinto. Por ejemplo entre un PIC16 y un PIC18 hay muchas diferencias. Pero que esto se soluciona un poco al ir a un lenguaje de alto nivel como C.

Citar
-con respecto a lo que me dijiste de guardar los registros STATUS y W, puse lo siguiente dentro de la interrupcion:

Serviria para otros registros, el problema es que vos estas intentando preservar las banderas del registro STATUS, y ejecutar intrucciones como MOVF que modifican la bandera Z rompen el proposito. Para la explicacion te invito a ver el datasheet del microcontrolador en cuestion:
http://ww1.microchip.com/downloads/en/DeviceDoc/40044G.pdf

En la pag. 118 tenes un resumen de todas las instrucciones, podes ver que las instrucciones MOVF modifica la bandera Z (cero) del registro STATUS. Si buscas por W_TEMP en ese documento encontras:

Código: ASM
  1. MOVWF W_TEMP
  2. SWAPF STATUS,W
  3. BCF STATUS,RP0
  4. MOVWF STATUS_TEMP
  5.  
  6. ; Aca codigo de la interrupcion
  7.  
  8. SWAPF STATUS_TEMP,W
  9. MOVWF STATUS
  10. SWAPF W_TEMP,F
  11. SWAPF W_TEMP,W
  12. RETFIE

Observaras que usar SWAPF que es una instrucción que cambia de lugar los bits[3:0], con los bits [7:4] y no modifica las banderas.


Citar
yo deje comentado lo de "interrupción apagado" porque cuando lo pobre me tiraba error al compilar,

Es obvio ya que:

Código: ASM
  1. ORG             0x04
  2.                         bcf             INTCON, GIE             ; inhabilito las interrupciones globales
  3.                         bcf             INTCON, INTF            ; bajo el flag de la interrupción

El ORG le dice la direccion desde donde poner las instrucciones, por lo tanto el primer BCF tiene direccion de memoria 0x04, y el segundo direccion de memoria 0x05, y asi con todas las instrucciones que siguen. Y luego.. tenes esto:

Código: ASM
  1. ORG             0x05
  2.                        bcf             INTCON, GIE             ; inhabilito las interrupciones globales
  3.                        bcf             INTCON, INTF            ; bajo el flag de la interrupción

Acordate que en el lugar 0x05, tenias el BCF anterior, y ahora queres ponerle este BCF, es decir poner 2 instrucciones en un mismo lugar de memoria.


Citar
-no me estaria saliendo lo de apagar los leds luego de prenderlos, calculo que habria que agregarlas instrucciones bsf LED1 y bsf LED2, dentro de la misma interrupcion? ahi es donde me trabe

Lee este codigo y pensalo

Código: ASM
  1. W_TEMP          EQU     0x20
  2. STATUS_TEMP     EQU     0x21
  3. ESTADO          EQU     0x22
  4.  
  5.  
  6.         ORG 0x00
  7.         GOTO    Inicio
  8.         ORG 0x04
  9.  
  10.         ; Guardado de W y STATUS
  11.         MOVWF W_TEMP
  12.         SWAPF STATUS,W
  13.         BCF STATUS,RP0
  14.         MOVWF STATUS_TEMP
  15.  
  16.         ;Aca el codigo de la interrupcion
  17.         BTFSS   INTCON, INTF
  18.         GOTO    Fin_Interrupcion
  19.         BCF     INTCON, INTF    ;Limpiamos
  20.  
  21.         MOVF    ESTADO, W       ;Comprobamos que nuestro registro no sea mayor o igual a 4
  22.         ANDLW   0x4             ; Ya que nuestra tabla tiene 4 entradas ( 0 a 3 )
  23.         BTFSS   STATUS,Z
  24.         CLRF    ESTADO          ; Si es 4, lo hacemos 0 antes de llamar a la tabla
  25.  
  26.         MOVF    ESTADO, W
  27.         CALL    Tabla  
  28.         MOVWF   PORTB
  29.         INCF    ESTADO, F
  30.        
  31.         ;Reponemos W y STATUS
  32.         SWAPF STATUS_TEMP,W
  33.         MOVWF STATUS
  34.         SWAPF W_TEMP,F
  35.         SWAPF W_TEMP,W
  36.         RETFIE
  37.  
  38.  
  39. Tabla:
  40.         ADDWF   PCL, F
  41.         RETLW   0x2     ;cuando W=0     0x2 = 0000 0010
  42.         RETLW   0x6     ;cuando W=1     0x6 = 0000 0110
  43.         RETLW   0x4     ;cuando W=2     0x4 = 0000 0100
  44.         RETLW   0x0     ;cuando W=3     0x0 = 0000 0000
  45.  
  46.  
  47.  
  48. ;Programa principal:
  49. Inicio
  50.  
  51.         BANK1                                           ; selección del banco 1
  52.         BCF     OPTION_REG, NOT_RBPU                    ; habilito el pulsador en RB0
  53.         MOVLW   b'00000001'
  54.         MOVWF   TRISB                                   ; pongo el RB0 como entrada
  55.         BANK0                                           ; selección de banco 0
  56.         CLRF    PORTB                                   ; apago los leds
  57.         CLRF    ESTADO                                  ; ESTADO = 0
  58.  
  59.         bsf     INTCON,INTE                             ; habilito la interrupción por RB0
  60.         bcf     INTCON,INTF                             ; habilito la interrupción por RB0
  61.         bsf     INTCON,GIE                              ; habilito las interrupciones globales
  62. Main:
  63.         goto    Main
  64.  
  65.         end

La tabla funciona de la siguiente manera.
El PC es el contador de programa (direccion de la instruccion a ejecutar), solo tenemos acceso al PCL directamente y la parte alta mediante el PCLATH pero solo algunas instrucciones.
Con el ADDWF yo puedo sumar valores al PCL, y asi hacer saltar tantas lineas como lo diga W.
Como yo llame con un CALL, tengo su correspondiente RETURN, pero el RETLW ademas devuelve un valor en W. Y este valor es el valor que quiero en el puerto.

Simple y sencillo... Te conviene simularlo paso a paso para entenderle.