Programació en pic-as del PIC 16F690

Referència Trucs Perifèrics   Recursos CITCEA
Tutorial Exemples Projectes   Inici

Exemple IT - Interrupció per Timer 0

A l'Exemple TM hem fet servir un temporitzador per a comptar el temps però era el propi programa que estava pendent de si el temporitzador habia assolit el valor o no. Ara farem que el temporitzador generi una interrupció quan arribi a zero. Serà a la funció d'interrupció on incrementarem el valor del comptador.

PROCESSOR 16F690
#include <xc.inc>
config FOSC = INTRCIO, WDTE = OFF, PWRTE = OFF, MCLRE = OFF, CP = OFF
config CPD = OFF, BOREN = OFF, IESO = OFF, FCMEN = OFF
; Zona de memòria de dades habitual
Visualit EQU 0x20  ; Una variable on guardem el que mostraran els LED
;
; Zona de memòria de dades que no depèn del banc triat
W_Copia EQU 0x70  ; Guardarà el contingut de W durant la interrupció
ST_Copia EQU 0x71  ; Guardarà STATUS durant la interrupció
PSECT code, class=CODE, delta=2, abs
main:  ; Adreça 0 h
  goto	Inici  ; Saltem al lloc on hi ha el programa principal
  nop  ; Zona de memòria de programa que no utilitzem
  nop
  nop
Interrup:  ; Adreça 4 h
  movwf W_Copia  ; Copiem l'acumulador a W_Copia
  swapf STATUS,w  ; Copiem STATUS a l'acumulador permutant els nibbles
  clrf STATUS  ; Posa a 0 i així segur que el banc és el 0
  movwf ST_Copia  ; Guarda STATUS permutat a ST_Copia
  btfss T0IF  ; Mira si Timer0 ha arribat a zero
                     ; Si hi ha arribat, no fa la instrucció següent
  goto FiInt  ; Si la interrupció no és del Timer0 no fem res
              ; Només havíem activat les interrupcions de Timer0
              ; Però, en general, és bo comprovar que l'origen
              ; de la interrupció és el que esperem
Timer0:  ; Programa corresponent a Timer0
  bcf T0IF  ; Si ha arribat, desactivem el bit
  incf Visualit,f  ; Incrementem Visualit
FiInt:
  swapf ST_Copia,w  ; Copia permutant ST_Copia a l'acumulador
  movwf STATUS  ; I ho passa a STATUS recuperant el valor d'abans
                ; de la interrupció
  swapf W_Copia,f  ; Permuta els bits de W_Copia
  swapf W_Copia,w  ; Torna a permutar els bits de W_Copia
                   ; i els guarda a l'acumulador sense variar STATUS
  retfie  ; Torna al programa principal, on s'havia quedat
Inici:
  bsf RP0  ; Tria el banc 1
  movlw 10000110B  ; Configuració de Timer0
                   ; Com a temporitzador basat en rellotge
                   ; 110 - Factor d'escala de 128
                   ; I resistències de pull-up desactivades (valor per defecte)
  movwf OPTION_REG  ; Ho guarda al registre de configuració del Timer0
  movlw 11110000B  ; Posa les potes dels LED com a sortida
  movwf TRISC  ; I la resta com a entrada
  bcf RP0  ; Tria el banc 0
  clrf Visualit  ; Posa Visualit a 0
  movlw 10100000B  ; Activem GIE i T0IE
  movwf INTCON  ; Activa les interrupcions globals i la de Timer0
Bucle:
  swapf Visualit,w  ; Permuta els nibbles i ho posa a l'acumulador
  movwf PORTC  ; I ho posa als LED
  goto Bucle  ; Repetim-ho...
END main

Observem que la part repetitiva del programa principal (inicialització a part) només té dues instruccions. En un programa més complet en podria tenir moltes més però el temporitzador ens garantiria que la variable s'incrementa en el temps prefixat.

Una opció alternativa seria la del programa següent en la que l'actualització dels LED està també a la funció d'interrupció. Així garantim que la cadència dels LED és la fixada. Observem que ara el programa principal ja no té cap instrucció dins el bucle.

PROCESSOR 16F690
#include <xc.inc>
config FOSC = INTRCIO, WDTE = OFF, PWRTE = OFF, MCLRE = OFF, CP = OFF
config CPD = OFF, BOREN = OFF, IESO = OFF, FCMEN = OFF
; Zona de memòria de dades habitual
Visualit EQU 0x20  ; Una variable on guardem el que mostraran els LED
;
; Zona de memòria de dades que no depèn del banc triat
W_Copia EQU 0x70  ; Guardarà el contingut de W durant la interrupció
ST_Copia EQU 0x71  ; Guardarà STATUS durant la interrupció
PSECT code, class=CODE, delta=2, abs
main:  ; Adreça 0 h
  goto	Inici  ; Saltem al lloc on hi ha el programa principal
  nop  ; Zona de memòria de programa que no utilitzem
  nop
  nop
Interrup:  ; Adreça 4 h
  movwf W_Copia  ; Copiem l'acumulador a W_Copia
  swapf STATUS,w  ; Copiem STATUS a l'acumulador permutant els nibbles
  clrf STATUS  ; Posa a 0 i així segur que el banc és el 0
  movwf ST_Copia  ; Guarda STATUS permutat a ST_Copia
  btfss T0IF  ; Mira si Timer0 ha arribat a zero
                     ; Si hi ha arribat, no fa la instrucció següent
  goto FiInt  ; Si la interrupció no és del Timer0 no fem res
              ; Només havíem activat les interrupcions de Timer0
              ; Però, en general, és bo comprovar que l'origen
              ; de la interrupció és el que esperem
Timer0:  ; Programa corresponent a Timer0
  bcf T0IF  ; Si ha arribat, desactivem el bit
  incf Visualit,f  ; Incrementem Visualit
  swapf Visualit,w  ; Permuta els nibbles i ho posa a l'acumulador
  movwf PORTC  ; I ho posa als LED
FiInt:
  swapf ST_Copia,w  ; Copia permutant ST_Copia a l'acumulador
  movwf STATUS  ; I ho passa a STATUS recuperant el valor d'abans
                ; de la interrupció
  swapf W_Copia,f  ; Permuta els bits de W_Copia
  swapf W_Copia,w  ; Torna a permutar els bits de W_Copia
                   ; i els guarda a l'acumulador sense variar STATUS
  retfie  ; Torna al programa principal, on s'havia quedat
Inici:
  bsf RP0  ; Tria el banc 1
  movlw 10000110B  ; Configuració de Timer0
                   ; Com a temporitzador basat en rellotge
                   ; 110 - Factor d'escala de 128
                   ; I resistències de pull-up desactivades (valor per defecte)
  movwf OPTION_REG  ; Ho guarda al registre de configuració del Timer0
  movlw 11110000B  ; Posa les potes dels LED com a sortida
  movwf TRISC  ; I la resta com a entrada
  bcf RP0  ; Tria el banc 0
  clrf Visualit  ; Posa Visualit a 0
  movlw 10100000B  ; Activem GIE i T0IE
  movwf INTCON  ; Activa les interrupcions globals i la de Timer0
Bucle:
  goto Bucle  ; Repetim-ho...
END main

 

 

Llicència de Creative Commons
Aquesta obra d'Oriol Boix està llicenciada sota una llicència no importada Reconeixement-NoComercial-SenseObraDerivada 3.0.