Einige PICs
verfügen über einen MSSP-Port (master synchronous serial
port).
Damit lässt sich entweder ein SPI-Bus (Serial Peripheral
Interface)
oder ein I2C-Bus (Inter-Integrated Circuit) aufbauen.
Andere PIC-Typen (z.B. dsPIC)
haben keinen MSSP, sondern getrennte Hardware für I2C und SPI.
Der SPI-Bus ist eine bidirektionale
synchrone
Dreidrahtverbindung. Der I2C-Bus ist ein sehr häufig eingesetzter
2-Draht-Bus.
PICs ohne I2C-Hardware können den I2C-Bus auch per Software emulieren. Wie das geht steht hier.
zu Beginn eine allgemeine
I2C-Beschreibung
Allgemeines
Busverdrahtung
I2C am PIC
Geschwindigkeitseinstellung
Datenfluss
allgemein
ab hier wird
es
spezifisch für 16F876
Initialisierung
Daten auf I2C-Bus
schreiben
Daten vom I2C-Bus
lesen
Beispiel: Daten
zum EEPROM 24C04 schreiben
Beispiel: Daten vom
EEPROM 24C04 lesen
Der I2C-Bus (I2C = IIC = Inter-Integrated-Circuit) wurde von der Firma Philips für die Kommunikation zwischen einzelnen Schaltkreisen innerhalb eines Gerätes entwickelt. Er findet sich z.B. in vielen Geräten der Unterhaltungselektronik. In meinem Videorekorder steuert ein Mikroprozessor den Audioprozessor, den Videoprozessor, den Laufwerkscontroller u.v.m. über den I2C-Bus.
Hinweis:
Auf der
Philips-Homepage
gibt es die Dokumentation des I2C-Busses unter dem Titel 'The I2C-bus
specification'
mit der document order number: 9398 393 40011 zum Download.
Beim I2C-Bus handelt es sich um eine synchrone serielle 2-Drahtverbindung zwischen einem Master und einer beliebigen Anzahl Slaves. Auf der einen Leitung (SCL) wird der Takt übertragen, die andere Leitung (SDA) dient der Übertragung der Daten. Die Daten können vom Controller zum Slave (schreiben) laufen, oder aber auch vom Slave zum Master (lesen). Der Takt wird dabei aber immer vom Master erzeugt. (Der Slave kann allerdings den Low-Teil des Taktes verlängern, indem er ihn so lange auf Low zieht, wie er es für nötig hält.)
Es ist auch möglich an einem Bus mehrere Master zu betreiben (Multi-Master-Bus). In dem Fall ist durch ein Protokoll gesichert, das ein Master den Bus nur übernehmen kann, wenn der Bus gerade nicht in Nutzung durch einen anderen Master ist. Damit werden Buskollisionen verhindert.
Es gibt den I2C-Bus in drei
Geschwindigkeiten:
mit 100 kHz Takt (Standard-Mode), mit 400 kHz-Takt (Fast-Mode) und mit
3,4 MBit/s (high speed). Der high-speed Modus wird von den PICs aber
nicht
unterstützt.
Die Hardware der PICs unterstützt
I2C-Taktraten bis zu 1MHz, und es gibt auch einige I2C-Bausteine, die
für
1 MHz ausgelegt sind (z.B. EEPROMs von Microchip). Ein offizieller
Standard
ist diese Geschwindigkeit aber wohl nicht.
Da alle Geräte parallel an einem Bus hängen, ist es nötig ein Adresssystem zu nutzen, um anzugeben, wer Daten empfangen bzw. senden soll. Es gibt einen 7-Bit-Adress-System und ein abwärtskompatibles 10-Bit Adress-System, die an einem Bus gemischt verwendet werden können.
Ich werde mich in meinen Erklärungen auf einen einfachen I2C-Bus mit nur einem Master (PIC16F876), einem Slave (EEPROM 24C04), einem Takt von 400 kHz und 7-Bit Adresse (24C04 hat immer eine 7-Bit -Adresse) beschränken. Das dürfte die meisten Anwendungen abdecken.
Alle Geräte hängen parallel am 2-Draht-Bus. Alle Ausgänge, die auf den Bus treiben, sind open-collector oder open-drain Stufen.Sie können die Busleitung also nur nach Masse ziehen, aber nicht auf High-Pegel (+5V). Deshalb werden für beide Leitungen je ein Hochziehwiderstand benötigt. Durch die Widerstände soll ein Mindeststrom von 3 mA fließen, deshalb sollten sie nicht größer als 1,8 kOhm sein.
+++ACHTUNG+++
Werden die Hochziehwiderstände
vergessen,
dann liegt der Bus ständig auf Low, und niemand wird sich
trauen,
den scheinbar aktiven Bus zu übernehmen. Das System hängt
dann.
Viele PICs
besitzen
eine MSSP- bzw. SSP-Schnittstelle, die sich als I2C-Interface betreiben
lässt. Die MSSP-Hardware unterstützt Master- und
Slave-Funktionen.
Die SSP-Hardware ist nur für einen Slave gedacht.
Ich beziehe mich zur Erläuterung
der Funktion exemplarisch auf den PIC16F876. In anderen PICs
können
die verwendeten Register auf anderen Adressen oder auch in anderen
Bänken
liegen.
Die Einstellung der Busgeschwindigkeit
Der Takt SCL des I2C-Busses wird im 16F876 vom PIC-Takt abgeleitet. Da der PIC aber mit verschiedensten Takten betrieben werden kann, erledigt dies ein Baud-Raten-Generator (BRG). Das ist ein programmierbarer Frequenzteiler, der den PIC Takt zum gewünschten I2C-Takt herunter teilt. Wie das im Detail zu erfolgen hat, ist weiter unten erläutert.
Zwar lassen sich nicht bei jedem PIC-Takt exakt 100 kHz oder 400 kHz erzeugen, aber so genau muss der Takt auch gar nicht eingehalten werden. Hauptsache der erzeugte Takt ist nicht höher als der vom angeschlossenen Chip akzeptierte Höchsttakt.
Bus-Übernahme (Start)
Jede Aktion geht vom Master aus. Sollen
Daten auf dem Bus bewegt werden, dann muss der Master den Bus erst
einmal übernehmen. Dazu schaut sich der Master die Pegel auf
beiden
Leitungen (SCL & SDA) an. Nur wenn beide Leitungen High-Pegel haben
beginnt er mit der Arbeit (Hochziehwiderstände nicht vergessen!).
Als erstes zieht der Master die
Datenleitung
SDA auf Masse, während die Taktleitung SCL noch auf High ist.
Damit
gehört der Bus ihm, und alle am Bus angeschlossenen Geräte
erkennen
dieses Startsignal als Ankündigung, dass gleich etwas auf
dem
Bus passieren wird.
+++ACHTUNG+++
Falls sich der Pegel der SDA-Leitung
ändert,
während SCL auf High liegt, dann wird das immer als Steuersignal
interpretiert,
also als Busübernahme oder Busfreigabe. Während der normalen
Kommunikation
darf sich deshalb SDA nie ändern, während SCL auf High liegt!
Adressierung
Jeder Datentransfer wird mit der Adressierung
eingeleitet, damit geklärt ist, welcher Slave für die
Kommunikation
mit dem Master erkoren wurde. Es gibt eine 7-Bit Adressierung (7-Bit
lange
Adresse) und eine 10-Bit Adressierung. Welcher Adresstyp verwendet
wird,
hängt von den verwendeten Slaves ab.
(Es gibt ein Philips-Dokument vom
März
1997 "I2C-bus allocation table" in dem die Zuordnung aller
7-Bit-Adressen
zu Schaltkreistypen festgelegt ist.)
Woher kennen die Slaves eigentlich
ihre
Adressen?
Jeder I2C-Schaltkreis-Typ hat eine feste
Adresse, in der aber einige Bits in der Regel über Schaltkreispins
festgelegt werden, indem diese Pins fest mit Masse oder
Betriebsspannung
verbunden werden. Der EEPROM 24C04 hat z.B. die Adresse 1010xxx
wobei der Wert von xxx durch die Pegel an den Pins 1, 2 & 3 (A0
..A3)
festgelegt werden. Sind alle drei Pins mit Masse verbunden, so hat der
24C04 also die Adresse
1010000.
vom Master zum Slave
Der Master schiebt nach der
Übernahme
des Busses eine 7-Bit lange Slave-Adresse auf den Bus, dabei
sind
die einzelnen Bits (MSB zuerst) jeweils mit der steigenden Flanke von
SCL
gültig. Es folgt als 8. Bit eine 0. Diese 0 ist das Kennzeichen,
das
Daten zum Slave geschrieben werden sollen.
Alle Slaves am Bus vergleichen nun die
gesendete Adresse mit ihrer eigenen Adresse. Stimmt für einen Chip
die Adresse überein (und ein Chip sollte sich eigentlich immer
angesprochen
fühlen, wenn der Programmierer sauber gearbeitet hat), dann zieht
dieser Slave die Datenleitung nun seinerseits auf Low und wartet auf
den
nächsten Takt vom Master (Takt Nr. 9) und hält während
dieses
Taktes die Datenleitung weiterhin auf Low (Signal ACK). Das ist
für den Master das Zeichen dafür, dass ein Empfänger
bereit
ist.
Der Slave kann nach dem Ende des
neunten Taktes die Taktleitung für eine Weile auf Low halten, und
damit den Masters vorübergehend stoppen. Damit kann der Slave den
Datenstrom bremsen, wenn er die empfangenen Daten erst intern
weiterleiten
muss. (Im 100kHz- und 400kHz-Mode ist das sogar bei jedem
einzelnen
Takt erlaubt.)
Der Master überträgt jetzt 8-Bit lange Datenworte über den Bus, die jeweils von einem 9.Takt gefolgt werden. Der Slave liest die Datenworte ein, und zieht jeweils während des 9. Taktes die Datenleitung auf Low (ACK). Das ist für den Master das Zeichen, das die Daten angenommen wurden, und er weiter machen kann.
Wichtig ist, dass der Zustand der Datenleitung SDA nur geändert wird, während der Pegel der Taktleitung SCL Low ist. Ansonsten kann das Signal versehentlich als Busfreigabe fehlinterpretiert werden, und die Kommunikation bricht zusammen.
vom Slave zum Master
Der Master schiebt nach der
Übernahme
des Busses eine 7-Bit lange Slave-Adresse auf dem Bus dabei sind
die einzelnen Bits (MSB zuerst) jeweils mit der steigenden Flanke von
SCL
gültig. Es folgt als 8. Bit eine 1. Diese 1 ist das Kennzeichen,
das
Daten vom Slave gelesen werden sollen.
Alle Slaves am Bus vergleichen nun die
gesendete Adresse mit ihrer eigenen Adresse. Stimmt für einen Chip
die Adresse überein, dann wartet dieser Slave auf den
nächsten
Takt vom Master (Takt Nr. 9) und zieht während dieses Taktes die
Datenleitung
auf Low (Signal ACK). Das ist für den Master das Zeichen
dafür,
dass ein Sender bereit ist.
Der Slave kann nach dem Ende des neunten Taktes die Datenleitung auf Low halten, und damit den Takt des Masters vorübergehend stoppen. Damit kann der Slave den Datenstrom bremsen, wenn er die zu sendenden Daten erst intern bereitstellen muss.
Der Master überträgt jetzt
jeweils
8-Takte während derer der Slave die Datenbits (MSB zuerst)
auf
den Datenbus legt. Der Master liest diese 8 Bit nacheinander ein.
Danach
kann er ein ACK senden, indem er während eines 9. Takts
die
Datenleitung auf Low zieht.
Bus-Freigabe (Stop)
Zum Schluss muss der Master
den Bus wieder freigeben.
Normalerweise liegt nach dem Senden oder
Empfangen die Taktleitung auf High und die Datenleitung auf Low.
Ausgehend von diesem Zustand schaltet
der Master die Datenleitung SDA von Low auf High, während die
Taktleitung
SCL auf High liegt. Damit ist der Bus wieder frei.
10-Bit Adressierung
Bisher habe ich mich auf die 7-Bit Adressierung beschränkt, die aber nur 128 verschiedene Adressen zulässt. Parallel existiert aber auch eine 10-Bit-Adressierung, die mit 1024 möglichen Adressen schon mehr Möglichkeiten bietet. Um die 10-Bit-Adressierung zur 7-Bit-Adressierung abwärtskompatibel zu machen, bedient man sich eines einfachen Tricks. Die 10-Bit-Adresse wird mit dem Präfix "11110" zu einer 16-Bit-Zahl verlängert, und dann diese zwei Bytes einfach nacheinander über den Bus übertragen. Chips, die nur die 7-Bit-Adressierung kennen, verwerten natürlich nur das erste Byte, und sehen eine Adresse der Form "11110xx". Diese Adresse ist aber für 7-Bit-Chips nicht vergeben worden. folglich ignorieren diese Chips die Übertagung.MSSP-Modul im Master-Mode
Der weitere Text auf dieser Seite beschreibt die Nutzung des MSSP-Moduls des PIC16F87x als I2C-Interface. Die Hardware dieses Moduls unterstützt sowohl den Master-Mode wie auch den Slave-Mode. Ich benutze in diesem Beispiel den Master-Mode, und steuere einen EEPROM an, der als Slave arbeitet.Einige PICs (z.B. PIC16F88) haben anstelle des MSSP-Moduls nur ein SSP-Modul. Das hier fehlende M in der Bezeichnung stand für Master, folglich unterstützt diese Hardware nur den I2C-Slave-Mode. (Es fehlt u.A. die komplette I2C-Takterzeugung.) Mit entsprechendem Softwareaufwand kann man trotzdem einen I2C-Master-Mode erreichen. Dafür muss die fehlende Hardware durch Software emuliert werden. Microchip spricht dann von I2C firmware controlled Master mode und beschreibt das in der Application Note AN554.
Einige PICs (z.B. PIC16F628) haben gar
keine spezielle I2C-Hardware. Aber wie man auch
einen PIC ohne MSSP oder SSP als I2C-Master verwenden kann ist auf
einer
anderen Seite beschrieben.
Initialisierung
Das MSSP-Modul hat 6 Register, die
für
die I2C-Funktionen von Bedeutung sind:
Für I2C werden die beiden Pins RC3 und RC4 des PortC benutzt. Sie sind zunächst als Input zu initialisieren, damit sie später vom MSSP-Modul als SCL und SDA benutzt werden können.
; einstellen von RC3 & RC4 auf input
bsf
STATUS, RP0 ; Bank 1
movlw
B'00011000'
; RC3,4 inputs
iorwf TRISC,
f ; +
RC2=CCP1 output
bcf
STATUS, RP0 ; Bank 0
Einstellung der Busgeschwindigkeit
Die Busgeschwindigkeit wird eingestellt, indem der geeignete Teilerwert (Berechnung siehe oben) in das Adressregister SSPADD (Adresse 93h) geschrieben wird, während der Master gerade nicht den I2C-Bus benutzt, also z.B. während der Initialisierungsphase im Programm. Der neue Teilerwert wird dann umgehend in den BRG übernommen
SSPADD: MSSP-Adress-Register (ADDRESS 93h):
bit 7 | bit 6 | bit 5 | bit 4 | bit 3 | bit 2 | bit 1 | bit 0 | |
Name: | - | BRG6 | BRG5 | BRG4 | BRG3 | BRG2 | BRG1 |
|
|
|
|
|
|
|
|
|
|
SCL = PICtakt / ( 4 * (BRG+1) )
BRG = (PIC / (4 * SCL)) -1
Die folgende Tabelle enthält sie
nötigen
SSPADD-Werte für 100 kHz bzw. 400 kHz I2C-Takt bei verschiedenen
PIC-Takten.
Bei den mit einem '*' gekennzeichneten Werten lässt
sich
die Frequenz nicht präzise einstellen. Der Takt ist etwas
niedriger,
was aber erlaubt ist:
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
Um bei einem PIC-Takt von 20 MHz einen I2C-Takt von 400 kHz einzustellen muss also SSPADD mit 12 geladen werden. Das ergibt zwar nur einen Takt von 385 kHz, aber der nächstschnellere Takt (Wert 11) wäre mit 417 kHz schon nicht mehr in der Spezifikation des 24C04 EEPROMs.
; einstellen des I2C-Taktes auf knapp 400
kHz
bsf
STATUS, RP0 ; Bank 1
movlw
d'12'
;
clock
=
20/(4*(12+1)) = 385kHz
movwf
SSPADD
;
für
I2C
bcf
STATUS, RP0 ; Bank 0
Aktivieren des I2C-Interfaces
Das I2C-Interface wird im Register SSPCON eingestellt
SSPCON: MSSP-Control-Register (ADDRESS 14h):
bit 7 | bit 6 | bit 5 | bit 4 | bit 3 | bit 2 | bit 1 | bit 0 | |
Name: | WCOL | SSPOV | SSPEN | CKP | SSPM3 | SSPM2 | SSPM1 |
|
|
|
|
|
|
|
|
|
|
Die Betriebsart des MSSP-Moduls wird mit den unteren 4 Bit dieses Registers eingestellt. Der normale I2C-Master-Mode ergibt sich mit der Einstellung 1000.
movlw
B'00001000'
; master mode, clock=Fosc/(4*(SSPADD+1))
movwf
SSPCON
;
Nachdem die Betriebsart feststeht, muss das MSSP-Modul nun noch eingeschaltet werden. Das geschieht durch Setzen des Bits SSPEN (SSP enable) im SSPCON-Register. Damit werden die Pins RC3 und RC4 gleichzeitig vom Port C gelöst, und an die I2C-Hardware des PIC angeschlossen.
bsf SSPCON, SSPEN ; MSSP-Modul enable
Damit wäre das I2C-Interface des 16F876 bereit.
Um ein Daten auf dem I2C-Bus auszugeben, müssen folgende Schritte durchgeführt werden:
Bus übernehmen
Um den Master den Bus übernehmen
zu lassen, setzt man das Bit SEN im Register SSPCON2.
Hat
der PIC den Bus übernommen, dann setzt er (als Zeichen des
Erfolgs)
das Bit SSPIF im Register PIR1. Solange sollte man
warten.
Danach muss man das SSPIF Bit manuell wieder
zurücksetzten.
; I2C-Bus im Master-Mode übernehmen
i2c_on bcf
PIR1, SSPIF ; SSPIF Bit löschen
bsf STATUS, RP0
bsf SSPCON2, SEN ; Bus
Übernahme
anweisen
bcf STATUS, RP0
i2c_t1
btfss PIR1, SSPIF ; Testen, ob Bus
schon übernommen wurde
goto
i2c_t1
; nein, noch nicht
bcf PIR1, SSPIF ; ja,
der
Bus ist mein! nun noch SSPIF zurücksetzen
Adresse / Datenbyte senden
Nun kann man ein Byte senden. Das erste
Byte ist immer eine Adresse. An die 7 Bit der Slave-Adresse wird
eine 0 als LSB angehangen. Das ist das Kennzeichen dafür,
das
der Master auf den Slave schreiben will. Anschließend
sendet
man die Datenbytes. Prinzipiell unterscheidet sich das Senden von
Adressen
und Daten aber nicht:
Dafür schiebt man das zu sendende Byte einfach in das Register SSPBUF. Der PIC sendet das Byte dann selbständig. Dann wartet er auf ACK vom Slave. Wurde ACK empfangen, dann setzt er das SSPIF-Bit im Register PIR1. So lange sollte man warten. Danach muss man das SSPIF Bit manuell wieder zurücksetzten.
movlw
H'A0'
; '1010 0000' soll gesendet werden
; ein Byte aus W senden
i2c_tx
movwf
SSPBUF
; -> zum I2C-Slave übertragen
i2c_t2
btfss PIR1, SSPIF ; ACK schon
empfangen?
goto
i2c_t2
; nein, noch nicht
bcf PIR1, SSPIF ; ja,
Daten
sind im Slave, nun noch SSPIF zurücksetzen
Das wiederholt sich nun für alle zu sendenden Bytes.
den Bus wieder freigeben
Abschließend soll der Master den
Bus wieder freigeben. Dazu setzt man das Bit PEN im Register SSPCON2.
Hat
der
PIC
den Bus wieder freigegeben, dann setzt er das Bit SSPIF
im Register PIR1. Solange sollte man warten. Danach muss
man
das SSPIF Bit manuell wieder zurücksetzten.
; I2C-Bus wieder freigeben
i2c_off
bsf STATUS, RP0
bsf SSPCON2, PEN ; Bus
Freigabe
anweisen
bcf STATUS, RP0
i2c_t8
btfss PIR1, SSPIF ; Bus schon
freigegeben?
goto
i2c_t8
; nein, noch nicht
bcf PIR1, SSPIF ; ja,
alles
fertig, nun noch SSPIF zurücksetzen
Um ein Daten vom Slave zu lesen, müssen folgende Schritte durchgeführt werden:
Bus übernehmen
erfolgt genau wie beim Schreiben.
Adresse senden
Nun muss man die Adresse des Slave
senden. An Ihre 7 Bit der wird eine 1 als LSB
angehangen.
Das ist das Kennzeichen dafür, das der Master aus den Slave lesen
will.
Das Programmstück zum Senden ist
mit dem vom I2C-Bus-Schreiben praktisch identisch.
Datenbytes empfangen
Nun will der Slave ein Byte senden,
dafür
benötigt er aber den Takt vom Master. Es genügt, im Register
SSPCON2das
Bit RCEN (receive enable) zu setzen, und der PIC erzeugt den
Takt
und liest die Slave-Daten in das Register SSPBUF ein. Danach
setzt
er das Bit SSPIF im Register PIR1. Solange sollte man
warten.
Danach muss man das SSPIF Bit manuell wieder
zurücksetzten.
;ein Byte vom Slave empfangen
i2c_rx
bsf STATUS, RP0
bsf SSPCON2, RCEN ; Daten Empfang
einschalten
bcf STATUS, RP0
i2c_r7
btfss PIR1, SSPIF ; Daten Empfang
fertig?
goto
i2c_r7
; nein, noch nicht
bcf PIR1, SSPIF ; ja,
nun
noch SSPIF zurücksetzen
movf SSPBUF, w ;
empfangene Daten -> W
movwf
RXData
; empfangene Daten -> RXData
Falls ein weiteres Byte gelesen werden soll, ist zuvor das ACK-Signal zu senden. Dafür setzte man nun einfach das Bit ACKEN im Register SSPCON2. Nach dem Empfang des letzten Datenbytes ist das aber nicht erforderlich.
bsf STATUS, RP0
bsf SSPCON2, ACKEN ; ACK senden
bcf STATUS, RP0
Die Routine i2c_rx wird für alle zu empfangenen Bytes wiederholt.
den Bus wieder freigeben
erfolgt genau wie beim Schreiben.
Ein PIC16F876-20 ist via I2C-Bus mit einem EEPROM 24C04 verbunden worden. Beide Leitungen haben 1kOhm-Widerstände nach Vdd.
+++ ANMERKUNG +++
Dieses Beispiel strebt nicht die
höchste
Effizienz an, sondern soll das Prinzip erläutern. Generell
wäre
es sinnvoll beim Speichern vieler Werte im EEPROM ein Seiten- (Page)-
weises
Schreiben zu benutzen, um den Vorgang zu beschleunigen und den EEPROM
zu
schonen.
Um ein Byte in eine Speicherzelle des
24C04
zu schreiben, muss man zum EEPROM zuerst die Speicher-Adresse der
Speicherzelle und danach den zu speichernden Wert übertragen.
Der
I2C-Bus muss also 2 Byte zum 24C04 übertragen. Vorher
muss
der 24C04 natürlich adressiert werden.
Der 24C04 hat die 7-Bit-I2C-Adresse
1010000
und wir wollen den Wert 5 in die Speicher-Adresse 3 schreiben. Für
die Standardaufgaben sind 4 kleine Unterprogramme zuständig:
;**Schreibe Wert 5 auf
Speicher-Adresse 3
in 24C04************* call i2c_on ; Bus aktiv
movlw
H'A0'
;
1010
0000
movlw
0x00
;
high
Teil
der Adresse (Page)
movlw
0x05
;
Wert
der
auf Adresse 3 soll
call
i2c_off
;
Bus
freigeben ;***I2C
UNTERPROGRAMME************************************************************
; ein Byte aus W senden ;ein Byte vom Slave empfangen (nach
SSPBUF) ; I2C-Bus wieder freigeben
i2c_warte ;***ENDE UNTERPROGRAMME********************************************************** |
Wenn man einen Slave via I2C adressiert, dann kann man von ihm entweder nur lesen, oder nur auf ihn schreiben. Um aus einer bestimmten Speicherzelle aber das Datenbyte auszulesen, muss man die Adresse über den I2C-Bus schreiben, und anschließend das Datenbyte lesen. Das geht nur, wenn man dafür den I2C-Bus 2 Mal aktiviert. Das erste man um die Speicher-Adresse zum EEPROM zu übertragen, und ein 2. Mal zum Lesen des Datenbytes.
Der 24C04 hat die I2C-Adresse 1010000 und wir wollen den Wert aus der Speicher-Adresse 3 auslesen. Für die Standardaufgaben sind die Unterprogramme aus dem obigen Beispiel zuständig:
;**Stelle EEPROM auf
Speicher-Adresse 3 ein************* call i2c_on ; Bus aktiv
movlw
H'A0'
;
1010
0000
movlw
0x00
;
high
Teil
der Adresse call i2c_off ; Bus freigeben Nun steht der Adress-Pointer im 24C04 auf dem Wert 3. Nun können wir den I2C-Bus erneut aktivieren, um ein Byte aus dem 24C04 zu lesen. Das ist unser Datenbyte. ;**Lesen des aktuellen Bytes aus
24C04*************
movlw
H'A1'
;
1010
0001
call
i2c_rx call i2c_off ; Bus freigeben |
Das war's. Das
gelesene
Byte steht nun in der (hoffentlich irgendwo per EQU deklarierten) Zelle
'Datenpuffer'.
Es ist übrigens
nicht unbedingt nötig, den Bus am Ende der
Speicher-Adress-Übertragung
freizugeben. Die gleich darauf folgende Bus-Aktivierung würde bei
aktivem Bus den Bus kurz freigeben, um ihn dann sofort wieder zu
übernehmen.