Datenaustausch zwischen zwei (oder mehreren) PIC16Fxx-Mikrocontrollern via I²C in C (Elektronik)

(oder: Wie realisiere ich einen I²C-Slave mit einem PIC16Fxx-Mikrocontroller)

zurück zu Elektronik, Homepage


3. PIC16Fxx als I²C-Slave

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.
nach oben

3.1. Hardware

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.

PIC16Fxx als I²C-Slave, Schaltung

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.

nach oben

3.2. Software

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.

PIC16Fxx als I²C-Slave, Statusbits bei einem Lesebefehl (Auszug aus dem Datenblatt zum PIC16F887)
PIC16Fxx als I²C-Slave, Statusbits bei einem Schreibebefehl (Auszug aus dem Datenblatt zum PIC16F887)

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.

PIC16Fxx als I2C-Slave, Flussdiagramm (Interrupt-Service-Routine)

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) 😢
nach oben

4 ICSP steht für In-Circuit-Serial-Programming

nach oben


zurück zu Elektronik, Homepage

Autor: Stefan Buchgeher
Erstellt: 31. Juli 2014
Letzte Änderung: