Assembly2

36
Gestione dei ritardi

Transcript of Assembly2

Page 1: Assembly2

Gestione dei ritardi

Page 2: Assembly2

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=16F628include "P16F628.inc“ ; libreria dove sono definiti I registri del 16f628org 0x0000 movlw 0x07 movwf CMCON ;tutti i comparatori sono disattivati. Le porte che sono multiplexate, fungono solo

;da I/Obsf STATUS, RP0 ; viene posto a 1 il bit RP0 del registro Staus per selezionare il bank1movlw b'00000000' movwf TRISB ;portb come outputmovwf TRISA ;porta come outputbcf STATUS, RP0 ; viene posto a 0 il bit RP0 del registro Staus per selezionare il bank0

Page 3: Assembly2

Loop del programmaLoop movlw 0xff ; viene caricato il numero

;255 in formato esadecimale che tradotto un binario è 11111111movwf PORTA ;porta è a livello logico altomovwf 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 operazionimovlw 0x00 ; viene caricato lo zeromovwf PORTA ;porta e portb sono a livello logico basso

movwf PORTBnopnopgoto Loop

end

Page 4: Assembly2

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

Page 5: Assembly2

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

Page 6: Assembly2

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

Page 7: Assembly2

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 generalecount2 equ 0x0D

org 0x00

Page 8: Assembly2

Ritardo con una routine di ritardomovlw 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 0clrf PORTA ;porta non viene mai usataclrf PORTB

loop: call Delaybsf PORTB, 7 ;pone il bit 7 a livello logico alto call Delay

Page 9: Assembly2

Ritardo con una routine di ritardo: subroutine di ritardoSpegni: bcf portb,7 ;pone a livello logico basso il bit 7

goto loopDelay: movlw 0x0f

movwf conta2 ;pone il valore 15 in un GFRmovlw 0x0fmovwf conta1 ;pone il valore 15 in un GFR

Loop1: decfsz conta1 ;decrementa il registro e salta se zerogoto Loop1

Loop2: decfsz conta2 ;decrementa il registro e salta se zerogoto Loop2returnend

Page 10: Assembly2

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

Page 11: Assembly2

esercizio Scrivere un programma che faccia accendere e

spegnere alternativamente 2 led e ciascuno con un ritardo di 200 us

Page 12: Assembly2

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 stackpointer fornisce l’indirizzo della memoria programma dove ritornare

Page 13: Assembly2

RegistriRiga 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

Page 14: Assembly2

DelayRiga 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.

Page 15: Assembly2

Un tempo di ritardo più lungoDelay: movlw 0x0f

movwf conta2 ;pone il valore 15 in un GFRLoop2: movlw 0x0f

movwf conta1 ;pone il valore 15 in un GFRLoop1: decfsz conta1 ;decrementa il registro e salta se zero

goto Loop1decfsz conta2 ;decrementa il registro e salta se zerogoto Loop2returnend

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

Page 16: Assembly2

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

Page 17: Assembly2

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 macchinaL’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

Page 18: Assembly2

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

Page 19: Assembly2

Esercizi per impostare l’interrupt senza prescaler1. 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

Page 20: Assembly2

Registro OptionBit 0 RBPU Disabilita o abilitai resistori interni di

pull up0 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

Page 21: Assembly2

Un piccolo schema

Page 22: Assembly2

PrescalerPs2 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 fidi interrupt con Np, il fattore di divisionedi prescaler fi assumeràla seguente formula matematica:

fi=fosc/4/Np

Page 23: Assembly2

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)

Page 24: Assembly2

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

Page 25: Assembly2

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

Page 26: Assembly2

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?

Page 27: Assembly2

Registro INTCONGIE 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

Page 28: Assembly2

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

Page 29: Assembly2

Routine di interrupt con prescaler• Bisogna scrivere la routine di interrupt e partire dalla locazione

004 della memoria programmao 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

Page 30: Assembly2

Come settare il prescaler

Page 31: Assembly2

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

Page 32: Assembly2

Lampeggio di un led con frequenza di 1 Hz

list p=16f628radix decporta equ 5portb equ 6

Timer equ 1intcon equ 0x0bcont equ 0x0cflag equ 0x0dtoif equ 0x02toie equ 0x05gie equ 0x07goto start

Page 33: Assembly2

Lampeggio led: routine interruptorg 4

interrupt: incf cont,1

movlw 0x00

movwf timer

bcf intcon, toif

retfie ;ritorno dall’interrupt

Page 34: Assembly2

Lampeggio di un led:routine principale

start: movlw 0xd5 ; carica il valore 11010101movwf option

movlw 0xfftris portbmovlw 0x00tris 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

Page 35: Assembly2

Lampeggio di un ledmovwf timer ;l’accumulatore è ancora azzeratomovwf contbsf intcon, toie ;abilita l’interrupt timerbsf intcon, gie ;abilita gli interrupt

ancora: movlw 125xorwf cont,0 ;esegue l’operazione logica XOR tra cont e W e pone il risultato in Wskpz ; salta se il risultato è zero. Il conteggio si ferma a 125goto ancora

avanti: movwf contcomf flag,1 ;complementa flag e pone il risultatp in flagbtfsc flag,0 ;testa il bit 0 e salta se 0goto accendibcf porta,0goto ancora

accendi: bsf porta,0 goto ancoraend

Page 36: Assembly2