PDA

Archiv verlassen und diese Seite im Standarddesign anzeigen : I²C ICs abfragen zwecks GETACK



MedanoCC
23.03.2004, 16:45
Olla!

Kurze Frage: Es gibt doch das Problem, dass wenn ein I²C-IC angesprochen werden soll, der aber nicht im Netz hängt, das System beim GETACK stehenbleibt, weil es in eine Endlosschlaufe geht.

Jetzt habe ich irgendwo gelesen, wie man das per ASM umgehen kann, bzw. wie der GETACK Befehl auszusehen hat um nach einer bestimmten Zeit aus der Schlaufe zu springen. Kanns mir denn jemand hier kurz skizzieren oder einen anderen Tipp geben, wie ich erkenne, ob der entsprechende IC im Netz ist bzw. Strom hat ??

Super, danke

MedanoCC

jörg
27.03.2004, 13:57
Das Problem tritt auf, wenn Du den System I2C Bus der CC1 benutzt, und dafür die System I2C-Routinen verwendest (I2C_START usw, liegen bei Adressen $08xx).

Wenn Du es vermeiden willst, musst Du eine eigene Routine "WRITE" zum Schreiben verwenden: die muss dasselbe macht wie das Original, aber bei fehlendem ACK nicht wiederholen. Dazu musst Du allerdings auch die I2C_START kopieren. Insgesamt dürften das dann mindestens 30 Bytes Code sein -- ganz schön viel.
Details dazu findest Du im Source-Listing der CC1 Routinen.

Wenn Du nur ein mal am Anfang prüfen musst, ob der I2C Baustein überhaupt da ist, könntest Du das ganze am Anfang des BASIC Programms einmalig als SYS Routine laufen lassen, und im laufenden Betrieb dann die System-Routinen verwenden, um Platz zu sparen.

Eine andere Methode kenne ich nicht.

MedanoCC
27.03.2004, 16:03
Hi!

Danke für Deine Antwort. Die Frage ist jedoch noch für mich, wie dann die Routine aussehen muss, da ich ja eine Schlaufe machen muss, die dann jedoch nicht unendlich sondern kontrolliert, d.h. nach einer bestimmten Zeit abbrechen muss. Wie sieht das denn dann aus ? Kann auch ein Basic-Script sein.

Könntest Du das vorgehen kurz skizieren ?


Danke - MedanoCC

jörg
27.03.2004, 16:55
OK, nur damit wir uns richtig verstehen:

1. Du willst den System I2C Bus der CC1 für Deine Peripherie mitbenutzen, z. B. einen PCF8574 hinhängen

2. Dafür hast Du ein Assembler-Programm, das die System-Routinen I2C_Start, I2C_Write, I2C_Read_Last usw. aufruft.
Dein Assembler-Programm sieht dann (immer) in etwa so aus:


; EEPROM vom I2C Bus abmelden
jsr I2C_ReadLast

; I2C Bus starten und mein device selektieren
ldx xxx (z. B. $A1)
jsr I2C_Start

; meine Daten zu diesem device senden
ldx xxx (z. B. $A3)
jsr I2C_Write

; vielleicht nochmal was senden

; mein Device abmelden
jsr I2C_Stop

; das EEPROM wieder anmelden
xxxx


3. Problem ist die System Routine I2C_Write, die auch noch mal in I2CStart enthalten ist.
Das sieht im Original so aus:


;------------------------------------------------
; void I2C_Start ( unsigned char devadr );

global _I2C_Start
signat _I2C_Start,4216
;------------------------------------------------

; Startbedingung nach Init, Write oder Stop moeglich
; Vorbedingung: SCL lo (nach Write) oder
; SCL hi und SDA hi (nach Init und Stop)
; SCL und SDA als Ausgang, SDA nach low ziehen
; = Startbedingung
; warten

_I2C_Start BSET SDA,DIR ; SDA hi ausgeben
BSET SDA,PORT ; Vorbereiten der Startbed.
BSET SCL,PORT ; SCL hi falls lo
BCLR SDA,PORT ; SDA lo -> STARTBEDINGUNG
BCLR SCL,PORT ;


; nach jeder Startbedingung wird sofort
; das Controlbyte geschrieben,
; also weiter bei I2C_Write

;------------------------------------------------
; void I2C_Write ( unsigned char byte );

global _I2C_Write
signat _I2C_Write,4216
;------------------------------------------------

_I2C_Write BSET SDA,DIR ; SDA out
TXA ;
STA writebuf ; merken fuer retry

LDX #8 ; init loop
putnextbit ROLA
BCC lobit ;
BSET SDA,PORT ; hi bit
BRA writeclock
lobit BCLR SDA,PORT ; lo bit

writeclock BSET SCL,PORT ; scl hi
BCLR SCL,PORT ; scl lo

DEX
BNE putnextbit ; loop

; ACK-Bit lesen
; Achtung: ACK ist low-aktiv

BCLR SDA,DIR ; sda als Eingang
BSET SCL,PORT ; scl hi
BRSET SDA,PORT,retrywrite; no ACK -> retry
BCLR SCL,PORT
RTS

; hierher nur bei control byte,
; wenn EEPROM noch nicht bereit

retrywrite BCLR SCL,PORT ;
LDX writebuf
BRA _I2C_Start


4. Diese beiden Routinen musst Du jetzt in Deinen Assembler-Source kopieren und anstelle der beiden Systemroutinen aufrufen.

5. Dann muss Du Dir den Teil "ACK-Bit lesen..." anschauen: Genau der Befehl
BRSET SDA, PORT, retrywrite
stört Dich: Wenn kein ACK da ist, wird unentwegt dasselbe Byte nochmal geschrieben.

6. Jetzt musst Du Dir überlegen, was in diesem Fall BEI DEINER SCHALTUNG passieren soll.
6.1 Du Kannst Dir zum Beispiel sagen: "Mir ist's egal ob das Byte quittiert wird": dann lässt Du den BRSET einfach weg.
6.2 Oder Du könntest den Befehl über eine Schleife paar (hundert) mal wiederholen, und erst dann aufhören.
6.3 Oder Du könntest das Ergebnis (ACK oder NOACK) an die aufrufende CCBASIC Routine zurückgeben, und die überlegt sich das dann.