ELEMANIA
PIC16F690 - Scrittura di una porta
Scrittura di PORTA: un caso semplice

Supponiamo ora di voler scrivere il valore 1 sul bit RB4 di PORTB per esempio per accendere un diodo LED collegato con la porta:

Come già osservato, la scrittura della porta dev'essere in generale effettuata prima della programmazione del registro TRISx, in modo da evitare che vengano erroneamente forniti in uscita valori senza senso. Inoltre il valore viene effettivamente scritto su PORTB solo dopo che il bit corrispondente è stato programmato in uscita. La sequenza di scrittura è dunque la seguente:

        BANKSEL PORTB
        BSF PORTB,4 ; Setta a 1 il bit 4 di PORTB
        
        BANKSEL TRISB
        BCF TRISB,4 ; Set a zero del bit 4 di TRISB (programmato come output)
       

 

Scrittura di PORTA: il problema del Read-Modify-Write

Nell'esempio precedente abbiamo supposto di scrivere in uscita un unico bit della porta. Supponiamo ora di voler settare a 1 due bit di una stessa porta, per esempio il bit zero e il bit 1 di PORTC (RC0 e RC1), per esempio per accendere due led collegati con i due piedini. La sequenza di operazioni che sembrerebbe corretta è questa:

        BANKSEL PORTC
        BSF PORTC,0 ; Setta a 1 il bit zero di PORTC
        BSF PORTC,1 ; Setta a 1 il bit uno di PORTC
        
        BANKSEL TRISC
        MOVLW b'11111100' ; Salva la costante binaria in W
        MOVWF TRISC ; Scrive W su TRISC  (solo a questo punto PORTC viene modificata)
       

Si osservi come in questo esempio abbiamo usato le istruzioni MOV per programmare TRISC (invece delle BSF e BCF usate negli esempi precedenti), in quanto si vogliono programmare 2 bit contemporaneamente (naturalmente sarebbe stato possibile eseguire la programmazione anche con due BCF, ma in questo caso la scrittura dei due bit sarebbe avvenuta in successione e non contemporaneamente).

Provando ad eseguire sul PIC (o a simulare in MPLAB) questa porzione di codice tuttavia si incontrano dei problemi. Ciò che si osserva è che solo il bit 1 di PORTC viene correttamente settato a 1, mentre il bit zero rimane a 0. In pratica si riesce a scrivere solo l'ultimo bit della sequenza (se, come nel nostro caso, i bit scritti sono più di uno). Vediamo le cause di questo problema esaminando la sequenza di operazioni con cui il PIC effettua la scrittura di una porta.

I PIC di fascia media (come il PIC16F690 - il problema è risolto diversamente nei PIC di fascia superiore come quelli della famiglia PIC18) utilizzano una sequenza nota come read-modify-write (RMW) quando si cambia lo stato di uscita (1 o 0) di un pin. Ciò può causare un comportamento imprevisto in determinate circostanze, in particolare quando al pin di uscita è collegato un carico capacitivo, cioè il cui valore non cambia istantaneamente nel tempo (un comportamento debolmente capacitivo è in realtà presente in ogni tipo di carico, perciò il problema qui esposto si verifica praticamente sempre).

Consideriamo a questo proposito la figura seguente:

RMW

Quando il programma cambia lo stato su un pin specifico, per esempio RC0 in PORTC, il PIC prima legge il valore di tutti i bit del registro PORTC e quindi memorizza questi dati in un registro interno del microcontrollore stesso (registro non accessibile al programmatore e non mappato sui banchi di memoria):

RMW

A questo punto il bit associato a RC0 che si vuole modificare viene cambiato nel registro interno in seguito a un'operazione di scrittura su PORTC:

RMW

Solo alla fine di questa operazione il PIC scrive tutti gli su PORTC e dunque in uscita:

RMW

Se il carico capacitivo collegato col pin di uscita era inizialmente scarico, ci vorrà un certo tempo prima che esso si carichi al valore desiderato. Supponiamo ora che, prima che il condensatore si sia caricato, venga fatta un'altra scrittura sul bit RC1. La sequenza è la stessa vista precedentemente e cioè anzitutto il valore della porta viene letto e copiato nel registro interno del PIC.

RMW

Tuttavia, siccome il condensatore non ha fatto in tempo a caricarsi, il valore letto non è il livello logico '1', ma il preesistente livello '0':

RMW

Ora il bit RC1 viene scritto nel registro interno (che però contiene un valore non corretto per RC0):

RMW

Infine il registro interno viene scritto sulla porta, cancellando in tale modo la precedente scrittura di RC0:

RMW

Questo errore di scrittura si presenta talmente frequentemente nella pratica che anche il simulatore MPLAB-IDE produce un risultato sbagliato quando si cerca di modificare in rapida sequenza due o più bit della stessa porta.

Le soluzioni possibili al problema sono almeno tre. La prima consiste nell'inserire un ciclo di ritardo fra la scrittura del primo bit e quella del secondo, in modo da lasciare il tempo al condensatore esterno di caricarsi (questa soluzione è la più semplice, ma non sempre funziona!). Un'altra soluzione consiste nel testare (dopo la scrittura) il valore del bit modificato e di ripetere il test finché non si è raggiunto il valore desiderato. Solo a quel punto si procede con la seconda scrittura sulla porta. Maggiori approfondimenti su questo argomento possono essere trovati qui.

La soluzione probabilmente più semplice ed efficace consiste nello scrivere tutti i bit che si vogliono programmare su un registro interno (ad esempio W o un registro GPR nella RAM) e poi di copiare l'intero registro sulla porta:

        BANKSEL PORTC
        MOVLW b'11' ; scrive il valore 11 su W
        MOVWF PORTC ; copia il contenuto di W su PORTC
        
        BANKSEL TRISC
        MOVLW b'11111100' ; Salva la costante binaria in W
        MOVWF TRISC ; Scrive W su TRISC  (solo a questo punto PORTC viene modificata)
       

In questo modo, poiché la porta viene programmata con un'unica scrittura, tutti i bit vengono scritti contemporaneamente e non si verifica più il problema legato ai ritardi di carica dei condensatori esterni.

 

precedente - successiva

Sito realizzato in base al template offerto da

http://www.graphixmania.it