PICmicro. PICmicro Cult 3

Funzionamento in uscita

Per configurare la linea RA0 in uscita, dobbiamo mettere a 0 il bit 0 del registro TRISA con l'istruzione:

bcf	TRISA,0

Questo determina la commutazione a 0 dell'uscita Q del TRIS latch (ed a 1 dell'uscita Q negata). In questo stato il valore in uscita dalle porte OR e AND dipende esclusivamente dallo stato dell'uscita Q negata del Data Latch. Come per il TRIS latch, anche il Data Latch dipende dallo stato di un bit in un registro, in particolare del registro PORTA. La sua uscita negata viene inviata all'ingresso delle due porte logiche OR e AND e quindi direttamente sulla base dei transistor P ed N.

Se mettiamo a 0 il bit 0 del registro PORTA con l'istruzione:

bcf	PORTA,0

otterremo la conduzione del transistor N con conseguente messa a 0 della linea RA0. Se invece mettiamo a 1 il bit 0 con l'istruzione:

bsf	PORTA,0

otterremo la conduzione del transistor P con conseguenza messa a +5 volt della linea RA0. In questa condizione è sempre possibile rileggere il valore inviato sulla linea tramite la circuiteria d'ingresso.

Stadio d'uscita della linea RA4

Analizziamo ora il funzionamento dello stadio d'uscita della linea RA4 che si differenzia da tutte le altre linee di I/O in quanto condivide lo stesso pin del PIC16F84 con il TOCKI.
Nella figura seguente viene riprodotto lo schema a blocchi dello stadio d'uscita estratto dal data sheet Microchip:

La logica di commutazione è sostanzialmente identica al gruppo di linee RA0-3 ad eccezione dell'assenza della porta OR e del transistor P, ovvero di tutta la catena che consente di collegare al positivo la linea RA4. Questo significa, in termini pratici, che quando la linea RA4 viene programmata in uscita e messa a 1 in realtà non viene connessa al positivo ma rimane scollegata. Tale tipo di circuiteria d'uscita viene denominata a "collettore aperto" ed è utile per applicazioni in cui sia necessario condividere uno stesso collegamento con più pin d'uscita e ci sia quindi la necessita di mettere in alta impedenza una linea d'uscita senza doverla riprogrammare come linea d'ingresso.

Se vogliamo essere sicuri che la linea RA4 vada a 1 dovremo collegare esternamente una resistenza di pull-up, ovvero una resistenza collegata al positivo di alimentazione.
Vedremo in seguito l'utilizzo della linea indicata sullo schema TMR0 clock input.

Stadio d'uscita delle linee RB0, RB1, RB2 ed RB3

Anche per questo gruppo di linee rimane sostanzialmente invariata la logica di commutazione. Esse dispongono in aggiunta una circuiteria di weak pull-up attivabile quando le linee sono programmate in ingresso.
In ingresso infatti, come spiegato precedentemente, le linee vengono completamente scollegate dal PIC in quanto sia il transitor P che il transistor N sono aperti. Lo stato delle linee dipende quindi esclusivamente dalla circuiteria esterna. Se tale circuiteria e' di tipo a collettore aperto o piu' semplicemente e' costituita da un semplice pulsante che, quando premuto, collega a massa la linea di I/O, e' necessario inserire una resistenza di pull-up verso il positivo per essere sicuri che quando il pulsante e' rilasciato ci sia una condizione logica a 1 stabile sulla linea d'ingresso. La circuiteria di weak pull-up consente di evitare l'uso di resistenze di pull-up e puo' essere attivata o disattivata agendo sul bit RBPU del registro OPTION .

Nella figura seguente viene riprodotto lo schema a blocchi dello stadio d'uscita estratto dal data sheet Microchip:

La sola linea RB0 inoltre, presenta una caratteristica molto particolare. Essa, quando viene configurata come linea di ingresso, puo' generare, in corrispondenza di un cambio di stato logico, un interrupt, ovvero una interruzione immediata del programma in esecuzione ed una chiamata ad una subroutine speciale denominata interrupt handler. Ma di questo parleremo in seguito.

Stadio d'uscita delle linee RB4, RB5, RB6 e RB7

La circuiteria di commutazione di questo gruppo di linee è identica al gruppo RB0-3. Queste linee dispongono anche della circuiteria di weak pull-up. In più rispetto alle linee RB0-3 hanno uno stadio in grado di rilevare variazioni di stato su una qualsiasi linea e di generare un interrupt di cui parleremo nelle prossime lezioni.

Nella figura seguente viene riprodotto lo schema a blocchi dello stadio d'uscita estratto dal data sheet Microchip:

Input da tastiera

Dopo aver realizzato, nella lezione precedente, le luci in sequenza sfruttando le linee da RB0 a RB3 come linee di output, vediamo ora come si può realizzare un input da tastiera configurando le linee da RB4 a RB7 come linee di input.
Per far questo ampliamo il circuito presentato nella lezione 2 con quattro pulsanti da stampato denominati SW1, SW2, SW3 ed SW4 e collegati secondo lo schema elettrico riportato di seguito:

Schema elettrico

Ognuno di questi pulsanti collega a massa una linea di ingresso normalmente mantenuta a + 5 volt da una resistenza (da R6 a R9). Prendendo, ad esempio, il pin 10 del PIC16F84A, questa linea verrà mantenuta a +5 volt finché non verrà premuto il tasto SW1 che provvederà a portare la linea ad 0 volt.

Realizziamo un programma d'esempio che accenda ciascuno dei led D1, D2, D3 e D4 in corrispondenza della pressione di uno dei tasti SW1, SW2, SW3 e SW4.
Il source dell'esempio e' riportato nel file

INPUT.ASM .

La parte iniziale del programma esegue le stesse funzioni effettuate negli esempi precedenti ed in particolare le istruzioni:

movlw 11110000B
movwf TRISB

configurano le linee da RB0 a RB3 in uscita per il collegamento con i led e le linee da RB4 a RB7 in ingresso per il collegamento con i quattro pulsanti. Il resto del programma.
L'istruzione:

bcf   STATUS,RP0

Effettua uno swap sul banco di registri 0 in modo che possiamo accedere direttamente allo stato delle linee di I/O.

MainLoop

  clrf  PORTB

Questa istruzione spegne tutti i led collegati sulla PORTA B and ogni ciclo di loop in modo che possano poi essere accesi sulla base dello stato dei pulsanti.

btfss PORTB,SW1
bsf   PORTB,LED1

Queste due istruzioni vengono eseguite per ogni linea collegata ad un pulsante per verificare se il pulsante è premuto e per accendere il led corrispondente.
in pratica la:

btfss PORTB,SW1

salta la successiva:

bsf   PORTB,LED1

solo se il pulsante SW1 è rilasciato. In caso contrario la esegue accendendo il led. Questa coppia di istruzioni viene eseguita per ogni tasto.
Il tutto viene eseguito all'interno di un singolo loop tramite l'istruzione:

goto  MainLoop

DATA SHEET PIC16F84a MICROCHIP

Il contatore TMR0

Vediamo ora cosa è e come funziona il registro TMR0.

Il registro TMR0 è un contatore, ovvero un particolare tipo di registro il cui contenuto viene incrementato con cadenza regolare e programmabile direttamente dall'hardware del PIC. In pratica, a differenza di altri registri, il TMR0 non mantiene inalterato il valore che gli viene memorizzato, ma lo incrementa continuamente, se ad esempio scriviamo in esso il valore 10 con le seguenti istruzioni:

movlw    10
movwf    TMR0

dopo un tempo pari a quattro cicli macchina, il contenuto del registro comincia ad essere incrementato a 11, 12, 13 e cosi via con cadenza costante e del tutto indipendente dall'esecuzione del resto del programma.
Se, ad esempio, dopo aver inserito un valore nel registro TMR0, eseguiamo un loop infinito

   movlw	10
   movwf	TMR0
loop
   goto loop

il registro TMR0 viene comunque incrementato dall'hardware interno al PIC contemporaneamente all'esecuzione del loop.
Una volta raggiunto il valore 255 il registro TMR0 viene azzerato automaticamente riprendendo quindi il conteggio non dal valore originariamente impostato ma da zero.
La frequenza di conteggio è direttamente proporzionale alla frequenza di clock applicata al chip e può essere modificata programmando opportunamente alcuni bit di configurazione.
Nella figura seguente viene riportata la catena di blocchi interni al PIC che determinano il funzionamento del registro TMR0.

I blocchi Fosc/4 e T0CKI riportati in blu rappresentano le due possibili sorgenti di segnale per il contatore TMR0.

Fosc/4 è un segnale generato internamente al PIC dal circuito di clock ed è pari alla frequenza di clock divisa per quattro.

T0CKI è un segnale generato da un eventuale circuito esterno ed applicato al pin T0CKI corrispondente al pin 3 nel PIC16F84A.

I blocchi T0CS e PSA riportati in verde sono due commutatori di segnale sulla cui uscita viene presentato uno dei due segnali in ingresso in base al valore dei bit T0CS e PSA del registro OPTION.

Il blocco PRESCALER è un divisore programmabile il cui funzionamento verrà spiegato nel prossimo passo.

Vediamo in pratica come è possibile agire su questi blocchi per ottenere differenti modalità di conteggio per il registro TMR0.
Iniziamo programmando i bit T0CS a 0 e PSA a 1. La configurazione di funzionamento che otterremo è rappresentata nella seguente figura:

