Dieser Abschnitt beschreibt nun wie ein PIC16Fxx-Mikrocontroller als Slave für den I²C zu konfigurieren ist und welche Software-Routinen notwendig sind.
|
Wichtig:
Damit ein Mikrocontroller vom Typ PIC16Fxx als Slave für den I²C-Bus verwendet werden kann muss dieser über das MSSP-Modul verfügen, und dieser muss den Slave-Mode beinhalten. MSSP steht für Master Synchronous Serial Port. |
Zunächst die Hardwarebeschaltung. Abbildung 2 zeigt die Beschaltung des PIC16Fxx-Mikrocontrollers, wobei auch die Beschaltung des Oszillators X1 entfallen kann, wenn der verwendete PIC16Fxx-Mikrocontroller über einen internen Oszillator verfügt.
Der I²C-Bus mit seinen Leitungen (SDA, SCL, Masse, Betriebsspannung und dem optionalen Interrupt) ist im Bild unten zu sehen. Wesentlich ist hier eigentlich nur, dass die beiden PIC-I/O-Pins SDA und SCL über Schutzwiderstände (R3 bis R5) mit dem I²C-Bus verbunden werden.
Die übrigen Schaltungsteile entsprechen den üblichen PIC16Fxx-Applikationen. Die Schaltung rund um den Quarz X1 erzeugt einen stabilen Systemtakt. Dieser Schaltungsteil kann entweder komplett entfallen falls der verwendete PIC16F-Mikrocontroller einen internen Oszillator besitzt und dieser verwendet wird, oder umschaltbar mit Steckbrücken.
Die PIC16Fxx-Familie lässt sich sehr gut in der Schaltung programmieren. Diese Methode wird ICSP4 genannt. Der Reset wird hier mit einem RC-Glied bestehend aus R1 und C1 erzeugt. Zusätzlich kann ein Reset jederzeit mit dem Taster S1 ausgelöst werden. Da der Reseteingang des Mikrocontrollers (MCLR, Pin 1) auch gleichzeitig die Programmierspannung (ca. 13V) bei der ICSP-Proghrammierung ist, darf während einer Programmierung kein Reset ausgelöst werden. Durch die Diode D1 ist ein Reset durch das RC-Glied (R1 und C1) während einer Programmierung via ICSP nicht möglich.
Die Spannungsversorgung für den Mikrocontroller erfolgt über den I²C-Bus, so dass hier kein extra Schaltungsteil notwendig ist. Ein Koppelkondensator (C4) ist aber empfehlenswert.
Die I²C-Busadresse kann entweder in der Software fix vergeben werden oder über Steckbrüken (Jumper, JP1 bis JP6). Hier wird fast der gesamte Port B dafür verwendet.
Alle übrigen Portpins sind frei verfügbar.
Damit ein PIC16Fxx-Mikrocontroller als Slave für den I²C-Bus verwendet werden kann muss dieser (wie in diesem Dokument schon öfter erwähnt) über ein so genanntes MSSP-Modul verfügen. Dieses Modul ist im Mikrocontroller als Hardware integriert und unterstützt neben dem I²C-Bus einen weiteren seriellen Bus, der hier nicht weiter behandelt wird. Dieses Hardware-Modul muss zunächst für den I²C-Slave-Mode konfigueriert werden. Dazu dienen die folgenden Register:
Wie diese konfiguriert werden müssen zeigen die beiden Demonstrationsbeispiele in Abschnitt 5.
Wichtig ist auch, dass die Portpins (SDA und SCL) als Eingang konfiguriert werden.
Da der Mikrocontroller über ein geeignetes Hardwaremodul verfügt erfolgt die Umsetzung des I²C-Protokolls automatisch, und der Anwender muss sich darum nicht kümmern. Er hat "nur" die Aufgabe die empfangenen Daten rechtzeitig zu lesen und die zu sendenden Daten rechtzeitig zur Verfügung zu stellen. Dieses "rechtzeitig" lässt sich sehr elegant mit einem Interrupt erkennen, die der Mikrocontroller erzeugt. Wichtig ist, dass dieser Interrupt (SSP-Interrupt) freigegeben werden muss! Die Abbildungen 3 und 4 zeigen die Statusbits bei einem Lesebefehl bzw. bei einem Schreibbefehl.
Für den Anwender (Softwarenetwickler) besteht "nur" die Aufgabe zum richtigen Zeitpunkt die zu lesenden Daten abzuholen bzw. die zu
schreibenden Daten zur Verfügung zu stellen. Dazu dienen die zwei Flags R_W und D_A
im Register SSPSTAT. Diese beiden Flags werden automatisch gesetzt oder gelöscht nachdem ein Datenbyte via I²C-Bus empfangen
oder gesendet wurde. Gleichzeitig wird auch das Interrupt-Flag für das SSP-Modul (SSPIF) gesetzt und ein Interrupt ausgelöst,
falls dieser Interrupt freigegeben wurde.
Mit anderen Worten ausgedrückt: Nach jedem empfangene oder gesendeten Byte via I²C-Bus wird der SSP-Interrupt ausgelöst. Dabei gibt das Flag
R_W an, ob die Daten am Bus vom Slave gelesen werden sollen R_W = 0 oder ob der Slave Daten
auf den Bus Schreiben muss R_W = 1. Das Flag D_A gibt an, ob das zuletzt empfangene Byte das
Adressbyte war D_A = 0 oder ob es sich um ein Datenbyte handelt D_A = 1.
Somit ergeben sich die vier Fälle:
| R_W | D_A | Bedeutung |
| 0 | 0 | Daten vom Bus lesen, zuletzt empfangenes Byte war die Slaveadresse |
| 0 | 1 | Daten vom Bus lesen, zuletzt empfangenes Byte war ein Datenbyte |
| 1 | 0 | Daten auf den Bus schreiben, zuletzt empfangenes Byte war die Slaveadresse |
| 1 | 1 | Daten auf den Bus schreiben, zuletzt gesendetes Byte war ein Datenbyte |
Das Flussdiagramm in Abbildung 5 zeigt was in diesen vier Fällen zu tun ist.
Anmerkungen:
Noch ein Hinweise: Leider hat sich herausgestellt, dass meine Software nicht bei jedem PIC16Fxx funktioniert obwohl dieser gemäß dem Datenblatt als I²C-Slave geeignet ist. Den Grund dafür habe ich leider nicht gefunden bzw. ich hatte noch nicht das Bedürfnis diesen Fehler zu suchen. Die nachfolgende Tabelle zeigt mit welche PIC16Fxx-Typen "meine" Software funktioniert und mit welchen nicht. Typen die in dieser Tabelle nicht aufscheinen habe ich (noch) nicht als I²C-Slave getestet.
| Typ | Anz. Pins | funktioniert oder funktioniert nicht |
| PIC16F887 | 40 | funktioniert 😊 |
| PIC16F877 | 40 | funktioniert (leider nicht) 😢 |
4 ICSP steht für In-Circuit-Serial-Programming