Gestione dei ritardi
Generatore di onde quadre
 Il generatore di onde quadre consiste di un treno di onde luminose caratterizzate da un periodo il cui 50% il livello
logico è alto e il restante 50% è a livello logico basso.
 Fare ciò, significa gestire il tempo e quindi i ritardi sui pic
 Un metodo molto semplice e forse, un po’ banale, è quello di far lavorare la macchina avuoto senza far eseguire alcuna
operazione.
 L’istruzione per non far eseguire operazioni è nop.
 La routine è la seguente:
LIST p=16F628
include "P16F628.inc“ ; libreria dove sono definiti I registri del 16f628
org 0x0000
movlw 0x07
movwf CMCON ;tutti i comparatori sono disattivati. Le porte che sono multiplexate, fungono solo
;da I/O
bsf STATUS, RP0 ; viene posto a 1 il bit RP0 del registro Staus per selezionare il bank1
movlw b'00000000'
movwf TRISB ;portb come output
movwf TRISA ;porta come output
bcf STATUS, RP0 ; viene posto a 0 il bit RP0 del registro Staus per selezionare il bank0
Loop del programma
Loop movlw 0xff ; viene caricato il numero
;255 in formato esadecimale che tradotto un binario è 11111111
movwf PORTA ;porta è a livello logico alto
movwf PORTB ;portb è a livello logico alto
nop ; viene inserito un ritardo di 1 microsecondo
;perchè ogni ciclo macchina ha frequenza 1 Mhz
nop ; per 1 us la macchina non esegue operazioni
movlw 0x00 ; viene caricato lo zero
movwf PORTA ;porta e portb sono a livello logico basso
movwf PORTB
nop
nop
goto Loop
end
Nop
 Nop è l’istruzione che non fa eseguire alcuna operazione.
 A che cosa può servire?
 Fa lavorare il micro a vuoto per mantenere fisso lo stato di
un microcontrollore e non far cambiare stato.
 Quanto può durare un ritardo?
 Se la frequenza di clock è di 4 MHz, il periodo sarà di 0,25
us e il tempo macchina è 4*Tclock=1us
 Ogni ciclo macchina dura quindi 1 us se la frequenza di
clock è 4 MHz.
 Il ritardo ottenuto è quindi 2 us visto che sono state
introdotte due righe con l’istruzione nop
Senza libreria
 Se non avessimo inserito la libreria avremmo dovuto
dare delle direttive al compilatore:
PORTA EQU 0x05
PORTB EQU 0x06
TRISA EQU 0x05
TRISB EQU 0x06
STAUS EQU 0x03
RP0 EQU 0x05 ; bit 5 del registro status
CMCON EQU 0x1F
Riga programma Registro interessato Stato deI bit Registro
MOVLW 0X07 accumulatore 0 0 0 0 0 1 1 1
MOVWF cmcon cmcon 0 0 0 0 0 1 1 1
Bsf status,rp0 5 bit registro status 0 0 1 0 0 0 0 0
Movlw 0x00 accumulatore 0 0 0 0 0 0 0 0
Movwf trisa Trisa del bank1 0 0 0 0 0 0 0 0
Movwf trisb Trisb del bank1 0 0 0 0 0 0 0 0
Bcf status, rp0 5 bit registro status 0 0 0 0 0 0 0 0
Movlw 0xff accumulatore 1 1 1 1 1 1 1 1
Movwf porta Porta del bank0 1 1 1 1 1 1 1 1
Movwf portb Portb del bank0 1 1 1 1 1 1 1 1
nop Nessun registro
Movlw 0x00 accumulatore 0 0 0 0 0 0 0 0
Movwf porta Porta del bank0 0 0 0 0 0 0 0 0
Movwf portb Portb del bank0 0 0 0 0 0 0 0 0
Ritardo con una routine di ritardo
• Con pochi microsecondi di ritardo non possiamo renderci conto della
differenza tra i due livelli logici e, gestire un ritardo più grande, comporterebbe
la scrittura di un numero enorme di istruzioni nop.
• Un metodo più efficace è quello di inserire un valore in un registro GFR e,
decrementarlo.
• La macchina rimane nel suo stato fino a quando il registro non è zero
• Si passa alla istruzione successiva se tutto è nullo.
• Useremo quindi decfsz salta alla istruzione successiva se il risultato è nullo
• Il programma è il seguente:
LIST p=16F628
include "P16F628.inc“
count1 equ 0x0C ; registro generale
count2 equ 0x0D
org 0x00
Ritardo con una routine di ritardo
movlw 0x07
movwf CMCON ;pone I comparatori a 1
bsf STATUS, RP0 ;seleziona bank1
movlw b'00000000'
movwf TRISB
movwf TRISA
bcf STATUS, RP0 ;seleziona banco 0
clrf PORTA ;porta non viene mai usata
clrf PORTB
loop: call Delay
bsf PORTB, 7 ;pone il bit 7 a livello logico alto
call Delay
Ritardo con una routine di ritardo:
subroutine di ritardo
Spegni: bcf portb,7 ;pone a livello logico basso il bit 7
goto loop
Delay: movlw 0x0f
movwf conta2 ;pone il valore 15 in un GFR
movlw 0x0f
movwf conta1 ;pone il valore 15 in un GFR
Loop1: decfsz conta1 ;decrementa il registro e salta se zero
goto Loop1
Loop2: decfsz conta2 ;decrementa il registro e salta se zero
goto Loop2
return
end
Osservazioni
 Nel programma sono stati settati sia i registri porta e trisa
