- Was ist das I2C-Kommunikationsprotokoll?
- Wie funktioniert I2C-Kommunikation?
- Wo kann ich die I2C-Kommunikation nutzen?
- I2C mit PIC16F877a unter Verwendung des XC8-Compilers
- Programmierung mit den I2C-Header-Dateien:
- Proteus-Simulation:
PIC-Mikrocontroller sind eine leistungsstarke Plattform, die von microchip für eingebettete Projekte bereitgestellt wird. Aufgrund ihrer Vielseitigkeit hat sie Wege in viele Anwendungen gefunden, und die Phase ist noch nicht abgeschlossen. Wenn Sie unseren PIC-Tutorials gefolgt sind, haben Sie bemerkt, dass wir bereits eine breite Palette von Tutorials zum PIC-Mikrocontroller behandelt haben, beginnend mit den Grundlagen. Seitdem haben wir die Grundlagen behandelt, die wir für interessantere Dinge wie das Kommunikationsportal benötigen.
In dem riesigen System eingebetteter Anwendungen kann kein Mikrocontroller alle Aktivitäten selbst ausführen. Zu einem bestimmten Zeitpunkt muss es mit anderen Geräten kommunizieren, um Informationen auszutauschen. Es gibt viele verschiedene Arten von Kommunikationsprotokollen, um diese Informationen zu teilen. Die am häufigsten verwendeten sind USART, IIC, SPI und CAN. Jedes Kommunikationsprotokoll hat seine eigenen Vor- und Nachteile. Konzentrieren wir uns zunächst auf den IIC-Teil, da wir dies in diesem Tutorial lernen werden.
Was ist das I2C-Kommunikationsprotokoll?
Der Begriff IIC steht für " Inter Integrated Circuits ". Es wird normalerweise an einigen Stellen als I2C oder I im Quadrat C oder sogar als 2-Draht-Schnittstellenprotokoll (TWI) bezeichnet, aber alles bedeutet dasselbe. I2C ist ein synchrones Kommunikationsprotokoll, dh beide Geräte, die die Informationen gemeinsam nutzen, müssen ein gemeinsames Taktsignal gemeinsam nutzen. Es gibt nur zwei Drähte zum Teilen von Informationen, von denen einer für das Hahnsignal und der andere zum Senden und Empfangen von Daten verwendet wird.
Wie funktioniert I2C-Kommunikation?
Die I2C-Kommunikation wurde erstmals von Phillips eingeführt. Wie bereits erwähnt, hat es zwei Drähte, diese beiden Drähte werden über zwei Geräte verbunden. Hier wird ein Gerät als Master und das andere Gerät als Slave bezeichnet. Die Kommunikation sollte und wird immer zwischen einem Master und einem Slave stattfinden. Der Vorteil der I2C-Kommunikation besteht darin, dass mehr als ein Slave mit einem Master verbunden werden kann.
Die vollständige Kommunikation erfolgt über diese beiden Drähte, nämlich Serial Clock (SCL) und Serial Data (SDA).
Serial Clock (SCL): Teilt das vom Master erzeugte Taktsignal mit dem Slave
Serielle Daten (SDA): Sendet die Daten zum und vom Master und Slave.
Zu jedem Zeitpunkt kann nur der Master die Kommunikation initiieren. Da sich mehr als ein Slave im Bus befindet, muss der Master auf jeden Slave mit einer anderen Adresse verweisen. Wenn angesprochen, antwortet nur die Salbe mit dieser bestimmten Adresse mit den Informationen, während die anderen aufhören. Auf diese Weise können wir denselben Bus verwenden, um mit mehreren Geräten zu kommunizieren.
Wo kann ich die I2C-Kommunikation nutzen?
Die I2C-Kommunikation wird nur für die Kurzstreckenkommunikation verwendet. Es ist sicherlich bis zu einem gewissen Grad zuverlässig, da es einen synchronisierten Takt hat, um es intelligent zu machen. Dieses Protokoll wird hauptsächlich zur Kommunikation mit Sensoren oder anderen Geräten verwendet, die Informationen an einen Master senden müssen. Dies ist sehr praktisch, wenn ein Mikrocontroller mit nur wenigen Kabeln mit vielen anderen Slave-Modulen kommunizieren muss. Wenn Sie nach einer Kommunikation über große Entfernungen suchen, sollten Sie RS232 ausprobieren. Wenn Sie nach einer zuverlässigeren Kommunikation suchen, sollten Sie das SPI-Protokoll ausprobieren.
I2C mit PIC16F877a unter Verwendung des XC8-Compilers
Genug der Einführungen, lassen Sie uns darauf eingehen und lernen, wie wir einen Mikrocontroller für die Durchführung der I2C-Kommunikation verwenden können. Bevor wir klarstellen, dass in diesem Lernprogramm nur I2C in PIC16F877a mit dem XC8-Compiler behandelt wird, ist der Vorgang für andere Mikrocontroller derselbe, es sind jedoch möglicherweise geringfügige Änderungen erforderlich. Denken Sie auch daran, dass der Compiler selbst für fortgeschrittene Mikrocontroller wie die PIC18F-Serie möglicherweise eine Bibliothek eingebaut hat, um die I2C-Funktionen zu nutzen. Für PIC16F877A gibt es jedoch nichts Vergleichbares. Erstellen wir also eine eigene. Die hier erläuterte Bibliothek wird unten als Header-Datei zum Download bereitgestellt, mit der PIC16F877A mit anderen I2C-Geräten kommunizieren kann.
Wie immer ist unser Datenblatt der beste Ausgangspunkt. Suchen Sie im Datenblatt nach Details zu I2C und prüfen Sie, welche Register konfiguriert werden müssen. Ich werde nicht im Detail erklären, da das Datenblatt dies bereits für Sie getan hat. Weiter unten werde ich die verschiedenen Funktionen in der Header-Datei und ihre Verantwortung im Programm erläutern.
void I2C_Initialize ()
Die Initialisierungsfunktion wird verwendet, um dem Mikrocontroller mitzuteilen, dass wir das I2C-Protokoll verwenden werden. Dies kann durch Setzen der erforderlichen Bits im SSPCON- und SSPCON2-Register erfolgen. Der erste Schritt wäre , die IIC-Pins als Eingangspins zu deklarieren. Hier sollten die Pins RC3 und RC4 für die I2C-Kommunikation verwendet werden, damit wir sie als Eingangspins deklarieren. Als nächstes sollten wir SSPCON und SSPCON2 setzen, die ein MSSP-Steuerregister sind. Wir betreiben den PIC im IIC-Master-Modus mit einer Taktfrequenz von FOSC / (4 * (SSPADD + 1)). Lesen Sie die Seitenzahlen des Datenblatts in den Kommentarzeilen unten, um zu verstehen, warum dieses bestimmte Register so eingestellt ist.
Als nächstes müssen wir die Taktfrequenz einstellen, die Taktfrequenz für verschiedene Anwendungen kann variieren, daher erhalten wir vom Benutzer die Wahl über die Variable feq_k und verwenden sie in unseren Formeln, um das SSPADD-Register einzustellen.
void I2C_Initialize (const unsigned long feq_K) // IIC als Master starten { TRISC3 = 1; TRISC4 = 1; // SDA- und SCL-Pins als Eingangspins setzen SSPCON = 0b00101000; // pg84 / 234 SSPCON2 = 0b00000000; // pg85 / 234 SSPADD = (_XTAL_FREQ / (4 * feq_K * 100)) - 1; // Einstellen der Taktrate pg99 / 234 SSPSTAT = 0b00000000; // pg83 / 234 }
Leere I2C_Hold ()
Die nächste wichtige Funktion ist die I2C_hold- Funktion, mit der die Ausführung des Geräts gehalten wird, bis die aktuelle I2C-Operation abgeschlossen ist. Wir müssten prüfen, ob die I2C-Operationen gehalten werden müssen, bevor wir eine neue Operation starten. Dies kann durch Überprüfen der Register SSPSTAT und SSPCON2 erfolgen. Der SSPSTAT enthält Informationen zum Status des I2C-Busses.
Das Programm scheint etwas kompliziert zu sein, da es einen "und" - und einen "oder" -Operator enthält. Wenn Sie es brechen als
SSPSTAT & 0b00000100 SSPCON2 & 0b00011111
Es bedeutet, dass wir dafür sorgen, dass 2 nd Bit auf SSPSTAT Null ist und in ähnlicher Weise Bits 0-4 Null auf SSPCON2 sind. Dann kombinieren wir alle diese, um zu überprüfen, ob das Ergebnis Null ist. Wenn das Ergebnis Null ist, fährt das Programm fort, wenn es nicht dort bleibt, bis es Null wird, da es in einer while- Schleife verwendet wird.
void I2C_Hold () { while ((SSPCON2 & 0b00011111) - (SSPSTAT & 0b00000100)); // Überprüfen Sie diese Register, um sicherzustellen, dass das IIC nicht ausgeführt wird. }
Leere I2C_Begin () und Leere I2C_End ()
Jedes Mal, wenn wir Daten über den I2C-Bus schreiben oder lesen, sollten wir die I2C-Verbindung beginnen und beenden. Um eine I2C-Kommunikation zu beginnen, müssen wir das SEN-Bit setzen und um die Kommunikation zu beenden, müssen wir das PEN-Statusbit setzen. Bevor Sie eines dieser Bits umschalten, sollten Sie auch überprüfen, ob der I2C-Bus ausgelastet ist, indem Sie die oben beschriebene Funktion I2C_Hold verwenden.
void I2C_Begin () { I2C_Hold (); // Halte das Programm gedrückt I2C ist beschäftigt SEN = 1; // IIC starten pg85 / 234 } void I2C_End () { I2C_Hold (); // Halte das Programm gedrückt I2C ist beschäftigt PEN = 1; // IIC beenden pg85 / 234 }
Leere I2C_Write ()
Mit der Schreibfunktion werden alle Daten vom Master-Modul an das Salve-Modul gesendet. Diese Funktion wird normalerweise nach einer I2C-Startfunktion verwendet, gefolgt von einer I2C-Endfunktion. Die Daten, die auf den IIC-Bus geschrieben werden müssen, werden durch die variablen Daten geleitet. Diese Daten werden dann in das SSPBUF-Pufferregister geladen, um sie über den I2C-Bus zu senden.
Normalerweise wird vor dem Schreiben von Daten eine Adresse geschrieben, sodass Sie die Schreibfunktion zweimal verwenden müssen, einmal zum Festlegen der Adresse und zum anderen Mal zum Senden der tatsächlichen Daten.
void I2C_Write (vorzeichenlose Daten) { I2C_Hold (); // Halten Sie das Programm ist I2C ist beschäftigt SSPBUF = data; // pg82 / 234 }
unsigned short I2C_Read ()
Die letzte Funktion, die wir kennen müssen, ist die I2C_Read- Funktion. Mit dieser Funktion werden die Daten gelesen, die sich derzeit auf dem I2C-Bus befinden. Es wird verwendet, nachdem ein Slave aufgefordert wurde, einen Wert in den Bus zu schreiben. Der empfangene Wert befindet sich im SSPBUF. Wir können diesen Wert für unsere Operation auf eine beliebige Variable übertragen.
Während einer I2C-Kommunikation sendet der Slave nach dem Senden der vom Master angeforderten Daten ein weiteres Bit, das das Bestätigungsbit ist. Dieses Bit sollte auch vom Master überprüft werden, um sicherzustellen, dass die Kommunikation erfolgreich war. Nachdem das ACKDT-Bit auf Bestätigung überprüft wurde, sollte es durch Setzen des ACKEN-Bits aktiviert werden.
unsigned short I2C_Read (unsigned short ack) { unsigned short incoming; I2C_Hold (); RCEN = 1; I2C_Hold (); eingehend = SSPBUF; // die in SSPBUF gespeicherten Daten abrufen I2C_Hold (); ACKDT = (ack) 0: 1; // überprüfe ob das Bestätigungsbit empfangen wurde ACKEN = 1; // S. 85/234 return incoming; }}
Das heißt, diese Funktionen sollten ausreichen, um eine I2C-Kommunikation einzurichten und Daten von einem Gerät zu schreiben oder zu lesen. Beachten Sie auch, dass die I2C-Kommunikation viele andere Funktionen ausführen kann. Der Einfachheit halber werden sie hier jedoch nicht behandelt. Sie können jederzeit auf das Datenblatt verweisen, um die vollständige Funktionsweise des zu erfahren
Der vollständige Code mit der Header-Datei für die I2C-Kommunikation mit PIC16F877A kann über den Link heruntergeladen werden.
Programmierung mit den I2C-Header-Dateien:
Nachdem wir gelernt haben, wie eine I2C-Kommunikation funktioniert und wie wir die dafür erstellte Header-Datei verwenden können, erstellen wir ein einfaches Programm, in dem wir die Header-Datei verwenden und einige Werte in die I2C-Zeilen schreiben. Wir werden dann dieses Programm simulieren und prüfen, ob diese Werte auf den Bus geschrieben werden.
Wie immer beginnt das Programm mit dem Einrichten der Konfigurationsbits und dem Einstellen der Taktfrequenz auf 20 MHz, wie unten gezeigt
#pragma config FOSC = HS // Oszillatorauswahlbits (HS-Oszillator) #pragma config WDTE = OFF // Watchdog-Timer-Aktivierungsbit (WDT deaktiviert) #pragma config PWRTE = ON // Einschalttimer-Aktivierungsbit (PWRT aktiviert) # Pragma-Konfiguration BOREN = EIN // Brown-Out-Reset-Aktivierungsbit (BOR aktiviert) # Pragma-Konfiguration LVP = AUS // Niederspannungs-Einzelprogrammierung (Einzelversorgung) Serielle Programmierung Aktivierungsbit (RB3 ist digitale E / A, HV ein) Für die Programmierung muss MCLR verwendet werden.) #Pragma config CPD = OFF // Daten-EEPROM-Speichercode- Schutzbit (Daten-EEPROM- Codeschutz aus) #pragma config WRT = OFF // Flash-Programmspeicher Schreibaktivierungsbits (Schreibschutz aus; gesamter Programmspeicher kann von der EECON-Kontrolle beschrieben werden) #pragma config CP = OFF // Code-Schutzbit für Flash-Programmspeicher ( Codeschutz aus) #define _XTAL_FREQ 20000000
Der nächste Schritt wäre das Hinzufügen der Header-Datei, über die wir gerade gesprochen haben. Die Header-Datei heißt PIC16F877a_I2C.h und kann über den oben beschriebenen Link heruntergeladen werden. Stellen Sie sicher, dass die Header-Datei in der Header-Datei Ihrer Projektliste hinzugefügt ist. Ihre Projektdateistruktur sollte folgendermaßen aussehen
Nachdem Sie sichergestellt haben, dass die Header-Datei zu Ihrer Projektdatei hinzugefügt wurde, fügen Sie die Header-Datei in die Haupt-C-Datei ein
#einschließen
Innerhalb der while- Schleife beginnen wir mit der I2C-Kommunikation, schreiben einige zufällige Werte auf den I2C-Bus und beenden dann die I2C-Kommunikation. Die zufälligen Werte, die ich ausgewählt habe, sind D0, 88 und FF. Sie können beliebige Werte eingeben. Denken Sie jedoch an diese Werte, da wir sie in unserer Simulation überprüfen werden.
während (1) { I2C_Begin (); I2C_Write (0xD0); I2C_Write (0x88); I2C_Write (0xFF); I2C_End (); __delay_ms (1000); }}
Das vollständige Programm finden Sie unten auf der Seite. Sie können es verwenden oder die vollständige Zip-Datei des Programms von hier herunterladen. Nachdem Sie das Programm erhalten haben, kompilieren Sie es und bereiten Sie sich auf die Simulation vor.
Proteus-Simulation:
Proteus hat ein nettes Instrument namens I2C-Debugger, mit dem die Daten auf einem I2C-Bus gelesen werden können. Lassen Sie uns also eine Schaltung daraus erstellen und prüfen, ob die Daten erfolgreich geschrieben wurden. Das vollständige Schaltbild ist unten dargestellt
Laden Sie die Hex-Datei, die von unserem Programm generiert wurde, indem Sie auf den Mikrocontroller doppelklicken. Dann simulieren Sie das Programm. Es erscheint ein Fenster, in dem alle Informationen zum I2C-Bus angezeigt werden. Das Fenster für unser Programm ist unten dargestellt.
Wenn Sie sich die zu schreibenden Daten genau ansehen, können Sie feststellen, dass sie mit denen übereinstimmen, die wir in unserem Programm geschrieben haben. Die Werte sind D0, 88 und FF. Die Werte werden alle 1 Sekunde geschrieben, sodass auch die Zeit wie unten gezeigt aktualisiert wird. Der blaue Pfeil zeigt an, dass er vom Master zum Slave geschrieben wurde und andernfalls in die entgegengesetzte Richtung zeigt. Ein genauerer Blick auf die gesendeten Daten ist unten dargestellt.
Dies ist nur ein kleiner Einblick in die Funktionen von I2C. Es kann auch Daten lesen und auf mehrere Geräte schreiben. In unseren nächsten Tutorials werden wir mehr über I2C erfahren, indem wir verschiedene Module miteinander verbinden, die mit dem I2C-Protokoll arbeiten.
Ich hoffe, Sie haben das Projekt verstanden und daraus etwas Nützliches gelernt. Wenn Sie irgendwelche Zweifel haben, posten Sie sie im Kommentarbereich unten oder nutzen Sie die Foren für technische Hilfe.
Der vollständige Code wurde unten angegeben. Hier können Sie Header-Dateien mit dem gesamten Code herunterladen.