Hallo zusammen,
ich arbeite mit einem XMega128, an den 4 I2C-Porterweiterungs-ICs
PCA9555 angeschlossen sind. Diese ICs schalten bzw. lesen über
Optokoppler 24V-Spannungspegel. Die 24V-Spannung wird extern
eingespeist. Die Erweiterungs-ICs werden aber von der internen
Boardspannung gespeist, an der auch der XMega hängt.
Nun passiert immer wieder, wenn die externe 24V-Spannung ausgeschaltet
und eingeschaltet wird, dass sich der XMega aufhängt. Er bleibt an der
Programmzeile hängen, in der abgefragt wird ob die TWI-Übertragung
abgeschlossen wurde. Dabei bleibt der Busszustand laut BUSSTATE-Bits auf
BUSY stehen und RXACK-Bit, das ja den zuletzt empfangenen
acknowledge-Bit anzeigt, ist gesetzt, es wurde folglich NACK empfangen.
Nun, das TWI-Modul im XMega hat ja die TIMOUT-Bits, die, wenn gesetzt,
den Bus wieder in den IDLE-Zustand zurückbringen, wenn er "lange"
inaktiv bleibt. Ich habe diese Bits jetzt auch gesetzt, aber das
Programm bleibt trotzdem hängen und wartet bis der Bus wieder frei ist.
Veilleicht hatte ja jemand von euch ein solches Problem und könnte mich
wissen lassen, wie er das gelöst hat. Ich wäre für die Hinweise seht
dankbar!
noips schrieb:> Ich habe mir gedacht, 1 Stunde ist schon eine gute Wartezeit :-)
Die Suchfunktion hast du benutzt?
Soweit ich weiß gibt es (auch) einen Hardwarebug, finde aber den Link
nicht mehr...
ach ja:ohne SourceCode wird dir wenig geholfen werden können...
Hallo noips, guten morgen Tim,
irgendein Fehler in HW? Also wenn der PCA9555 und der XMega versorgt
bleiben, funktioniert auch I2C. Ich hatte das Problem mal, dass bei der
MegaXX Serie I2C des Empfängers stromlos wurde - dann hat sich der Bus
aufgehängt.
Deine Abhilfe in SW: die Atmel Treiber haben viele do{...}while...
Konstrukte ohne Fehler abzufangen ==> Controller bleibt 'stecken'
Abhilfe:
>Die Suchfunktion hast du benutzt?>Soweit ich weiß gibt es (auch) einen Hardwarebug, finde aber den Link>nicht mehr...
Gesucht habe ich davor schon. Nur nichts gefunden, was mir weiterhilft.
In den entsprechenden Threads wird empfohlen, einen Timeout-Counter
laufen zu lassen und bei zu langer Inaktivität des Busses den Bus zu
"reseten" sozusagen. Ich denke aber, dass die von mir erwähnten
TIMEOUT-Bits des XMega dafür sorgen sollten, was diese bei mir aber
nicht tun. Drum habe ich fragen wollen, was da falsch sein könnte.
Was den Code betrifft, es werden die Softwaretreiber von Atmel benutzt.
Sie wurden ergänzt durch die folgende Funktion, die auf die
Treiberfunktionen zurückgreift und die aus dem Hauptprogramm aufgerufen
wird:
1
boolReadDigitalIO(TWI_Master_t*twi,uint8_t*input)
2
{
3
uint8_tcommand=0;
4
5
command=TWI_PCA_IN_PORT_0;
6
while(twi->status!=TWIM_STATUS_READY);//Wait until transaction is complete.
Hallo,
wie kann eien externe Spannung von 24 Volt mit den Prozessor in
Verbindung kommen?
Opto's trennen doch die hohe Spannung von der eigentlichen
Betriebsspannung (z.B 3,3 Volt).
Beim Senden über den Prozessor werden die Led der Opto mit ca. 3 Volt
versorgt. In der Gegenrichtiung hängen die die Led auf der 24
Volt-Seite. Das Aus-und Einschalten der 24 Volt Spannung darf doch die
I2C-Übertragung nicht stören.
Gruß GG
noips schrieb:> while (twi->status != TWIM_STATUS_READY);
Du solltest zuerst das Interruptbit testen, d.h. ob eine I2C-Aktion auf
Behandlung wartet.
Erst dann kannst Du den Status auslesen. Du mußt dann jeden Status
behandeln, da durch Störimpulse auf dem Bus jeder Status möglich ist.
Nur einen bestimmten Status zu erwarten, ist daher ne ganz schlechte
Idee.
Z.B. kann der Master high senden, aber ein Störimpuls low anlegen und
dann geht der Master in den Arbitration-Lost-Status.
Peter
>Das Aus-und Einschalten der 24 Volt Spannung darf doch die I2C-Übertragung >nicht stören.
Das sehe ich ja auch so, darum verstehe ich nicht warum die Störung
auftritt. Aber nicht das ist das eigentliche Problem. Die Folge der
Störung kann man ja beseitigen, wenn man den Bus wieder in Bereitschaft
zurücksetzt.
@ Peter Dannegger
In den Beispiel-Codes von Atmel wird es aber genau so gemacht. Es wird
eine I2C-Übertragung ausgelöst und danach wird mit while gewartet, bis
der Stauts wieder READY ist. Erst dann führt man das Programm weiter
aus. Die anderen möglichen Zustände am Bus verden durch Interrupts und
die in der Treiber-Software von Atmel vorhandenen Interrupt-Handler
behandelt.
noips schrieb:> In den Beispiel-Codes von Atmel wird es aber genau so gemacht.
Beispielcodes sollen immer nur das Prinzip verdeutlichen.
Niemand bei Atmel oder einem anderen IC-Hersteller wird Dir garantieren,
daß sie auch praxistauglich sind.
Ich kenne die XMega nicht, ich benutze die ATmega.
Und da habe ich ne Switch-Anweisung im I2C-Interrupt, die alle 32
möglichen Status-Case behandelt.
Zusätzlich habe ich noch ein Timeout, was das I2C kurz mal abschaltet,
falls es sich richtig verklemmt hat (die ATmega haben leider nen bösen
Multimaster-Bug).
Peter
Ich versuche jetzt seit Stunden dem Problem auf den Grund zu gehen.
Dabei scheint der XMega sich nicht immer so zu verhalten, wie es im
Manual beschrieben ist. Vielleicht hat jemand ähnliche Sachen bei
XMega-TWI-Modul schon beobachtet. Wäre sehr dankbar, wenn sich jemand
meldet.
noips schrieb:> Ich versuche jetzt seit Stunden dem Problem auf den Grund zu gehen.
Wie?
Versuch mal systematisch vorzugehen.
Wenn er hier hängt:
> while (twi->status != TWIM_STATUS_READY);
Also nie "TWIM_STATUS_READY" wird.
Was steht dann in "twi->status"?
Was bedeutet es?
Peter
Peter Dannegger schrieb:> Wie?> Versuch mal systematisch vorzugehen.
Das versuche ich ja auch!
Ich verwende die von Atmel in Apl.-Notes vorgeschlagene
TWI-Treibersoftware TWI_MASTER_DRIVER.c (mit der dazugehörigen
.h-Datei). Da gibt es eine Interrupt-Handler-Funktion, die prüft, ob
Master-Write-Interrupt oder Master-Read-Interrupt aufgetreten ist und
ruft dementsprechend entweder den Write-Interrupt-Handler oder den
Read-Interrupt-Handler. In diesen Handlern wird Schreib- bzw.
Lesevorgang gestartet und wenn alles geschrieben/gelesen wurde wird eine
STOP-Condition gesendet und twi->status auf READY gesetzt, aber davor
wird geprüft, ob Arbitration-Lost, Buss-Error oder Not-Acknoledge (vom
Slave) aufgetreten ist (zu jedem dieser drei Fälle gibt es Bits in einem
Register). Ist einer der Fälle aufgetreten, so wird (neben einigen
anderen Dingen) durch Setzen von CMD-Bits das Senden einer
STOP-Condition vom Master veranlasst. Laut Manual, muss die TWI-Logik im
XMega bei Erkennen einer STOP-Condition auf dem Bus, das TWI-Modul aus
den Zuständen BUSY oder OWNER wieder in den Zustand IDLE zurückholen.
Ich sehe im Debugger, wie die CMD-Bits auch gesetzt werden und folglich
auch STOP-Condition auch gesendet wird, aber nicht immer geht das
TWI-Modul in den IDLE-Zustand über. twi-status wird aber immer auf READY
in der Software gesetzt. Wenn dan der nächste Schreibvorgang durch
Software ausgelöst wird, kommt kein Interrupt mehr, vermutlich weil das
TWI-Modul nicht in IDLE ist. Dann wartet die Software vergeblich auf die
Bedingung (twi->status = TWIM_STATUS_READY), denn damit diese Bedingung
eintritt, muss ein Interrupt-Handler aufgerufen werden.
Als ich das alles eingefügt hatte klappte es.
Sollte es grundsätzlich bei Dir funktionieren gibt es zwei Möglichkeiten
1. Watchdog
2. T/C Interrupt zählen und in der While Schleife eine bedingung
schaffen mit der aus der Schleife gesprungen werden kann.
Allerdings muß dann der TWI neu eingerichtet und gestartet werden.
Ich hoffe es war hilfreich.
noips schrieb:> Peter Dannegger schrieb:>> Wie?>> Versuch mal systematisch vorzugehen.>> Das versuche ich ja auch!>> Ich verwende die von Atmel in Apl.-Notes vorgeschlagene> TWI-Treibersoftware TWI_MASTER_DRIVER.c (mit der dazugehörigen> .h-Datei). Da gibt es eine Interrupt-Handler-Funktion, die prüft, ob> Master-Write-Interrupt oder Master-Read-Interrupt aufgetreten ist und> ruft dementsprechend entweder den Write-Interrupt-Handler oder den> Read-Interrupt-Handler. In diesen Handlern wird Schreib- bzw.> Lesevorgang gestartet und wenn alles geschrieben/gelesen wurde wird eine> STOP-Condition gesendet und twi->status auf READY gesetzt, aber davor> wird geprüft, ob Arbitration-Lost, Buss-Error oder Not-Acknoledge (vom> Slave) aufgetreten ist (zu jedem dieser drei Fälle gibt es Bits in einem> Register). Ist einer der Fälle aufgetreten, so wird (neben einigen> anderen Dingen) durch Setzen von CMD-Bits das Senden einer> STOP-Condition vom Master veranlasst. Laut Manual, muss die TWI-Logik im> XMega bei Erkennen einer STOP-Condition auf dem Bus, das TWI-Modul aus> den Zuständen BUSY oder OWNER wieder in den Zustand IDLE zurückholen.> Ich sehe im Debugger, wie die CMD-Bits auch gesetzt werden und folglich> auch STOP-Condition auch gesendet wird, aber nicht immer geht das> TWI-Modul in den IDLE-Zustand über. twi-status wird aber immer auf READY> in der Software gesetzt. Wenn dan der nächste Schreibvorgang durch> Software ausgelöst wird, kommt kein Interrupt mehr, vermutlich weil das> TWI-Modul nicht in IDLE ist. Dann wartet die Software vergeblich auf die> Bedingung (twi->status = TWIM_STATUS_READY), denn damit diese Bedingung> eintritt, muss ein Interrupt-Handler aufgerufen werden.
Hallo Zusammen,
ich habe genau das hier beschriebene Problem. Wurde das inzwischen
gelöst, bzw. gibt es einen Workaround?
Ich verwenden den TWI_MASTER_DRIVER.c im Originalzustand. Eine Zeit lang
läuft die Übertragung einwandfrei, dann kommt kein Write Interrupt mehr,
obwohl das WIF Flag gesetzt ist.
Ich verwende Atxmega192A3.
@noips wie bust du weiter gekommen?
Gruß
Rolf
Hallo,
hatte auch das Problem, dass die SCL Leitung dauerhaft LOW war, wenn ich
folgende Schleife benutzt habe, um sicher zu gehen, dass die
Kommunikation beendet ist.
1
while(twiMaster.status!=TWIM_STATUS_READY){
2
/* Wait until transaction is complete. */
3
}
Habe jetzt bei der Initialisierung des TWI-Moduls das Interruptlevel auf
HIGH gesetzt und es funktioniert jetzt, allerdings kann ich nicht
erklären warum.
Viele Grüße
Hendrik