che non servono; non serve nemmeno il settaggio del
registro comcon che setta i comparatori. Se fosse stato
utilizzato tutto il registro trisa, sarebbe stato utile settare i
comparatori.
 Si noti che il ritardo sul cambio di stato di ogni porta è di
30 us perché il decremento di ciascun registro 0ch e 0dh
dura 15 cicli macchina e, ogni ciclo dura 1 us; 15 cicli durano
15 us. Siccome sono due registri da decrementare, il ritardo
sarà di 30 us
 Per fare un ritardo più grande, si possono settare a 1 al
massimo 8 bit di ciascun registro per un numero di cicli
massimi di decrementi pari a 255 us
esercizio
 Scrivere un programma che faccia accendere e
spegnere alternativamente 2 led e ciascuno con un
ritardo di 200 us
Osservazioni
 Quando si incontra l’istruzione goto oppure call
subroutine, si ha un salto e si interrompe il flusso del
programma per eseguire la linea programma o la
subroutine. Nella memoria programmi c’è una parte
riservata allo stack pointer in cui si inserisce l’indirizzo
in cui è stato interrotto il programma. Terminate le
istruzioni in cui il programma è saltato, lo stack
pointer fornisce l’indirizzo della memoria programma
dove ritornare
Registri
Riga programma Registri Bit
Movlw 0x07 w 0 0 0 0 0 1 1 1
Movwf cmcon Registro comparatore 0 0 0 0 0 1 1 1
Bsf status,rp0 Bit 5 di status 0 0 0 1 0 0 0 0
Movlw 0x00 w 0 0 0 0 0 0 0 0
Movwf trisb trisb 0 0 0 0 0 0 0 0
Bcf status,rp0 Bit 5 di status 0 0 0 0 0 0 0 0
Clrf portb portb 0 0 0 0 0 0 0 0
Call delay
Bsf portb,7 Bit 7 portb 1 0 0 0 0 0 0 0
Call delay
Goto loop
Delay
Riga programmi Registri Bit
Movlw 0x02 w 0 0 0 0 0 0 1 0
Movwf conta1 Registro 0x0c 0 0 0 0 0 0 1 0
Movlw 0x02 W 0 0 0 0 0 0 1 0
Movwf conta2 Registro 0x0d 0 0 0 0 0 0 1 0
Decfsz conta1 0x0c 0 0 0 0 0 0 0 1
Goto loop1
Decfsz conta1 0x0c 0 0 0 0 0 0 0 0
Decfsz conta2 0x0d 0 0 0 0 0 0 0 1
Decfsz conta2 0x0d 0 0 0 0 0 0 0 0
Return
Supponiamo di inserire un ritardo molto più piccolo
Ritorna all’ultima chiamata di subroutine.
Un tempo di ritardo più lungo
Delay: movlw 0x0f
movwf conta2 ;pone il valore 15 in un GFR
Loop2: movlw 0x0f
movwf conta1 ;pone il valore 15 in un GFR
Loop1: decfsz conta1 ;decrementa il registro e salta se zero
goto Loop1
decfsz conta2 ;decrementa il registro e salta se zero
goto Loop2
return
end
 Questa volta, per ogni decremento di conta2, si ritorna a
loop2
 Ogni decremento di conta2 genera 15 decrementi di conta1
 I decrementi terminano quando conta2 è zero
 Il tempo di ritardo è 255 us=15*15
Sorgenti di segnali
 Ogni microcontrollore lavora secondo un certo
sincronismo
 I segnali di sincronizzazione possono essere interni o
