Il modulo timer0 possiede le seguenti caratteristiche:
- timer/contatore ad 8bit -> 0-255
- possibilità di leggere e scrivere il valore del timer
- presenza di un prescaler a 8bit
- possibilità di collegarlo al clock interno o esterno
- genera un interrupt sull'overflow ovvero nel passaggio tra i valori da FFh a 00h
- selezione del fronte del clock esterno
Struttura interna del timer0 dal datasheet della Microchip

Azzerando il bit T0CS e settando il bit PSA del registro OPTION_REG il moduo timer0 (registro TMR0) viene incrementato ad ogni ciclo istruzione.
Nota: Quando viene scritto il registro TMR0 l'incremento viene inibito per due cicli istruzioni succesivi.
SOFTWARE PROGRAMMABLE PRESCALER
Il prescaler è un contatore ad 8bit che permette di rallentare la velocità del clock da 1:2 fino a 1:256.
E' possibile impostare via software un prescaler per il Timer0. Il prescaler è abilitato azzerando il bit PSA del registro OPTION_REG. Le 8 opzioni del prescaler sono da 1:2 fino a 1:256. I valori del prescaler sono selezionabili tramite i bit PS<2:0> di OPTION_REG. Ogni istruzione che scrive il registro TMR0 azzera il prescaler.
TIMER0 INTERRUPT
Il timer0 genera un'interrupt quando il registro TMR0 ha un'overflows dal valore FFh a 00h. Il bit interrupt flag T0IF del registro INTCON viene settato ogni volta che il registro TMR0 ha un'overflows, indipendentemente che l'interrupt Timer0 sia abilitato. Il bit T0IF può essere azzerato solo via software. L'interrupt Timer0 è abilitato settando il bit T0IE di INTCON.
SCRITTURA DEL FIRMWARE
Vediamo come configurare il modulo timer0 e come scrivere un firmware che generi un' onda quadra con frequenza di 500hz sul pin RB0.
Ricordarsi di abilitare anche il nit GIE del registro INTCON
Il calcolo del tempo impiegato a far scattare l'interrupt è il seguente:
(0x100-TMR0_RESET_VAL)*durata_ciclo_istruzioni*PRESCALER_VALUE+2*durata_ciclo_istruzioni
;*****************************************************************************************
; CONSTANT DEFINITIONS
;*****************************************************************************************
; /----------- WPUEN: PWeak Pull-up Enable bit = X
; |/---------- INTEDG: Interrupt Edge Select bit = X
; ||/--------- T0CS: TMR0 Clock Source Select bit = 0 = Internal
; ||| instruction cycle clock (FOSC/4)
; |||/-------- T0SE: TMR0 Source Edge Select bit = X
; ||||/------- PSA: Prescaler Assignment bit = 0 = Prescaler is
; ||||| assigned to the Timer0 module
; |||||///---- PS2:PS0: Prescaler Rate Select bits =
; |||||||| 010 = TMR0 Rate 1 : 8
; ||||||||
OPTION_REG_CFG EQU B'11010010'
T0_RESET_VAL EQU 0x83 ; interrupt ogni 1ms per clock a 4MHz e prescaler = 8
; ([0x100-0x83]*1us*8=1ms) (Formula imprecisa!!!!)
;*****************************************************************************************
; VARIABLE DEFINITIONS
;*****************************************************************************************
T0_reset EQU 0x2A
square_wave_out EQU 0x2B
;*****************************************************************************************
; VERSIONE: 1.0.0
; ULTIMA MODIFICA: 15.01.13
; INPUT: NONE
; OUTPUT: NONE
; inizializzazione del registro OPTION_REG,
; ripristino del valore di TMR0 e abilitazione
; dell'interrupt del timer0
;*****************************************************************************************
T0_init
;OPTION_REG = OPTION_REG_CFG // Prescaler Rate 1:8
;TMR0 = T0_reset;
;INTCON.TMR0IF = 0; // enable_interrupts(INT_TIMER0);
;TRISB.RB0 = 0; // imposto RB0 come pin di output
return
;TRISB.RB0 = 0; // imposto RB0 come pin di output
return
; VERSIONE: 1.0.0 ; ULTIMA MODIFICA: 15.01.13
; INPUT: NONE
; OUTPUT: NONE
;*****************************************************************************************
T0_isr
;TMR0 = T0_reset;
;square_wave_out = ~square_wave_out;
;INTCON.T0IF=0; //The interrupt flag bits must be cleared before
; //exiting the ISR to avoid repeated interrupts.
return
;*****************************************************************************************
; VERSIONE: 1.0.0
; ULTIMA MODIFICA: 15.01.13
; INPUT: NONE
; OUTPUT: NONE
;*****************************************************************************************
isr
; GIE bit is cleared
movwf w_temp ; save off current W register contents
movf STATUS,w ; move status register into W register
movwf status_temp ; save off contents of STATUS register
; Determine the source of the interrupt by polling the interrupt flag bits.
; if(TMR0IF==1) T0_isr
banksel INTCON
btfsc INTCON, T0IF
call T0_isr
; if(TMR1IF==1) T1_isr
banksel INTCON
btfsc INTCON, T1IF
call T1_isr
movf status_temp,w ; retrieve copy of STATUS register
movwf STATUS ; restore pre-isr STATUS register contents
swapf w_temp,f
swapf w_temp,w ; restore pre-isr W register contents
; GIE bit is setted
retfie
Per il 23.01.13:
- montare su bread bord il circuito dell'es1 presente in questo blog
- studiare (e stampare) le seguenti pagine del datasheet del PIC16F628A :
* pag 18 - DATA MEMORY MAP OF THE PIC16F627A AND PIC16F628A
* pag 24-26 - STATUS register, OPTION register, INTCON register
* pag 47-49 - TIMER0 MODULE
* pag 117-130 - INSTRUCTION SET SUMMARY
- creare un progetto con MPLAB basandosi sul presente progetto allegato
- completare il progetto MPLAB scrivendo il programma generi una onda quadra sul pin RB0 ad una frequenza di 500Hz
NOTA: il codice deve rispettare le convenzioni di scrittura utilizzate negli esempi precedentemente proposti e deve essere commentato adeguatamente
Buon lavoro!
Nessun commento:
Posta un commento