- Cos'è il protocollo di comunicazione I2C?
- Come funziona la comunicazione I2C?
- Dove utilizzare la comunicazione I2C?
- I2C con PIC16F877a utilizzando il compilatore XC8
- Programmazione utilizzando i file di intestazione I2C:
- Simulazione di Proteus:
I microcontrollori PIC sono una potente piattaforma fornita da microchip per progetti embedded, la sua natura versatile ha fatto sì che trovassero strade in molte applicazioni e la fase è ancora in corso. Se hai seguito i nostri tutorial PIC, avresti notato che abbiamo già coperto un'ampia gamma di tutorial sul microcontrollore PIC partendo dalle basi. Da ora, abbiamo coperto le basi, possiamo entrare in cose più interessanti come il portale di comunicazione.
Nel vasto sistema di applicazioni embedded, nessun microcontrollore può eseguire da solo tutte le attività. Ad un certo punto del tempo deve comunicare con altri dispositivi per condividere informazioni, ci sono molti diversi tipi di protocolli di comunicazione per condividere queste informazioni, ma i più utilizzati sono USART, IIC, SPI e CAN. Ogni protocollo di comunicazione ha i suoi vantaggi e svantaggi. Concentriamoci sulla parte IIC per ora poiché è ciò che impareremo in questo tutorial.
Cos'è il protocollo di comunicazione I2C?
Il termine IIC sta per " Inter Integrated Circuits ". Normalmente è indicato come I2C o I al quadrato C o anche come protocollo di interfaccia a 2 fili (TWI) in alcuni punti, ma significa tutto lo stesso. I2C è un protocollo di comunicazione sincrono che significa che entrambi i dispositivi che condividono le informazioni devono condividere un segnale di clock comune. Ha solo due fili per condividere le informazioni di cui uno viene utilizzato per il segnale del rubinetto e l'altro viene utilizzato per inviare e ricevere dati.
Come funziona la comunicazione I2C?
La comunicazione I2C è stata introdotta per la prima volta da Phillips. Come detto in precedenza, ha due fili, questi due fili saranno collegati tra due dispositivi. Qui un dispositivo è chiamato master e l'altro dispositivo è chiamato slave. La comunicazione dovrebbe e avverrà sempre tra due un Master e uno Slave. Il vantaggio della comunicazione I2C è che più di uno slave può essere collegato a un Master.
La comunicazione completa avviene attraverso questi due fili, ovvero Serial Clock (SCL) e Serial Data (SDA).
Serial Clock (SCL): condivide il segnale di clock generato dal master con lo slave
Dati seriali (SDA): invia i dati da e verso il master e lo slave.
In qualsiasi momento solo il master potrà avviare la comunicazione. Poiché nel bus è presente più di uno slave, il master deve fare riferimento a ciascuno slave utilizzando un indirizzo diverso. Quando viene indirizzato solo il balsamo con quel particolare indirizzo risponderà con le informazioni mentre gli altri continuano a smettere. In questo modo possiamo utilizzare lo stesso bus per comunicare con più dispositivi.
Dove utilizzare la comunicazione I2C?
La comunicazione I2C viene utilizzata solo per comunicazioni a breve distanza. È certamente affidabile in una certa misura poiché ha un impulso di clock sincronizzato per renderlo intelligente. Questo protocollo viene utilizzato principalmente per comunicare con sensori o altri dispositivi che devono inviare informazioni a un master. È molto utile quando un microcontrollore deve comunicare con molti altri moduli slave utilizzando un minimo di soli fili. Se stai cercando una comunicazione a lungo raggio dovresti provare RS232 e se stai cercando una comunicazione più affidabile dovresti provare il protocollo SPI.
I2C con PIC16F877a utilizzando il compilatore XC8
Basta con le presentazioni, entriamoci e impariamo come possiamo usare un microcontrollore per eseguire la comunicazione I2C. Prima di iniziare chiarire che questo tutorial parla solo di I2C in PIC16F877a utilizzando il compilatore XC8, il processo sarà lo stesso per altri microcontrollori ma potrebbero essere necessarie lievi modifiche. Ricorda anche che per microcontrollori avanzati come la serie PIC18F il compilatore stesso potrebbe avere alcune librerie integrate per utilizzare le funzionalità I2C, ma per PIC16F877A non esiste nulla del genere, quindi costruiamone una da soli. La libreria spiegata qui verrà fornita come file di intestazione per il download in basso che può essere utilizzato per PIC16F877A per comunicare con altri dispositivi I2C.
Come sempre il posto migliore per iniziare qualsiasi cosa è la nostra scheda tecnica. Cerca i dettagli su I2C nella scheda tecnica e controlla quali registri devono essere configurati. Non ho intenzione di spiegarlo in dettaglio poiché la scheda tecnica lo ha già fatto per te. Più avanti spiegherò le diverse funzioni presenti nel file di intestazione e la loro responsabilità nel programma.
void I2C_Initialize ()
La funzione di inizializzazione viene utilizzata per dire al microcontrollore che utilizzeremo il protocollo I2C. Questo può essere fatto impostando i bit richiesti sul registro SSPCON e SSPCON2. Il primo passo sarebbe dichiarare i pin IIC come pin di input, qui i pin RC3 e RC4 dovrebbero essere usati per la comunicazione I2C quindi li dichiariamo come pin di input. Successivamente dovremmo impostare SSPCON e SSPCON2 che è un registro di controllo MSSP. Stiamo utilizzando il PIC in modalità master IIC con una frequenza di clock di FOSC / (4 * (SSPADD + 1)). Fare riferimento ai numeri di pagina del foglio dati menzionati nelle righe di commento seguenti per capire perché quel particolare registro è impostato in questo modo.
Quindi dobbiamo impostare la frequenza di clock, la frequenza di clock per diverse applicazioni potrebbe variare, quindi otteniamo la scelta dall'utente tramite la variabile feq_k e la usiamo nelle nostre formule per impostare il registro SSPADD.
void I2C_Initialize (const unsigned long feq_K) // Inizia IIC come master { TRISC3 = 1; TRISC4 = 1; // Imposta i pin SDA e SCL come pin di ingresso SSPCON = 0b00101000; // pg84 / 234 SSPCON2 = 0b00000000; // pg85 / 234 SSPADD = (_XTAL_FREQ / (4 * feq_K * 100)) - 1; // Impostazione della velocità di clock pg99 / 234 SSPSTAT = 0b00000000; // pg83 / 234 }
Void I2C_Hold ()
La prossima funzione importante è la funzione I2C_hold che viene utilizzata per sospendere l'esecuzione del dispositivo fino al completamento dell'operazione I2C corrente. Dovremmo controllare se le operazioni I2C devono essere mantenute prima di iniziare qualsiasi nuova operazione. Questo può essere fatto controllando il registro SSPSTAT e SSPCON2. Lo SSPSTAT contiene le informazioni sullo stato del bus I2C.
Il programma potrebbe sembrare un po 'complicato poiché coinvolge un operatore "e" e un "o". Quando lo rompi come
SSPSTAT e 0b00000100 SSPCON2 e 0b00011111
Significa che ci stiamo assicurando che il 2 ° bit su SSPSTAT sia zero e allo stesso modo i bit da 0 a 4 siano zero su SSPCON2. Quindi combiniamo tutti questi per verificare che il risultato sia zero. Se il risultato è zero, il programma procederà, altrimenti rimarrà lì finché non diventa zero poiché viene utilizzato in un ciclo while .
void I2C_Hold () { while ((SSPCON2 & 0b00011111) - (SSPSTAT & 0b00000100)); // controlla questo nei registri per assicurarti che l'IIC non sia in corso }
Void I2C_Begin () e void I2C_End ()
Ogni volta che scriviamo o leggiamo dati utilizzando il bus I2C dovremmo iniziare e terminare la connessione I2C. Per iniziare una comunicazione I2C dobbiamo impostare il bit SEN e per terminare la comunicazione dobbiamo impostare il bit di stato PEN. Prima di commutare uno qualsiasi di questi bit, dovremmo anche controllare se il bus I2C è occupato utilizzando la funzione I2C_Hold come discusso sopra.
void I2C_Begin () { I2C_Hold (); // Mantieni il programma se I2C è occupato SEN = 1; // Begin IIC pg85 / 234 } void I2C_End () { I2C_Hold (); // Mantieni il programma se I2C è occupato PEN = 1; // Fine IIC pg85 / 234 }
Void I2C_Write ()
La funzione di scrittura viene utilizzata per inviare qualsiasi dato dal modulo master al modulo salve. Questa funzione viene normalmente utilizzata dopo una funzione di inizio I2C ed è seguita da una funzione di fine I2C. I dati che devono essere scritti sul bus IIC vengono passati attraverso i dati variabili. Questi dati vengono quindi caricati nel registro buffer SSPBUF per inviarli tramite il bus I2C.
Normalmente prima di scrivere un dato verrà scritto un indirizzo, quindi dovresti usare la funzione di scrittura due volte, una per impostare l'indirizzo e l'altra per inviare i dati effettivi.
void I2C_Write (dati non firmati) { I2C_Hold (); // Mantieni il programma se I2C è occupato SSPBUF = dati; // pg82 / 234 }
corto senza segno I2C_Read ()
L'ultima funzione che dobbiamo conoscere è la funzione I2C_Read . Questa funzione viene utilizzata per leggere i dati che si trovano attualmente sul bus I2C. Viene utilizzato dopo aver chiesto a uno slave di scrivere un valore sul bus. Il valore che viene ricevuto sarà nel SSPBUF possiamo trasferire quel valore a qualsiasi variabile per la nostra operazione.
Durante una comunicazione I2C, lo slave dopo aver inviato i dati richiesti dal Master invierà un altro bit che è il bit di riconoscimento, anche questo bit dovrebbe essere controllato dal master per assicurarsi che la comunicazione sia andata a buon fine. Dopo aver controllato il bit ACKDT per il riconoscimento, dovrebbe essere abilitato impostando il bit ACKEN.
unsigned short I2C_Read (unsigned short ack) { unsigned short incoming; I2C_Hold (); RCEN = 1; I2C_Hold (); in arrivo = SSPBUF; // recupera i dati salvati in SSPBUF I2C_Hold (); ACKDT = (ack)? 0: 1; // controlla se ack bit ricevuto ACKEN = 1; // pg 85/234 return in arrivo; }
Cioè, queste funzioni dovrebbero essere sufficienti per impostare una comunicazione I2C e scrivere o leggere dati da un dispositivo. Notare inoltre che ci sono molte altre funzionalità che la comunicazione I2C può eseguire, ma per semplicità non le discuteremo qui. Potete sempre fare riferimento alla scheda tecnica per conoscere il completo funzionamento del
Il codice completo con il file di intestazione per la comunicazione I2C PIC16F877A può essere scaricato dal link.
Programmazione utilizzando i file di intestazione I2C:
Ora che abbiamo imparato come funziona una comunicazione I2C e come possiamo usare il file di intestazione creato per essa, creiamo un semplice programma in cui useremo il file di intestazione e scriveremo alcuni valori nelle righe I2C. Quindi simuleremo questo programma e controlleremo se questi valori vengono scritti sul bus.
Come sempre, il programma inizia con l'impostazione dei bit di configurazione e l'impostazione della frequenza di clock a 20 MHz come mostrato di seguito
#pragma config FOSC = HS // Bit di selezione dell'oscillatore (oscillatore HS) #pragma config WDTE = OFF // Bit di abilitazione del timer watchdog (WDT disabilitato) #pragma config PWRTE = ON // Bit di abilitazione del timer di accensione (PWRT abilitato) # pragma config BOREN = ON // Bit di abilitazione reset brown-out (BOR abilitato) #pragma config LVP = OFF // Bit di abilitazione programmazione seriale in-circuit a bassa tensione (alimentazione singola) (RB3 è I / O digitale, HV on MCLR deve essere utilizzato per la programmazione) #pragma config CPD = OFF // Bit di protezione codice memoria EEPROM dati (protezione codice EEPROM dati disattivata) #pragma config WRT = OFF // Bit di abilitazione scrittura memoria programma flash (protezione da scrittura disattivata; tutta la memoria programma può essere scritto dal controllo EECON) #pragma config CP = OFF // Bit di protezione del codice della memoria del programma Flash (protezione del codice disattivata) #define _XTAL_FREQ 20000000
Il prossimo passo sarebbe aggiungere il file di intestazione di cui abbiamo appena discusso. Il file di intestazione è denominato PIC16F877a_I2C.he può essere scaricato dal collegamento discusso sopra. Assicurati che il file di intestazione sia aggiunto nel file di intestazione del tuo elenco di progetti, la struttura del file di progetto dovrebbe essere simile a questa
Dopo esserti assicurato che il file di intestazione sia stato aggiunto al file di progetto, includi il file di intestazione nel file C principale
#includere
All'interno del ciclo while inizieremo la comunicazione I2C scrivendo alcuni valori casuali sul bus I2C e quindi termineremo la comunicazione I2C. I valori casuali che ho scelto sono D0, 88 e FF. Puoi inserire tutti i valori che desideri. Ma ricorda quei valori mentre li verificheremo nella nostra simulazione.
while (1) { I2C_Begin (); I2C_Write (0xD0); I2C_Write (0x88); I2C_Write (0xFF); I2C_End (); __delay_ms (1000); }
Il programma completo si trova in fondo alla pagina, puoi usarlo o scaricare il file zip completo del programma da qui. Dopo aver ottenuto il programma, compilalo e preparati per la simulazione.
Simulazione di Proteus:
Proteus ha un simpatico strumento chiamato debugger I2C che può essere usato per leggere i dati su un bus I2C, quindi costruiamo un circuito usandolo e controlliamo se i dati vengono scritti con successo. Di seguito è mostrato lo schema elettrico completo
Carica il file hex che è stato generato dal nostro programma facendo doppio clic sul microcontrollore. Quindi simula il programma. Noterai una finestra pop-up che mostrerà tutte le informazioni sul bus I2C. Di seguito viene mostrata la finestra del nostro programma.
Se osservi attentamente i dati scritti puoi notare che sono gli stessi che abbiamo scritto nel nostro programma. I valori sono D0, 88 e FF. I valori vengono scritti ogni 1 secondo, quindi anche il tempo si aggiorna come mostrato di seguito. La freccia blu indica che è scritto da master a slave, sarebbe puntato in direzione opposta se altrimenti. Di seguito è mostrato uno sguardo più da vicino ai dati inviati.
Questo è solo un assaggio di ciò che può fare I2C, può anche leggere e scrivere dati su più dispositivi. Tratteremo di più su I2C nei nostri prossimi tutorial interfacciando vari moduli che funzionano con il protocollo I2C.
Spero che tu abbia capito il progetto e imparato qualcosa di utile da esso. Se hai dei dubbi, pubblicali nella sezione commenti qui sotto o usa i forum per assistenza tecnica.
Il codice completo è stato fornito di seguito; puoi scaricare i file di intestazione con tutto il codice da qui.