Le parti in rosso evidenziano il percorso che effettua il segnale prima di arrivare al contatore TMR0.
Come abbiamo già detto in precedenza, la frequenza Fosc/4 è pari ad un quarto della frequenza di clock. Utilizzando un quarzo da 4Mhz avremo una Fosc/4 pari ad 1 MHz. Tale frequenza viene inviata direttamente al registro TMR0 senza subire nessun cambiamento. La cadenza di conteggio che se ne ottiene è quindi pari ad 1 milione di incrementi al secondo del valore presente in TMR0.
Ipotizziamo ora di cambiare lo stato del bit T0CS da 0 a 1 la configurazione che otteniamo è la seguente:

Questa volta sarà il segnale applicato al pin TOCKI del PIC ad essere inviato direttamente al contatore TMR0 determinandone la frequenza di conteggio. Applicando ad esempio a questo pin una frequenza pari ad 100Hz otterremo una frequenza di conteggio pari a cento incrementi al secondo.

La presenza della porta logica XOR (exclusive OR) all'ingresso TOCKI del PIC consente di determinare tramite il bit T0SE del registro OPTION se il contatore TMR0 deve essere incrementato in corrispondenza del fronte di discesa (T0SE=1) o del fronte di salita (T0SE=0) del segnale applicato dall'esterno.
Nella figura seguente viene rappresentata la corrispondenza tra l'andamento del segnale esterno ed il valore assunto dal contatore TMR0 in entrambe i casi:

Il Prescaler

L'ultimo blocco rimasto da analizzare per poter utilizzare completamente il registro TMR0 è il PRESCALER.
Se configuriamo il bit PSA del registro OPTION a 0 inviamo al registro TMR0 il segnale in uscita dal PRESCALER come visibile nella seguente figura:

Il PRESCALER consiste in pratica in un divisore programmabile a 8 bit da utilizzare nel caso la frequenza di conteggio inviata al contatore TMR0 sia troppo elevata per i nostri scopi.
Nell'esempio riportato al passo precedente abbiamo visto che utilizzando un quarzo da 4Mhz otteniamo una frequenza di conteggio pari ad 1Mhz che per molte applicazioni potrebbe risultare troppo elevata.
Con l'uso del PRESCALER possiamo dividere ulteriormente la frequenza Fosc/4 configurando opportunamente i bit PS0, PS1 e PS2 del registro OPTION secondo la seguente tabella.

Proviamo ora ad effettuare un esperimento sul campo per verificare quanto finora appreso.
Nella lezione 2 avevamo realizzato un lampeggiatore a quattro led la cui sequenza di lampeggio era determinata da una subroutine che introduceva un ritardo software, ovvero un ritardo basato sul tempo di esecuzione di un ciclo continuo di istruzioni.
Proviamo ora a riscrivere la stessa subroutine per introdurre un ritardo pari ad un secondo utilizzando il registro TMR0.
Le modifiche sono state riportate nel file

SEQTMR0.ASM.

Dobbiamo anzitutto programmare il PRESCALER per ottenere una frequenza di conteggio conveniente inserendo le seguenti istruzioni all'inizio del programma:

movlw    00000100B
movwf    OPTION_REG

In pratica dobbiamo programmare bit T0CS a 0 per selezionare come sorgente del conteggio il clock del PIC, il bit PSA a 0 per assegnare il PRESCALER al registro TRM0 anziché al Watch Dog Timer (di cui tratteremo in seguito) e i bit di configurazione del PRESCALER a 100 per ottenere una frequenza di divisione pari a 1:32.
La frequenza di conteggio che otterremo sul TRM0 sara' pari a:

Fosc = 1Mhz / 32 = 31.250 Hz

La subrountine Delay dovrà utilizzare opportunamento il registro TMR0 per ottenere un ritardo pari ad un secondo. Vediamo come. Le prime istruzioni che vengono eseguite nella Delay sono:

movlw    6
movwf    TMR0

e

movlw    125
movwf    Count

Le prime due memorizzano in TMR0 il valore 6 in modo che il registro TMR0 raggiunga lo zero dopo 250 conteggi (256 - 6 = 250) ottenendo cosi una frequenza di passaggi per lo zero di TMR0 pari a:

31.250 / 250 = 125 Hz

Le istruzioni seguenti memorizzano in un registro a 8 bit (Count) il valore 125 in modo tale che, decrementando questo registro di uno per ogni passaggio per lo zero di TMR0, si ottenga una frequenza di passaggi per lo zero del registro Count pari a:

125/125 = 1Hz

Le istruzioni inserite nel loop DelayLoop si occupano quindi di controllare se TMR0 ha raggiunto lo zero, quindi di reinizializzarlo a 6 e decrementare il valore contenuto in Count. Quando Count raggiungerà anch'esso lo zero allora sarà trascorso un secondo e la subroutine potrà fare ritorno al programma chiamante.

Scarica subito una copia gratis

Scrivi un commento

Seguici anche sul tuo Social Network preferito!

Send this to a friend