Programació en mpasm 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.

#include <p16F690.inc>
	__config (_INTRC_OSC_NOCLKOUT&_WDT_OFF&_PWRTE_OFF&_MCLRE_OFF&_CP_OFF&_BOR_OFF&_IESO_OFF&_FCMEN_OFF)
	cblock 0x20	; Zona de memòria de dades habitual
Visualit		; Una variable on guardem el que mostraran els LED
	endc
	cblock 0x70	; Zona de memòria de dades que no depèn del banc triat
W_Copia			; Guardarà el contingut de W durant la interrupció
ST_Copia		; Guardarà STATUS durant la interrupció
	endc
	org 0
	goto	Inici		; Saltem al lloc on hi ha el programa principal
	nop			; Zona de memòria de programa que no utilitzem
	nop
	nop
Interrup
	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	INTCON,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	INTCON,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	STATUS,RP0	; Tria el banc 1
	movlw	b'10000110'	; 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
	clrf	TRISC		; Posa tots els bits del port C com a sortida
	bcf	STATUS,RP0	; Tria el banc 0
	clrf	Visualit	; Posa Visualit a 0
	movlw	b'10100000'	; 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

Observem que la part repetitiva del programa principal (inicialització apart) 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.

#include <p16F690.inc>
	__config (_INTRC_OSC_NOCLKOUT&_WDT_OFF&_PWRTE_OFF&_MCLRE_OFF&_CP_OFF&_BOR_OFF&_IESO_OFF&_FCMEN_OFF)
	cblock 0x20	; Zona de memòria de dades habitual
Visualit		; Una variable on guardem el que mostraran els LED
	endc
	cblock 0x70	; Zona de memòria de dades que no depèn del banc triat
W_Copia			; Guardarà el contingut de W durant la interrupció
ST_Copia		; Guardarà STATUS durant la interrupció
	endc
	org 0
	goto	Inici		; Saltem al lloc on hi ha el programa principal
	nop			; Zona de memòria de programa que no utilitzem
	nop
	nop
Interrup
	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	INTCON,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	INTCON,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	STATUS,RP0	; Tria el banc 1
	movlw	b'10000110'	; 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
	clrf	TRISC		; Posa tots els bits del port C com a sortida
	bcf	STATUS,RP0	; Tria el banc 0
	clrf	Visualit	; Posa Visualit a 0
	movlw	b'10100000'	; Activem GIE i T0IE
	movwf	INTCON		; Activa les interrupcions globals i la de Timer0
Bucle
	goto	Bucle		; Repetim-ho...
	end

 

 

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