In molti casi il programmatore desidera temporizzare il funzionamento del PIC con intervalli di tempo piuttosto lunghi (per esempio per far lampeggiare un LED). Abbiamo già visto come ciò possa essere ottenuto per mezzo di cicli di ritardo, cioè mediante una temporizzazione software. Questa soluzione, sebbene abbastanza semplice da realizzare, non è in generale la migliore, in quanto impegna continuamente il microcontrollore nell'esecuzione di cicli di ritardo.
Un'altra soluzione (temporizzazione hardware) consiste nell'utilizzare uno dei timer interni al PIC, programmato in modo tale da generare un interrupt allo scadere di ogni intervallo prefissato di tempo (per esempio ogni volta che si vuole accendere o spegnere un LED). Se si usano a questo scopo i timer a 8 bit (Timer0 o Timer2) si ha il problema che i tempi prodotti sono sempre piuttosto brevi. Per esempio usando Timer0 (ma lo stesso ragionamento vale per Timer2) con una frequenza di clock standard di 4 MHZ, si ha un periodo di incremento pari a 1 µs. Ciò significa che il timer si azzera (e genera un interrupt) ogni 256 µs. Anche programmando il prescaler al massimo valore (256) il massimo tempo che si ottiene è pari a 256*256 µs = 65 ms circa. Se si vogliono temporizzare tempi più lunghi, escludendo la possibilità di cambiare la frequenza del clock di sistema, l'unica soluzione consiste nell'effettuare un conteggio software del numero di interrupt generati e nell'eseguire una determinata azione (es. spegnere o accendere un LED) solo quando tale conteggio ha raggiunto il valore desiderato (dopodiché si azzera il contatore e si ricomincia il conteggio daccapo), come spiegato nella precedente lezione.
Una soluzione forse più semplice è quella di usare Timer1. Nel PIC16F690 questo timer ha 16 bit e dunque è in grado di contare fino a 65536. Se a ciò si aggiunge il prescaler (che permette di moltiplicare i tempi fino a un massimo di 8 volte), con questo timer (sempre facendo riferimento a un clock a 4 MHz) si possono ottenere tempi fino a 8*65536 µs = 0,52 s.
Inoltre, se anche questo tempo non fosse sufficientemente
lungo, c'è un'altra caratteristica che rende Timer1
particolarmente adatto allo scopo ed è il fatto di poter usare
come sorgente di clock non il clock di sistema, ma l'oscillatore
RC secondario
LFINTOSC da 31 kHz
interno al PIC (indipendentemente da quale sia l'oscillatore
selezionato come clock del PIC). In questo modo i tempi
raggiungibili arrivano fino a un massimo di circa 67 secondi.
La figura seguente riassume i principali registri di controllo di Timer1:
Il registro più importante per la programmazione di Timer1 è T1CON:
Senza entrare nei dettagli (per i quali si rimanda il lettore al manuale del PIC) i bit più importanti per i nostri scopi sono:
Vediamo ora un semplice esempio di programma che utilizza Timer1 per far lampeggiare una serie di LED ogni 0,5 secondi circa (usando il clock standard a 4 MHz). Il programma suppone che i LED siano collegati con i pin di PORTC:
#include <P16F690.inc>
__CONFIG _CP_OFF & _CPD_OFF & _BOR_OFF & _PWRTE_ON & _WDT_OFF & _INTRC_OSC_NOCLKOUT & _MCLRE_ON & _FCMEN_OFF & _IESO_OFF
;***** DEFINIZIONE DI REGISTRI GPR PER IL SALVATAGGIO DEL CONTESTO
W_TEMP EQU 0X7D
STATUS_TEMP EQU 0X7E
PCLATH_TEMP EQU 0X7F
;**********************************************************************
ORG 0X000 ; INIZIO MEMORIA DI PROGRAMMA
GOTO MAIN ; SALTA ALL'INIZIO DEL PROGRAMMA PRINCIPALE
;******************* INTERRUPT SERVICE ROUTINE *****************
ORG 0X004 ; INIZIO ROUTINE DI INTERRUPT
MOVWF W_TEMP ; SALVA W
; SALVATAGGIO REGISTRI DEL PIC
MOVF STATUS,W ; COPIA STATUS IN W
MOVWF STATUS_TEMP ; SALVA STATUS
MOVF PCLATH,W ; COPIA PCLATH IN W
MOVWF PCLATH_TEMP ; SALVA PCLATH
BANKSEL PIR1
BTFSC PIR1, TMR1IF ; CONTROLLA SE CI SONO INTERRUPT DA
TIMER1
CALL TIMER1INT
MOVF PCLATH_TEMP,W ;
RIPRISTINO REGISTRI DEL PIC
MOVWF PCLATH
MOVF STATUS_TEMP,W
MOVWF STATUS
SWAPF W_TEMP,F
SWAPF W_TEMP,W
RETFIE
; RETURN FROM INTERRUPT
;*******************************************************
; *************** SUBROUTINE PER FAR LAMPEGGIARE IL LED ************
TIMER1INT
BCF PIR1, TMR1IF ; CLEAR DEL FLAG DI INTERRUPT
MOVLW 0xFF
; INVERTE LO STATO DEI LED
XORWF PORTC,F
RETURN
; ***********************************************************
MAIN
; ABILITAZIONE DEGLI INTERRUPT
BANKSEL INTCON
BSF INTCON, GIE
BSF INTCON, PEIE
BANKSEL PIE1
BSF PIE1, TMR1IE
; PROGRAMMAZIONE DEL REGISTRO T1CON
BANKSEL T1CON
MOVLW b'00110001'
; PRESCALER 1:8
MOVWF T1CON
; PROGRAMMAZIONE DI PORTC
BANKSEL ANSEL
CLRF ANSEL
CLRF ANSELH
BANKSEL PORTC
CLRF PORTC ; LED SPENTI
INIZIALMENTE
BANKSEL TRISC
CLRF TRISC ; PORTC IN
OUTPUT
GOTO $ ; CICLO INFINITO (ATTESA DI INTERRUPT)
END
Sito realizzato in base al
template offerto da
http://www.graphixmania.it