I²C-Routinen (für PIC-Mikrocontroller, Elektronik)


zurück zu Elektronik, Homepage


4. Software

Die Aufgabe der Software ist das im Abschnitt I²C-Protokoll beschriebene I²C-Protokoll umzusetzen. Die hier beschriebenen Unterprogramme sind nur notwendig, wenn der verwendete Mikrocontroller kein I²C-Hardwaremodul besitzt. Weiters unterstützt die hier beschrieben Software nur die langsamere Taktgeschwindigkeit (100 kBit/s), und ist für die Standardtaktfrequenz des PIC (4 MHz) ausgelegt.

nach oben

4.1. Benötigte Register und Maske

Für die Realisierung des Softwareprotokolls werden neben einigen PIC internen Register (SFR, Spezielle Funktions-Register) noch folgende Register benötigt:

Anmerkung:
Diese drei Register (TEMP1 bis TEMP3) sind so genannte temporäre Register. D.h. Sie werden nur kurzzeitig verwendet und können daher auch in beliebigen anderen Unterprogrammen verwendet werden.

Wie schon erwähnt benötigt der I²C-Bus eine Takt- und eine Datenleitung. Diese werden im Code wie folgt definiert (siehe auch Abschnitt 5 Demonstrationsbeispiel):

#define        SDA        PORTA,3
#define        SCL        PORTA,4
Anmerkung:
Hier wird für die Softwareimplementierung des I²C-Bus der Port A verwendet, wobei die Datenleitung am Portpin RA3 angeschlossen ist, während der Taktleitung der Portpin RA4 zugeordnet wird. Diese Zuordnung ist natürlich von Projekt zu Projekt unterschiedlich. Es ist auch möglich, dass diese beiden Pins an unterschiedlichen Ports angeschlossen sind. Z. B SDA (Datenleitung) am Port B (genauer am Portpin RB1) und SCL (Taktleitung) am Port C (genauer am Portpin RC3).

nach oben

Initialisierung (Unterprogramm "INIT")

Dieses Unterprogramm dient zur Initialisierung des Mikrocontrollers. Bei diesem Beispiel ist hier, für die impementierung des I²C-Protokolls, nur die Definition der der verwendeten Portpins als Ausgang notwendig.

nach oben

4.3. Unterprogramme für die Nachbildung des I²C-Protokolls

Zur Nachbildung des I²C-Protokolls sind 7 Unterprogramme notwendig:

Nun aber zu den einzelnen Unterprogrammen im Detail:

nach oben

4.3.1. Unterprogramm I2C_START

Aufgabe:
Dieses Unterprogramm erzeugt die Startbedingung.

Zur Erinnerung, die Startbedingung ist wie folgt definiert:
Auf der Datenleitung (SDA) erfolgt eine High-Low-Flanke, während die Taktleitung (SCL) High ist.

Anmerkung:
Die Anweisung call DELAY5 ruft ein Unterprogramm auf, welches eine Verzögerung von 5µs erzeugt. Diese Verzögerungszeit ist notwendig, damit die maximale Taktgeschwindigkeit von 100 kbit/s nicht überschritten wird. (siehe auch DELAY5 und 4.4. Änderung bei Verwendung eines höheren PIC-Takzes als 4MHz)

nach oben

4.3.2. Unterprogramm I2C_STOP

Aufgabe:
Dieses Unterprogramm erzeugt die Stoppbedingung.

Zur Erinnerung, die Stoppbedingung ist wie folgt definiert:
Auf der Datenleitung (SDA) erfolgt eine Low-High-Flanke, während die Taktleitung (SCL) High ist.

Anmerkung:
Die Anweisung call DELAY5 ruft ein Unterprogramm auf, welches eine Verzögerung von 5µs erzeugt. Diese Verzögerungszeit ist notwendig, damit die maximale Taktgeschwindigkeit von 100 kbit/s nicht überschritten wird. (siehe auch DELAY5 und 4.4. Änderung bei Verwendung eines höheren PIC-Takzes als 4MHz)

nach oben

4.3.3. Unterprogramm I2C_BITLESEN

Aufgabe:
Dieses Unterprogramm liest ein Bit vom Slave ein und sichert es im Übergabeflag TEMP3,0. Der für die Datenübertragung erforderliche Takt (Leitung SCL) wird dabei softwaremäßig so erzeugt, dass der Pin SCL von Low (0) auf High (1) gesetzt wird. Nach einer bestimmten Zeit wird SCL wieder auf Low (0) zurückgesetzt. Diese Zeit wird hauptsächlich vom Unterprogramm DELAY5 bestimmt.

Vorgehensweise:

Anmerkung:
Das Bit 0 im temporären Register TEMP3 beinhaltet das gelesene Bit. Dieses Register dient hier nur als Übergaberegister zum übergeordneten Unterprogramm I2C_LESEN. Das Register TEMP3 kann daher auch in anderen Unterprogrammen verwendet werden.

nach oben

4.3.4. Unterprogramm I2C_BITSCHREIBEN

Aufgabe:
Dieses Unterprogramm schreibt das im Übergabeflag TEMP3,1 stehende Bit zum Slave. Der für die Datenübertragung erforderliche Takt (Leitung SCL) wird dabei softwaremäßig so erzeugt, dass der Pin SCL von Low (0) auf High (1) gesetzt wird Nach einer bestimmten Zeit wird SCL wieder auf Low (0) zurückgesetzt. Diese Zeit wird hauptsächlich vom Unterprogramm DELAY5 bestimmt.

Vorgehensweise:

