martedì 15 gennaio 2013

PIC16F628A e il Timer0

Ecco di seguito una traduzione delle parti più rilevanti del datasheet, viene descritto l'utilizzo del timer0 con collegamento al clock di sitema.



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
       
;*****************************************************************************************
; 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