Muss der Master nur senden, oder auch empfangen?
Ich habe I2C bisher nur für die Kommunikation mit EEProms, RTCs und so verwendet, nicht für die Kommunikation zwischen Prozessoren, deshalb meine Frage. Beim I2C Protokoll gebe ich ja neben der Slaveadresse noch eine Speicheradresse und so an. Das muss nicht unbedingt sinnvoll sein für die Kommunikation zwischen Prozessoren. bzw. das Protokoll läßt sich vermutlich recht einfach mit wenigen Logikbausteinen realisieren, ist aber nicht für den Austausch von Datentelegrammen geeignet.
Wenn der Master Antworten benötigt, muss er sich diese quasi Byte für Byte rauspulen.
Es gibt viele Möglichkeiten, wie man soetwas mit nur zwei, oder auch nur einer Leitung realisieren kann. Mit einer Leitung würde der Master einfach ein asynchrones serielles Signal per Software realisieren (falls nicht doch ein UART frei ist) und auf die Datenleitung legen. Der Slave antwortet dann auf der selben Leitung ebenfalls mit einem asynchronen seriellen Signal.
Vorteil: Zum Testen / Abhören nehme ich einfach die Com-Schnittstelle des PCs und ein Terminalprogramm
Wenn es eine Zweidrahtlösung sein soll, kann man eine synchrone Lösung wählen, bei der der Master den Takt sowohl zum Senden, als auch zum Empfangen vorgibt. Bei den Slaves hängt die Taktleitung dann z.B. an einem INT-Eingang. Damit sind dann sehr hohe Datentransferraten möglich.
Hier erstmal ein paar Fragmente aus einem 8031 Programm, mit einem I2C Uhrenchip PCF85?? Ich hoffe, der Code ist selbsterklärend...
Pascal-Sources muss ich noch suchen.
Gruß
Stefan
------------------------------------------------- snip -------------------------
INIT_I2C: SETB SDA SETB SCL RET
START_I2C: CLR SDA ;Startbedingung setzen LCALL _DELAY CLR SCL ;SCL auch auf LOW SJMP _DELAY ;nach kurzer Wartezeit return
BIT_I2C: MOV SDA,C ;Bit in Carry ausgeben LCALL _DELAY SETB SCL ;Taktbit setzen LCALL _DELAY MOV C,SDA ;Zustand des Datenbits lesen PUSH PSW CLR SCL ;Taktbit zurckseten LCALL _DELAY POP PSW RET
STOP_I2C: SETB SCL ;SCL auf High-Pegel LCALL _DELAY SETB SDA ;Steigende Flanke SJMP _DELAY ;warten und return
BYTE_I2C: MOV C,ACC.7 ;Daten im ACCU senden oder lesen LCALL BIT_I2C MOV ACC.7,C
MOV C,ACC.6 LCALL BIT_I2C MOV ACC.6,C
MOV C,ACC.5 LCALL BIT_I2C MOV ACC.5,C
MOV C,ACC.4 LCALL BIT_I2C MOV ACC.4,C
MOV C,ACC.3 LCALL BIT_I2C MOV ACC.3,C
MOV C,ACC.2 LCALL BIT_I2C MOV ACC.2,C
MOV C,ACC.1 LCALL BIT_I2C MOV ACC.1,C
MOV C,ACC.0 LCALL BIT_I2C ;letztes Bit senden MOV ACC.0,C RET
ACK_I2C: SETB C LJMP BIT_I2C
ACK_I2C_W: CLR C LJMP BIT_I2C
GET_I2C: .module GET_I2C MOV C,SCL MOV I2C_BIT,C LCALL STOP_I2C ;Stopbedingung sicherstellen LCALL START_I2C ;Startbedingung MOV A,ADR_I2C ;Slave-Adresse nach A CLR ACC.0 ;erst Adresse schreiben LCALL BYTE_I2C ;Slave-Adr. schreiben LCALL ACK_I2C MOV A,WRD_I2C ;Wordadresse in den AKKU LCALL BYTE_I2C ;Wordadresse senden LCALL ACK_I2C LCALL STOP_I2C LCALL START_I2C MOV A,ADR_I2C SETB ACC.0 LCALL BYTE_I2C ;Slaveadresse senden LCALL ACK_I2C ;ACK abwarten MOV A,#$FF ;alle Bits High, um zu lesen LCALL BYTE_I2C LCALL ACK_I2C ;Ack schreiben SDA auf low LCALL STOP_I2C MOV C,I2C_BIT MOV SCL,C RET
PUT_I2C: .module PUT_I2C MOV C,SCL MOV I2C_BIT,C LCALL STOP_I2C ;Stopbedingung sicherstellen LCALL START_I2C ;Startbedingung PUSH ACC MOV A,ADR_I2C ;Slave-Adresse nach A CLR ACC.0 ;erst Adresse schreiben LCALL BYTE_I2C ;Slave-Adr. schreiben LCALL ACK_I2C MOV A,WRD_I2C ;Wordadresse in den AKKU LCALL BYTE_I2C ;Wordadresse senden LCALL ACK_I2C POP ACC LCALL BYTE_I2C LCALL ACK_I2C LCALL STOP_I2C MOV C,I2C_BIT MOV SCL,C RET
GET_UHR: .module GET_UHR MOV ADR_I2C,#$A0 ;Slave-Adresse nach R1 MOV WRD_I2C,#04 ;Stunden adressieren LCALL GET_I2C ;Byte auslesen MOV STUNDE,A MOV WRD_I2C,#03 ;Minuten adressieren LCALL GET_I2C ;Byte auslesen MOV MINUTE,A MOV WRD_I2C,#02 ;Sekunden adressieren LCALL GET_I2C ;Byte auslesen MOV SEKUND,A RET