Anmerkung:
Das Bit 1 im temporären Register TEMP3 beinhaltet das zu schreibende Bit. Dieses Register dient hier nur als Übergaberegister vom übergeordneten Unterprogramm I2C_SCHREIBEN. Das Register TEMP3 kann daher auch in anderen Unterprogrammen verwendet werden.

nach oben

4.3.5. Unterprogramm I2C_LESEN

Aufgabe:
Ein Byte vom I²C-Bus bitweise mit Hilfe des Unterprogramms I2C_BITLESEN lesen und im Übergaberegister TEMP1 sichern. Danach ein Bestätigungsbit ausgeben.

Vorgehensweise:

Anmerkung:
Die temporären Register TEMP1 bis TEMP3 dienen hier als Übergabe- oder als Hilfsregister. Diese Register können daher auch in anderen Unterprogrammen verwendet werden.

nach oben

4.3.6. Unterprogramm I2C_SCHREIBEN

Aufgabe:
Das zu schreibende Byte (befindet sich im Übergaberegister TEMP1) bitweise mit Hilfe des Unterprogramms I2C_BITSCHREIBEN auf den I²C-Bus schreiben. Danach ein Bestätigungsbit empfangen.

Vorgehensweise:

Anmerkung:
Die temporären Register TEMP1 bis TEMP3 dienen hier als Übergabe- oder als Hilfsregister. Diese Register können daher auch in anderen Unterprogrammen verwendet werden.

nach oben

4.3.7. Unterprogramm DELAY5

Aufgabe:
Dieses Unterprogramm erzeugt eine Zeitverzögerung von 5 us. Diese Verzögerungszeit ist notwendig, damit die maximale Taktgeschwindigkeit von 100 kbit/s nicht überschritten wird.

Anmerkung:
Bei einer PIC-Taktfrequenz von 4 MHz betragen die hier benötigten Befehle die in den Klammern angegebenen Abarbeitungszeiten (Zykluszeiten)

                call    DELAY5        (2us)
                nop                   (1us)
                return                (2us)

Bei Verwendung einer höheren Taktfrequenz müssen zusätzlich nop-Befehle eingefügt werden!

nach oben

4.4. Änderung bei Verwendung eines höheren PIC-Taktes als 4MHz

Die hier beschriebene Software wurde für die PIC-Standard-Taktfrequenz von 4 MHz beschrieben. eine geringere Taktfrequenz kann problemlos verwendet werde. Nicht aber eine Höhere. Wird eine höhere Taktfrequenz verwendet so muss aber nur das Unterprogramm DELAY5 geändert werden. Dieses Unterprogramm hat ja die Aufgabe die im I²C-Protokoll spezifizierte Taktrate (von 100 kHz) zu erzeugen. Also eine Verzögerung von 5 µs.

Zu beachten ist, dass die Befehle "call" und "return" jeweils zwei Taktzyklen benötigen, während der Befehl "nop" nur einen Taktzyklus benötigt. Als Taktzyklus ist bei der PIC-Familie folgende Formel definiert:

                                               4
                     Taktzyklus [µs] = ------------------
                                       Taktfrequenz [MHz] 

Bei der Standard-Taktfrequenz von 4 MHz gilt also: Die Befehle "call" und "return" benötigen je 2 µs. Dies ergibt zusammen also 4 µs. Für die benötigte Verzögerungszeit von 5 µs sind also noch Befehle notwendig, die eine µs benötigen. Dies entspricht einem "nop"-Befehl, da dieser nur 1 Taktzyklus benötigt, also genau 1µs.

Bei Verwendung eines 10 MHz Taktes gilt:

                                          4
                     Taktzyklus [µs] = ------- = 0.4 µs
                                       10 MHz 

Die Befehle "call" und "return" benötigen je 2 Taktzyklen, also 0.8 µs, der Befehl "nop" benötigt 0.4 µs. Es stellt sich also die Frage wie viele "nop"-Befehle benötigt man für eine Verzögerung von 5 µs. Zieht man von den 5 µs die Zeit für die beiden Befehle "call" und "return" ab, bleiben 3,4 µs übrig. (5 µs – 0,8 µs – 0,8 µs = 3,4 µs). Ein "nop"–Befehl benötigt 0,4 µs. Daraus ergibt sich, dass theoretisch 8,5 "nop"-Befehle notwendig sind (3,4 µs / 0,4 µs = 8,5). Ein halber "nop"-Befehl existiert natürlich nicht! Deshalb müssen 9 "nop"-Befehle verwendet werden.
Das Unterprogramm DELAY5 sieht also bei Verwendung eines 10 MHz-Quarzes wie folgt aus:

DELAY5          nop
                nop
                nop
                nop
                nop
                nop
                nop
                nop
                nop
                return

Eine bessere, "schönere" und vor allem codesparendere Möglichkeit ist die Verwendung einer Schleife anstelle dieser vielen "nop"-Befehle. Würde man für den PIC einen 20-MHz-Takt verwenden, so wären 21 (!) "nop"-Befehle notwendig.

Mit einer Schleife würde das Unterprogramm DELAY5 so aussehen:

Für 10 MHz:
DELAY5          movlw       .3
                movwf       TEMP3
DELAY5SCHL1     decfsz      TEMP3,f
                goto        DELAY5SCHL1
                return
Für 20 MHz:
DELAY5          movlw       .5
                movwf       TEMP3
DELAY5SCHL1     nop
                decfsz      TEMP3,f
                goto        DELAY5SCHL1
                nop
                return
==>Verzögerungszeit: 5.6 µs ==>Verzögerungszeit: 5 µs
nach oben


zurück zu Elektronik, Homepage

Autor: Buchgeher Stefan
Erstellt: 17. Oktober 2003
Letzte Änderung: 10. Oktober 2004