esterni
 Se esterni, viene applicato un generatore di impulsi ad
una certa frequenza su un determinato pin.
 Nel caso del pic16f628, il segnale viene applicato sul
pin 3
Prescaler e interrupt
Il pic 16f628 è dotato di un timer interno ad 8 bit.
Il registro timer0, registro del bank0 all’indirzzo 01h,
incrementa il proprio contenuto per ogni ciclo macchina
L’oscillatore interno del pic genera una frequenza f=4 MHz;
la frequenza di un qualsiasi segnale proveniente dal pic è
quindi di f/4=1 Mhz, frequenza macchina.
Il registro timer0 incrementa così il proprio contenuto con la
frequenza di 1 MHz
La frequenza di interruzione, frequenza di interrupt, si ha
quando il timer inizia a contare daccapo, cioè quando passa
da overflow a zero. Essendo il timer0 di 8 bit, l’interrupt si
ha ogni 28 -1 cicli macchina+1=256 contando anche il
passaggio da overflow a zero
Frequenza di interrupt
 La frequenza fi di interrupt si calcola dividendo la
frequenza macchina per 256: fi=f(osc)/(4*256)
 Si potrebbe cambiare la frequenza di interrupt con due
metodi:
 Inizializzando il timer con un valore Nt diverso da 0.
• È come accorciare la lunghezza del timer così impiegherà
meno tempo per andare in overflow
• La nuova frequenza fi di interrupt sarà: fi=f(osc)/4/(256-Nt)
 La frequenza di interrupt può cambiare se si inserisce un
prescaler, cioè un divisore di frequenza.
• Il prescaler è formato dai tre bit del registro option che si
trova all’indirizzo 81h, è cioè un registro di bank1
Esercizi per impostare l’interrupt
senza prescaler
1. Calcolare il periodo di interrupt se Nt=0
2. Calcolare il periodo e la frequenza di interrupt se
Nt=200
3. A quanto bisogna impostare Nt se si chiede che
fi=300 Hz
Registro Option
Bit 0 RBPU Disabilita o abilitai resistori interni di
pull up
0 disabilita
1 abilita
Bit 1 INTEDG Seleziona il fronte di salita di interrupt
su RB0/INT
0 fronte salita
1 fronte discesa
Bit 2 TOCS Seleziona il fronte di segnale di clock
del timer
0 clock interno
1 clock esterno
Bit 3 TOSE Seleziona il fronte del segnale per il
clock del timer su RA4/TOCKL
0 fronte di discesa
1 fronte di salita
Bit 4 PSA Assegna il prescaler l timer TMR0 o al
WDT
0 TMR0
1 WDT
Bit 5 PS2 Selezione il fattore di divisione per il TMR0
Bit 6 PS1
Bit 7 PS0
Un piccolo schema
Prescaler
Ps2 Ps1 Ps0 Divisore
0 0 0 2
0 0 1 4
0 1 0 8
0 1 1 16
1 0 0 32
1 0 1 64
1 1 0 128
1 1 1 256
Se si vuole cambiare la frequenza fi
di interrupt con Np,
il fattore di divisione
di prescaler fi assumerà
la seguente formula matematica:
fi=fosc/4/Np
Prescaler
 La frequenza di interrupt può essere cambiata anche
utilizzando sia il prescaler che cambiando il punto di
partenza del timerO.
 La frequenza fi può cambiare nel seguente modo:
fi=fosc/4/Np*(256-Nt)
Esempio con il prescaler
• Supponiamo di voler generare un interrupt ogni 3 ms
• Ti=256*Tm=256*4*Tclock=256/fosc/4
• Si inserisce il prescaler per cambiare Ti
• Ti=256*Np/f/4
• Imponendo Ti=3 Np=Ti/256*fosc/4=11.72
• Questo valore non è nelle tabelle del prescaler
• Si può far partire il conteggio del timer da un valore diverso da
zero
• Si deve allora calcolare il valore Nt da dove far partire il timer
• Si può utilizzare la seguente formula per calcolare il periodo di
interrupt Ti=Np*((256-Nt)/fosc/4
• Se si impone Ti=3 ms, Np=64, si calcola Nt=256-
3000/64=209,125=209
esempio
 Si vuole accendere e spegnere un led collegato su RA0
di un pic16f628 con periodo di 1 secondo. Si utilizza un
clock di 4 MHz.
 Se si impone un divisore di prescaler pari a 64, la
frequenza di interrupt diventa 15625
 Con un semplice conto, si calcola che per avere 1 Hz
basta far partire il timer da 125
Esercizi
 Se Nt=200 e Np=512, per un clock con frequenza 4
MHz, che valore assumeranno fi e ti?
 Se si vuole una frequenza fì pari a 300 con un clock di
4 MHz, come bisogna combinare Np ed Nt?
Registro INTCON
GIE Abilitazione di tutti gli interrupt 0 disabilitati
1 abilitati
EEIE Segnala il completamento nella memoria
EEPROM
0 Non completo
1 Completo
TOIE Abilita l’interrupt per il superamento di capacità
del timer0
0 Disabilitato
1 Abilitato
INTE Abilita l’interrupt su RB0/INT 0 Disabilita
1 Abilita
RBIE Abilita l’interrupt per il cambio di livello su RB7-
RB4
0 Disabilita
1 abilita
TOIF Segnala overflow su timer0 0 No Overflow
1 Overflow avvenuto
INTF Segnala la richiesta di interrupt su RB0/INT 0 Nessuna richiesta
1 Richiesta avvenuta
RBIF Segnale di cambio di livello su RB7-RB4 0 Nessun cambio livello
1 Cambio di più livelli
Routine di interrupt senza
prescaler
 La routine di interrupt va scritta a partire dalla locazione 004 della
memoria programma
 Se si vuole utilizzare il timer senza inserire il prescaler, bisogna seguire
questa sequenza di passaggi:
 Scrivere una routine di interrupt a partire dalla locazione 004. Nella
routine bisogna dare le seguenti informazioni:
• Si carica il valore dal quale bisogna far partire il timer
• Azzerare il flag di avvenuto interupt, bit 2 del registro INTCON
• Ritornare al programma principale tramite il comando RETFIE
 Nella routine principale bisogna scrivere:
• Porre a zero il bit 5 del registro OPTION, cioè porre in modalità timer
• Caricare il valore iniziale del timer
• Abilitare l’interrupt ponendo a 1 il bit 5 di INTCON
• Abilitare gli interrupt ponendo a 0 il bit 7 del registro INTCON
Routine di interrupt con prescaler
• Bisogna scrivere la routine di interrupt e partire dalla locazione
004 della memoria programma
o ricaricare il valore iniziale del timer
o azzerare il flag di avvenuto interrupt tramite il bit 2 del registro
INTCON
o terminare la routine di interrupt tramite l’istruzione RETFIE
• Nel programma principale si scrivono le seguenti istruzioni:
o assegnare il prescaler al timer ponendo a 0 il bit 3 del registro
OPTION
o selezionare il fattore di divisione del prescaler
o assegnare il valore di inizio del timer
o abilitare l’interrupt del timer ponendo a 1 il bit 5 di INTCON
o abilitare tutti gli interrupt ponendo a 1 il bit 7 di INTCON
Come settare il prescaler
esempio
 Si vuol far accendere e spegnere un led su RA1 con
frequenza 1 Hz. Si utilizzi un quarzo di 4 MHz
 f(clock)=4000000Hz; f(macchina)=1000000 Hz
 Si pone Np=(64) 10=combinazione prescaler 101
 256-Nt=125
Lampeggio di un led con frequenza
di 1 Hz
list p=16f628
radix dec
porta equ 5
portb equ 6
Timer equ 1
intcon equ 0x0b
cont equ 0x0c
flag equ 0x0d
toif equ 0x02
toie equ 0x05
gie equ 0x07
goto start
Lampeggio led: routine interrupt
org 4
interrupt: incf cont,1
movlw 0x00
movwf timer
bcf intcon, toif
retfie ;ritorno dall’interrupt
Lampeggio di un led:routine
principale
start: movlw 0xd5 ; carica il valore 11010101
movwf option
movlw 0xff
tris portb
movlw 0x00
tris porta
RBPU INTEDG TOCS TOSE PSA PS2 PS1 PS0
1 1 0 1 0 1 0 1
Divisore di prescaler=64
Clock interno
Prescaler al timer
Lampeggio di un led
movwf timer ;l’accumulatore è ancora azzerato
movwf cont
bsf intcon, toie ;abilita l’interrupt timer
bsf intcon, gie ;abilita gli interrupt
ancora: movlw 125
xorwf cont,0 ;esegue l’operazione logica XOR tra cont e W e pone il risultato in W
skpz ; salta se il risultato è zero. Il conteggio si ferma a 125
goto ancora
avanti: movwf cont
comf flag,1 ;complementa flag e pone il risultatp in flag
btfsc flag,0 ;testa il bit 0 e salta se 0
goto accendi
bcf porta,0
goto ancora
accendi: bsf porta,0
goto ancora
end
Assembly2

Assembly2

  • 1.
  • 2.
    Generatore di ondequadre  Il generatore di onde quadre consiste di un treno di onde luminose caratterizzate da un periodo il cui 50% il livello logico è alto e il restante 50% è a livello logico basso.  Fare ciò, significa gestire il tempo e quindi i ritardi sui pic  Un metodo molto semplice e forse, un po’ banale, è quello di far lavorare la macchina avuoto senza far eseguire alcuna operazione.  L’istruzione per non far eseguire operazioni è nop.  La routine è la seguente: LIST p=16F628 include "P16F628.inc“ ; libreria dove sono definiti I registri del 16f628 org 0x0000 movlw 0x07 movwf CMCON ;tutti i comparatori sono disattivati. Le porte che sono multiplexate, fungono solo ;da I/O bsf STATUS, RP0 ; viene posto a 1 il bit RP0 del registro Staus per selezionare il bank1 movlw b'00000000' movwf TRISB ;portb come output movwf TRISA ;porta come output bcf STATUS, RP0 ; viene posto a 0 il bit RP0 del registro Staus per selezionare il bank0
  • 3.
    Loop del programma Loopmovlw 0xff ; viene caricato il numero ;255 in formato esadecimale che tradotto un binario è 11111111 movwf PORTA ;porta è a livello logico alto movwf PORTB ;portb è a livello logico alto nop ; viene inserito un ritardo di 1 microsecondo ;perchè ogni ciclo macchina ha frequenza 1 Mhz nop ; per 1 us la macchina non esegue operazioni movlw 0x00 ; viene caricato lo zero movwf PORTA ;porta e portb sono a livello logico basso movwf PORTB nop nop goto Loop end
  • 4.
    Nop  Nop èl’istruzione che non fa eseguire alcuna operazione.  A che cosa può servire?  Fa lavorare il micro a vuoto per mantenere fisso lo stato di un microcontrollore e non far cambiare stato.  Quanto può durare un ritardo?  Se la frequenza di clock è di 4 MHz, il periodo sarà di 0,25 us e il tempo macchina è 4*Tclock=1us  Ogni ciclo macchina dura quindi 1 us se la frequenza di clock è 4 MHz.  Il ritardo ottenuto è quindi 2 us visto che sono state introdotte due righe con l’istruzione nop
  • 5.
    Senza libreria  Senon avessimo inserito la libreria avremmo dovuto dare delle direttive al compilatore: PORTA EQU 0x05 PORTB EQU 0x06 TRISA EQU 0x05 TRISB EQU 0x06 STAUS EQU 0x03 RP0 EQU 0x05 ; bit 5 del registro status CMCON EQU 0x1F
  • 6.
    Riga programma Registrointeressato Stato deI bit Registro MOVLW 0X07 accumulatore 0 0 0 0 0 1 1 1 MOVWF cmcon cmcon 0 0 0 0 0 1 1 1 Bsf status,rp0 5 bit registro status 0 0 1 0 0 0 0 0 Movlw 0x00 accumulatore 0 0 0 0 0 0 0 0 Movwf trisa Trisa del bank1 0 0 0 0 0 0 0 0 Movwf trisb Trisb del bank1 0 0 0 0 0 0 0 0 Bcf status, rp0 5 bit registro status 0 0 0 0 0 0 0 0 Movlw 0xff accumulatore 1 1 1 1 1 1 1 1 Movwf porta Porta del bank0 1 1 1 1 1 1 1 1 Movwf portb Portb del bank0 1 1 1 1 1 1 1 1 nop Nessun registro Movlw 0x00 accumulatore 0 0 0 0 0 0 0 0 Movwf porta Porta del bank0 0 0 0 0 0 0 0 0 Movwf portb Portb del bank0 0 0 0 0 0 0 0 0
  • 7.
    Ritardo con unaroutine di ritardo • Con pochi microsecondi di ritardo non possiamo renderci conto della differenza tra i due livelli logici e, gestire un ritardo più grande, comporterebbe la scrittura di un numero enorme di istruzioni nop. • Un metodo più efficace è quello di inserire un valore in un registro GFR e, decrementarlo. • La macchina rimane nel suo stato fino a quando il registro non è zero • Si passa alla istruzione successiva se tutto è nullo. • Useremo quindi decfsz salta alla istruzione successiva se il risultato è nullo • Il programma è il seguente: LIST p=16F628 include "P16F628.inc“ count1 equ 0x0C ; registro generale count2 equ 0x0D org 0x00
  • 8.
    Ritardo con unaroutine di ritardo movlw 0x07 movwf CMCON ;pone I comparatori a 1 bsf STATUS, RP0 ;seleziona bank1 movlw b'00000000' movwf TRISB movwf TRISA bcf STATUS, RP0 ;seleziona banco 0 clrf PORTA ;porta non viene mai usata clrf PORTB loop: call Delay bsf PORTB, 7 ;pone il bit 7 a livello logico alto call Delay
  • 9.
    Ritardo con unaroutine di ritardo: subroutine di ritardo Spegni: bcf portb,7 ;pone a livello logico basso il bit 7 goto loop Delay: movlw 0x0f movwf conta2 ;pone il valore 15 in un GFR movlw 0x0f movwf conta1 ;pone il valore 15 in un GFR Loop1: decfsz conta1 ;decrementa il registro e salta se zero goto Loop1 Loop2: decfsz conta2 ;decrementa il registro e salta se zero goto Loop2 return end
  • 10.
    Osservazioni  Nel programmasono stati settati sia i registri porta e trisa che non servono; non serve nemmeno il settaggio del registro comcon che setta i comparatori. Se fosse stato utilizzato tutto il registro trisa, sarebbe stato utile settare i comparatori.  Si noti che il ritardo sul cambio di stato di ogni porta è di 30 us perché il decremento di ciascun registro 0ch e 0dh dura 15 cicli macchina e, ogni ciclo dura 1 us; 15 cicli durano 15 us. Siccome sono due registri da decrementare, il ritardo sarà di 30 us  Per fare un ritardo più grande, si possono settare a 1 al massimo 8 bit di ciascun registro per un numero di cicli massimi di decrementi pari a 255 us
  • 11.
    esercizio  Scrivere unprogramma che faccia accendere e spegnere alternativamente 2 led e ciascuno con un ritardo di 200 us
  • 12.
    Osservazioni  Quando siincontra l’istruzione goto oppure call subroutine, si ha un salto e si interrompe il flusso del programma per eseguire la linea programma o la subroutine. Nella memoria programmi c’è una parte riservata allo stack pointer in cui si inserisce l’indirizzo in cui è stato interrotto il programma. Terminate le istruzioni in cui il programma è saltato, lo stack pointer fornisce l’indirizzo della memoria programma dove ritornare
  • 13.
    Registri Riga programma RegistriBit Movlw 0x07 w 0 0 0 0 0 1 1 1 Movwf cmcon Registro comparatore 0 0 0 0 0 1 1 1 Bsf status,rp0 Bit 5 di status 0 0 0 1 0 0 0 0 Movlw 0x00 w 0 0 0 0 0 0 0 0 Movwf trisb trisb 0 0 0 0 0 0 0 0 Bcf status,rp0 Bit 5 di status 0 0 0 0 0 0 0 0 Clrf portb portb 0 0 0 0 0 0 0 0 Call delay Bsf portb,7 Bit 7 portb 1 0 0 0 0 0 0 0 Call delay Goto loop
  • 14.
    Delay Riga programmi RegistriBit Movlw 0x02 w 0 0 0 0 0 0 1 0 Movwf conta1 Registro 0x0c 0 0 0 0 0 0 1 0 Movlw 0x02 W 0 0 0 0 0 0 1 0 Movwf conta2 Registro 0x0d 0 0 0 0 0 0 1 0 Decfsz conta1 0x0c 0 0 0 0 0 0 0 1 Goto loop1 Decfsz conta1 0x0c 0 0 0 0 0 0 0 0 Decfsz conta2 0x0d 0 0 0 0 0 0 0 1 Decfsz conta2 0x0d 0 0 0 0 0 0 0 0 Return Supponiamo di inserire un ritardo molto più piccolo Ritorna all’ultima chiamata di subroutine.
  • 15.
    Un tempo diritardo più lungo Delay: movlw 0x0f movwf conta2 ;pone il valore 15 in un GFR Loop2: movlw 0x0f movwf conta1 ;pone il valore 15 in un GFR Loop1: decfsz conta1 ;decrementa il registro e salta se zero goto Loop1 decfsz conta2 ;decrementa il registro e salta se zero goto Loop2 return end  Questa volta, per ogni decremento di conta2, si ritorna a loop2  Ogni decremento di conta2 genera 15 decrementi di conta1  I decrementi terminano quando conta2 è zero  Il tempo di ritardo è 255 us=15*15
  • 16.
    Sorgenti di segnali Ogni microcontrollore lavora secondo un certo sincronismo  I segnali di sincronizzazione possono essere interni o esterni  Se esterni, viene applicato un generatore di impulsi ad una certa frequenza su un determinato pin.  Nel caso del pic16f628, il segnale viene applicato sul pin 3
  • 17.
    Prescaler e interrupt Ilpic 16f628 è dotato di un timer interno ad 8 bit. Il registro timer0, registro del bank0 all’indirzzo 01h, incrementa il proprio contenuto per ogni ciclo macchina L’oscillatore interno del pic genera una frequenza f=4 MHz; la frequenza di un qualsiasi segnale proveniente dal pic è quindi di f/4=1 Mhz, frequenza macchina. Il registro timer0 incrementa così il proprio contenuto con la frequenza di 1 MHz La frequenza di interruzione, frequenza di interrupt, si ha quando il timer inizia a contare daccapo, cioè quando passa da overflow a zero. Essendo il timer0 di 8 bit, l’interrupt si ha ogni 28 -1 cicli macchina+1=256 contando anche il passaggio da overflow a zero
  • 18.
    Frequenza di interrupt La frequenza fi di interrupt si calcola dividendo la frequenza macchina per 256: fi=f(osc)/(4*256)  Si potrebbe cambiare la frequenza di interrupt con due metodi:  Inizializzando il timer con un valore Nt diverso da 0. • È come accorciare la lunghezza del timer così impiegherà meno tempo per andare in overflow • La nuova frequenza fi di interrupt sarà: fi=f(osc)/4/(256-Nt)  La frequenza di interrupt può cambiare se si inserisce un prescaler, cioè un divisore di frequenza. • Il prescaler è formato dai tre bit del registro option che si trova all’indirizzo 81h, è cioè un registro di bank1
  • 19.
    Esercizi per impostarel’interrupt senza prescaler 1. Calcolare il periodo di interrupt se Nt=0 2. Calcolare il periodo e la frequenza di interrupt se Nt=200 3. A quanto bisogna impostare Nt se si chiede che fi=300 Hz
  • 20.
    Registro Option Bit 0RBPU Disabilita o abilitai resistori interni di pull up 0 disabilita 1 abilita Bit 1 INTEDG Seleziona il fronte di salita di interrupt su RB0/INT 0 fronte salita 1 fronte discesa Bit 2 TOCS Seleziona il fronte di segnale di clock del timer 0 clock interno 1 clock esterno Bit 3 TOSE Seleziona il fronte del segnale per il clock del timer su RA4/TOCKL 0 fronte di discesa 1 fronte di salita Bit 4 PSA Assegna il prescaler l timer TMR0 o al WDT 0 TMR0 1 WDT Bit 5 PS2 Selezione il fattore di divisione per il TMR0 Bit 6 PS1 Bit 7 PS0
  • 21.
  • 22.
    Prescaler Ps2 Ps1 Ps0Divisore 0 0 0 2 0 0 1 4 0 1 0 8 0 1 1 16 1 0 0 32 1 0 1 64 1 1 0 128 1 1 1 256 Se si vuole cambiare la frequenza fi di interrupt con Np, il fattore di divisione di prescaler fi assumerà la seguente formula matematica: fi=fosc/4/Np
  • 23.
    Prescaler  La frequenzadi interrupt può essere cambiata anche utilizzando sia il prescaler che cambiando il punto di partenza del timerO.  La frequenza fi può cambiare nel seguente modo: fi=fosc/4/Np*(256-Nt)
  • 24.
    Esempio con ilprescaler • Supponiamo di voler generare un interrupt ogni 3 ms • Ti=256*Tm=256*4*Tclock=256/fosc/4 • Si inserisce il prescaler per cambiare Ti • Ti=256*Np/f/4 • Imponendo Ti=3 Np=Ti/256*fosc/4=11.72 • Questo valore non è nelle tabelle del prescaler • Si può far partire il conteggio del timer da un valore diverso da zero • Si deve allora calcolare il valore Nt da dove far partire il timer • Si può utilizzare la seguente formula per calcolare il periodo di interrupt Ti=Np*((256-Nt)/fosc/4 • Se si impone Ti=3 ms, Np=64, si calcola Nt=256- 3000/64=209,125=209
  • 25.
    esempio  Si vuoleaccendere e spegnere un led collegato su RA0 di un pic16f628 con periodo di 1 secondo. Si utilizza un clock di 4 MHz.  Se si impone un divisore di prescaler pari a 64, la frequenza di interrupt diventa 15625  Con un semplice conto, si calcola che per avere 1 Hz basta far partire il timer da 125
  • 26.
    Esercizi  Se Nt=200e Np=512, per un clock con frequenza 4 MHz, che valore assumeranno fi e ti?  Se si vuole una frequenza fì pari a 300 con un clock di 4 MHz, come bisogna combinare Np ed Nt?
  • 27.
    Registro INTCON GIE Abilitazionedi tutti gli interrupt 0 disabilitati 1 abilitati EEIE Segnala il completamento nella memoria EEPROM 0 Non completo 1 Completo TOIE Abilita l’interrupt per il superamento di capacità del timer0 0 Disabilitato 1 Abilitato INTE Abilita l’interrupt su RB0/INT 0 Disabilita 1 Abilita RBIE Abilita l’interrupt per il cambio di livello su RB7- RB4 0 Disabilita 1 abilita TOIF Segnala overflow su timer0 0 No Overflow 1 Overflow avvenuto INTF Segnala la richiesta di interrupt su RB0/INT 0 Nessuna richiesta 1 Richiesta avvenuta RBIF Segnale di cambio di livello su RB7-RB4 0 Nessun cambio livello 1 Cambio di più livelli
  • 28.
    Routine di interruptsenza prescaler  La routine di interrupt va scritta a partire dalla locazione 004 della memoria programma  Se si vuole utilizzare il timer senza inserire il prescaler, bisogna seguire questa sequenza di passaggi:  Scrivere una routine di interrupt a partire dalla locazione 004. Nella routine bisogna dare le seguenti informazioni: • Si carica il valore dal quale bisogna far partire il timer • Azzerare il flag di avvenuto interupt, bit 2 del registro INTCON • Ritornare al programma principale tramite il comando RETFIE  Nella routine principale bisogna scrivere: • Porre a zero il bit 5 del registro OPTION, cioè porre in modalità timer • Caricare il valore iniziale del timer • Abilitare l’interrupt ponendo a 1 il bit 5 di INTCON • Abilitare gli interrupt ponendo a 0 il bit 7 del registro INTCON
  • 29.
    Routine di interruptcon prescaler • Bisogna scrivere la routine di interrupt e partire dalla locazione 004 della memoria programma o ricaricare il valore iniziale del timer o azzerare il flag di avvenuto interrupt tramite il bit 2 del registro INTCON o terminare la routine di interrupt tramite l’istruzione RETFIE • Nel programma principale si scrivono le seguenti istruzioni: o assegnare il prescaler al timer ponendo a 0 il bit 3 del registro OPTION o selezionare il fattore di divisione del prescaler o assegnare il valore di inizio del timer o abilitare l’interrupt del timer ponendo a 1 il bit 5 di INTCON o abilitare tutti gli interrupt ponendo a 1 il bit 7 di INTCON
  • 30.
    Come settare ilprescaler
  • 31.
    esempio  Si vuolfar accendere e spegnere un led su RA1 con frequenza 1 Hz. Si utilizzi un quarzo di 4 MHz  f(clock)=4000000Hz; f(macchina)=1000000 Hz  Si pone Np=(64) 10=combinazione prescaler 101  256-Nt=125
  • 32.
    Lampeggio di unled con frequenza di 1 Hz list p=16f628 radix dec porta equ 5 portb equ 6 Timer equ 1 intcon equ 0x0b cont equ 0x0c flag equ 0x0d toif equ 0x02 toie equ 0x05 gie equ 0x07 goto start
  • 33.
    Lampeggio led: routineinterrupt org 4 interrupt: incf cont,1 movlw 0x00 movwf timer bcf intcon, toif retfie ;ritorno dall’interrupt
  • 34.
    Lampeggio di unled:routine principale start: movlw 0xd5 ; carica il valore 11010101 movwf option movlw 0xff tris portb movlw 0x00 tris porta RBPU INTEDG TOCS TOSE PSA PS2 PS1 PS0 1 1 0 1 0 1 0 1 Divisore di prescaler=64 Clock interno Prescaler al timer
  • 35.
    Lampeggio di unled movwf timer ;l’accumulatore è ancora azzerato movwf cont bsf intcon, toie ;abilita l’interrupt timer bsf intcon, gie ;abilita gli interrupt ancora: movlw 125 xorwf cont,0 ;esegue l’operazione logica XOR tra cont e W e pone il risultato in W skpz ; salta se il risultato è zero. Il conteggio si ferma a 125 goto ancora avanti: movwf cont comf flag,1 ;complementa flag e pone il risultatp in flag btfsc flag,0 ;testa il bit 0 e salta se 0 goto accendi bcf porta,0 goto ancora accendi: bsf porta,0 goto ancora end