MSSP in modo Master
Il modo Master è abilitato con i bit SSMP3:0 di SSPCON1. Sono possibili
due condizioni:
SSPM3:0 = 1000 |
Master |
SSPM3:0 = 1011 |
Master firmware controlled |
Il modo Master supporta la generazione di interrupt al riconoscimento di
varie condizioni:
- Start
- Stop
- trasferimento dato completato
- trasmissione dell' ACK
- Restart
Nel modo firmware controlled la conduzione del bus è a carico dell' utente
in seguito alle condizioni Start e Stop.
Le condizioni
applicate al bus dal modulo MSSP
saranno cancellate da un Reset del microcontroller o dalla
disabilitazione del modulo MSSP (SSPEN=0). Le linee SDA
e SCL saranno rilasciate. |
Il diagramma riporta la struttura logica del modulo MSSP in modo Master
I pin hanno un drive open drain e un receiver Schmitt trigger ciascuno.
Elemento chiave è la logica hardware di controllo delle condizioni,
che rileva e/o genera in modo automatico:
- Start
- Stop
- ACK
- Collisioni
- Arbitraggio del clock
- Stato dei contatori per la fine di trasmissione e ricezione
Il clock di comunicazione dipende da un generatore di baud rate (BRG),
alimentato dal clock principale (Fosc/4) e controllabile dai segnali di
arbitraggio per la sincronizzazione del clock nel caso di bus multi-Master.
Configurazione del Master.
Prima di poter utilizzare il modulo MSSP come Master, occorre configurarlo.
Supponiamo di voler impostare il PIC per un funzionamento:
- in modo Master
- su un bus a 400 kHz, con la Fosc=40 MHz
occorreranno i seguenti passi:
- Programmiamo il registro TRISC (direzione del PORTC) come ingressi per i pin
SCL (RC3) e SDA (RC4).
- Selezioniamo con i bit SSMP di SSPCON1 la modalità Master
- Configuriamo SSPSTAT portando a 0 il bit SMP per il
400 kHz e il bit CKP
anche a 0 per la compatibilità con I2C
- Calcoliamo il valore da impostare nel BRG (0x18) e scriviamo
questo in SSPADD
- Accendiamo il modulo con il bit SSPEN di SSPCON1
In Assembly:
; Configura MSSP per Master
I2C a 400kHz con Fosc=40MHz
i2c_setmssp bsf
TRISC,3 ;
SCL input
bsf TRISC,4
;
SDA input
movlw b'0x08'
; modo Master
movwf SSPCON1
clrf SSPSTAT
; SMP=CKP=0
movlw 0x18
; programma BRG
movwf
SSPADD
bsf
SSPCON1,SSPEN ;
accendi MSSP |
Operazioni in modo Master
Quando il Master è abilitato, l' utente può avviare le seguenti
operazioni:
- Generazione della condizione di Start
- Generazione della condizione di Restart
- Scrivere dati/indirizzi sul bus (Master trasmettitore)
- Ricevere dati dal bus (Master ricevitore)
- Generare un ACK o un NACK alla fine della ricezione di un byte di dati
- Generare la condizione di Stop
I dispositivi Master sono i soli a poter generare sul bus gli impulsi di clock seriale e le
condizioni di Start e Stop.
La sessione inizia con la condizione di Start e un trasferimento è chiuso con una condizione di
Stop o con
un Restart.
La differenza tra Stop e Restart è la seguente:
- Stop indica allo Slave che il Master ha chiuso la comunicazione e
il bus viene rilasciato. Un altro Master può intervenire e
prenderne il controllo.
- Restart indica allo Slave che il Master ha chiuso la
comunicazione corrente, ma non intende perdere il controllo del, dato che
darà subito inizio ad un nuovo trasferimento, sulla stessa o su un' altra
periferica. Il bus I2C non verrà rilasciato.
In modalità Master trasmettitore, i dati seriali sono in uscita attraverso
SDA, mentre SCL
emette il clock sincrono. Il primo byte trasmesso dopo lo Start contiene l'indirizzo dello
Slave richiesto (7 bit) e il bit di lettura/scrittura (R/W). In questo caso, il bit
R/W sarà
a 0 (write).
I dati seriali sono trasmessi a blocchi di 8 bit; dopo la trasmissione ogni byte, viene
atteso un ACK dalla periferica, che, con questo, conferma la
corretta ricezione del dato.
In modalità ricezione del Master, il primo byte trasmesso contiene
l'indirizzo di
Slave del dispositivo trasmittente (7 bit) e il bit R/W. In questo caso, il bit
R/W sarà
a 1 (read): il primo byte trasmesso è un indirizzo di 7 bit , seguito da un '1' per indicare il bit di ricezione.
I dati seriali sono ricevuti tramite
SDA, mentre SCL
è l' uscita del clock.Dopo aver ricevuto ogni byte, viene trasmesso un
bit di ACK dalla periferica, che, con questo, conferma la
corretta ricezione del dato.
Va notato che, essendo I2C un sistema multi-Master,
un Master potrà essere chiamato da un' altro Master per uno scambio di dati.
Un microcontroller quindi, quindi, potrà assumere sia le funzioni di Master
che quelle di Slave.
In condizione Slave, sarà dotato di un indirizzo che servirà ad altri Master
per la chiamata.
Per contro, uno Slave non potrà iniziare una comunicazione, ma si limiterà a
rispondere alle richieste di un Master. |
Il generatore di Baud Rate utilizzato per il funzionamento in modalità SPI viene utilizzato per
anche per impostare la frequenza di clock SCL, tipicamente 100 kHz, 400 kHz o 1 MHz.
Una sequenza di trasmissione tipica
può essere la seguente:
- l'utente genera una condizione di
Start impostando il bit di Start, SEN (SSPCON2 <0>) = 1.
- Il modulo MSSP dovrà attendere
il completamento della operazione richiesta prima di avviare qualsiasi altra operazione,
verificando se il bit SSPIF è settato.
- L'utente carica il SSPBUF con l'indirizzo
dello Slave a cui trasmettere.
- L' indirizzo è shiftato su SDA
partendo dal bit più significativo.
- Il modulo MSSP riceve l' ACK
dal dispositivo Slaves e aggiorna il registro SSPCON2.
- Il modulo MSSP genera un interrupt alla fine del
nono impulso di clock, settando il bit SSPIF.
- L'utente carica SSPBUF con il
byte dei dati.
- I dati sono shiftati sul pin SDA fino a quando tutti gli 8 bit
sono trasmessi.
- Il modulo MSSP riceve l' ACK
dal dispositivo Slave e aggiorna il registro SSPCON2.
- Il modulo MSSP genera un interrupt alla fine del del
nono impulso di clock, settando il bit SSPIF.
- L'utente genera una condizione di
Stop impostando il bit di Stop PEN (SSPCON2
2) = 1.
- Un interrupt viene generato una volta che è la condizione di
Stop
è stata completata
Alcuni esempi in Assembly e C per la gestione della trasmissione in
polling.
Il modulo MSSP svolge interamente le funzioni di gestione dei pin di
controllo del bus e delle relative temporizzazioni in modo del tutto
trasparente all' utente: per generare una condizione, ad esempio, basta
semplicemente settare un bit in un registro di controllo !
Avvertenze:
- Se il modulo MSSP
automatizza al massimo le condizioni sul bus, la gestione
della logica del protocollo è interamente a carico dell'
Utente.
- Molto importante
avere presente che il
modulo MSSP in modo Master non supporta l' accodamento degli
eventi.
Ad esempio, se l' utente ha comandato uno Start, non può
immediatamente scrivere SSPBUF, ma deve attendere il completamento
dell' operazione precedente (che può richiedere un certo tempo).
In un caso come questo SSPBUF non sarà scritto e il bit di
collisione WCOL sarà settato, indicando la situazione
anomala.
|
Quindi, una gestione tipica della
comunicazione sarà costituita da macchine a stati il cui passaggio allo
stato successivo sarà ammesso alla conclusione dello stato precedente.
Vediamo alcuni semplici esempi di codice
per generare le varie condizioni.
Generare una condizione di Start
Per generare uno Start basta settare il bit SEN in SSPCON2:
; genera condizione di Start
bsf SSPONC2,
SEN |
oppure, in C:
/*genera condizione di Start*/
SSPONC2bits.SEN = 1 ; |
Il modulo MSSP si prende carico delle temporizzazioni e del controllo dei
pin del bus necessari
Occorre sempre verificare che la condizione sia
completata.
Lo stesso
bit utilizzato per la generazione, portandolo a livello alto (1), servirà
da indicatore della conclusione dell' operazione, che azzera il bit:
; verifica esecuzione Start
completata
vcsc
btfsc SSPONC2,
SEN
bra vcsc |
oppure, in C:
/*verifica
esecuzione Start completata*/
while
(SSPONC2bits.SEN); |
Prima di poter occupare il bus occorre verificare che esso
sia libero (idle), per evitare una collisone con un' altro dispositivo che
stia trasmettendo in quel momento. Occorre anche verificare che ogni dato in
SSPBUF sia stato ricevuto o inviato completamente:
; verifica per il bus idle
(subroutine)
i2cbus_idle movlw
0x1F
andwf SSPCON2, W
; verifica se le prime 5 condizioni
; di busy non sono attivate
bz test_wr
; se no, prossimo test
bra
i2cbus_idle
; se si, resta in attesa
test_wr btfsc
SSPSTAT,R_W ; check
status trasmissione
bra
test_wr
; se si, resta in attesa
return
; se no, fine test |
oppure, in C:
/*verifica
esecuzione Start completata*/
void 12c_idle
(void)
{
while ((SSPONC2 & 0x1F) |
SSPSTATbits.R_W);
} |
Generare una condizione di Restart
Del tutto analogamente a quanto visto per lo Start, anche per il Restart il
bit RSEN in SSPCON2:
; genera condizione di Restart
bsf SSPONC2,
RSEN |
oppure, in C:
/*genera condizione di
Restart*/
SSPONC2bits.RSEN = 1 ; |
Il modulo MSSP si prende carico delle temporizzazioni e del controllo dei
pin del bus necessari
Occorre sempre verificare che la condizione sia completata, ad esempio
con::
; verifica esecuzione Restart
completata
vcpc
btfsc SSPONC2,
RSEN
bra vcpc |
oppure, in C:
/*verifica
esecuzione Restart
completata*/
while
(SSPONC2bits.RSEN) ; |
Si ricorda che la condizione di Restart è valida solamente se è già
stata emessa una condizione di Start.
Generare una condizione di Stop
Del tutto analogamente a quanto visto per lo Start, anche per lo Stop basta
agire su un bit, il bit PEN in SSPCON2:
; genera condizione di Stop
bsf SSPONC2,
PEN |
oppure, in C:
/* genera condizione di Stop*/
SSPONC2bits.PEN = 1 ; |
Il modulo MSSP si prende carico delle temporizzazioni e del controllo dei
pin del bus necessari
Occorre sempre verificare che la condizione sia completata, ad esempio
con::
; verifica esecuzione Stop
completata
vcpc
btfsc SSPONC2,
PEN
bra vcpc |
oppure, in C:
/
verifica esecuzione Stop
completata/
while (SSPONC2bits.PEN) ; |
Si ricorda che la condiz ione
di Stop
è valida solamente se è già stata emessa una condizione di Start
oppure un Restart.
Scrivere
un byte sul bus
Anche la scrittura di un byte sul bus è automatizzata al
massimo.
Il byte da trasmettere viene semplicemente scritto nel registro SSPBUF;
il modulo MSSP provvederà autonomamente alla trasmissione, generando i bit
sulla linea SDA e il clock sincrono su SCL con le corrette
temporizzazioni.
Ovviamente il bus dovrà:
Ecco una possibile subroutine che invia il dato in WREG sul bus I2C:
; verifica per il bus idle
i2cbus_wr movwf
savew ;
salva dato in WREG
rcal
i2cbus_idle
; verifica se il bus è libero
movf
savew, W ;
recupera dato
movwf
SSPBUF
; e trsmetti
i2cbus_wre
btfsc SSPSTAT,BF
;
attesa fine trasmissione
bra
i2cbus_wre
; se no, resta in attesa
return
; se si, fine trasmissione |
oppure, in C:
/*verifica
esecuzione Start completata*/
void i2cbus_wr
(unsigned char dat)
{
i2cbus_idle
();
SSPBUF = dat
while (SSPDATbits.BF);
} |
Ricevere
un byte dal bus
Il byte inviato sul bus da un' altra periferica viene raccolto
nel registro SSPSR e, completati gli 8 bit, passato al registro SSPBUF.
Anche qui il modulo MSSP si incarica di tutte le operazioni connesse.
Il flag BF di SSPSTAT conferma il completamento. La ricezione viene
abilitata con il bit RCEN di SSPCON2.
Ecco una possibile subroutine per effettuare l' operazione, rientrando con il
dato ricevuto in WREG.:
; verifica per il bus idle
i2cbus_rd bsf
SSPCON2, RCEN ; abilita ricezione
i2c_rdl rbtfss SSPSTAT,
BF
;
attesa fine ricezione
bra
i2c_rdl
movf
SSPBUF, W ;
recupera dato
return
; fine ricezione |
oppure, in C:
/*verifica
esecuzione Start completata*/
unsigned char i2cbus_rd
(void)
{
SSSPCON2bits.RCEN
= 1 ;
while (!SSPDATbits.BF);
return (SSPBUF) ;
} |
Generazione
di ACK o NACK sul bus
Se l' operazione di ricezione è andata a buon fine,
occorrerà generare un ACK sul bus. Anche qui il modulo MSSP si occupa delle
temporizzazioni hardware, ma resta all' utente la gestione della struttura logica
connessa.
Da osservare che ACK e NACK sono avviate entrambe con il bit ACKEN, dopo di
che il modulo MSSP si
incarica di tutte le operazioni connesse. Per
contro, la polarità della condizione (ACK a livello basso e NACK a livello
alto su SDA) viene programmata con il bit ACKDT, sempre in SSPCON2,
prima di
avviare l'esecuzione della condizione.
; genera ACK
i2cbus_ack bcf
SSPCON2, ACKDT ; reset bit per
acknowledge
bsf
SSPCON2,
ACKEN
;
inizia sequenza di ACK |
oppure, in C:
/*verifica
esecuzione Start completata*/
void i2cbus_ack
(void)
{
SSPCON2bits.ACKDT
= 0 ;
SSPCON2bits.ACKEN = 1 ;
} |
Identicamente per il NACK
; genera NACK
i2cbus_nac bsf
SSPCON2, ACKDT ; set bit per
not-acknowledge
bsf
SSPCON2,
ACKEN
;
inizia sequenza di NACK |
oppure, in C:
/*verifica
esecuzione Start completata*/
void i2cbus_nac
(void)
{
SSPCON2bits.ACKDT
= 1 ;
SSPCON2bits.ACKEN = 1 ;
} |
E'
molto consigliabile il
raccogliere le varie sequenze di comandi come macro
e subroutine in Assembly.
Il C
e altri linguaggi ad alto livello
offrono
librerie
specifiche di comandi (funzioni) per la gestione del modulo
MSSP.
|
|