Durante una
interrupción el único registro que se salvaguarda en la pila, es el contador de
programa. La subrutina de atención a la interrupción puede alterar el contenido
de nuestros registros del microcontrolador. Por esta razón al iniciar la rutina
de atención a la interrupción es conveniente guardar el valor de nuestros
registros y restaurarlos antes de la instrucción retfie.
A simple vista,
guardar los datos y restaurarlos sin modificar los contenidos parece fácil, el
contenido de los registros W y STATUS deben guardarse primero y después los
demás datos que puedan variar su valores durante la interrupción.
Para dejar mas claro
esto, a continuación se expondrá la manera en que no esta correcto el guardado
de datos y la correcta.
ORG 0 ;Inicio del
programa
goto Inicio
ORG 4 ; Vector de interrupción
goto Serviciodeinterrupcion
Inicio
---------
Subrutina
“Serviciodeinterrupcion”
; Esta subrutina
puede alterar los registros, asi que debemos preservar su valor previo
CBLOCK
Guarda_W
Guarda_STATUS
Guarda_RegistroA
Guarda_ RegistroB
….
ENDC
;Ya se
preservaron los valores de W y STATUS
Serviciodeinterrupcion
movwf Guarda_W ;Guarda
W y STATUS
movf STATUS,W ;Esta
instrucción altera el registro STATUS
movwf Guarda_STATUS
movf RegistroA,W
movwf Guarda_RegistroA ;Guarda RegistroA alterado
movf RegistroB,W ;Guarda
RegistroB
movwf Guarda_RegistroB
…
; Aquí
va el resto de la rutina de atención
…
;Ahora
se deben restaurar los valores de los registros
movf Guarda_RegistroB,W ;Restaura
el contenido de B
movwf RegistroB
movf Guarda_RegistroA,W
movwf RegistroA ; Restaura el contenido de A
movf Guarda_STATUS,W ;Esta
instrucción ha alterado el contenido de
movwf STATUS ;STATUS
movf Guarda_W,W ;Esta
instrucción vuelve a alterar STATUS
bcf INTCON,INTF ;Limpia
la Flag para la interrupción
retfie ;Retorna a antes
de la interrupción
|
La parte del programa
anterior esta errónea ya que al mover un registro cualquiera al registro de
trabajo W corrompe el flag Z y modifica el registro STATUS, lo que se
recomiendo para evitar este tipo de problemas es lo siguiente:
;No se
puede usar la instrucción “movf STATUS,W” porque corrompe el contenido de
STATUS
Serviciodeinterrupcion
movwf Guarda_W ;Guarda
W y STATUS
swapf STATUS,W ;Asi
no se altera el registro STATUS
movwf Guarda_STATUS
movf RegistroA,W
movwf Guarda_RegistroA ;Guarda RegistroA
movf RegistroB,W ;Guarda
RegistroB
movwf Guarda_RegistroB
…
bcf STATUS,RP0 ;Asegurar
que trabajamos en el banco 0
; Aquí
va el resto de la rutina de atención
…
;Ahora
se deben restaurar los valores de los registros
movf Guarda_RegistroB,W ;Restaura
el contenido de B
movwf RegistroB
movf Guarda_RegistroA,W
movwf RegistroA ;
Restaura el contenido de A
swapf Guarda_STATUS,W ;Restaura
STATUS con su valor original
movwf STATUS
swapf Guarda_W,F ;Restaura
W como estaba antes
swapf Guarda_W,W
bcf INTCON,INTF ;Limpia
la Flag para la interrupción
retfie ;Retorna a antes
de la interrupción
|
La función de la instrucción “swapf STATUS, W” mueve los datos sin
afectar el registro STATUS, aunque antes del proceso los nibles se
intercambian, posteriormente son restaurados y esto sin afectar ninguna de las
banderas como la Z, evitando hacer “movf
STATUS,W” y no se altera la bandera Z.
No hay comentarios:
Publicar un comentario