Hallo Freunde,
ich bin jetzt seit Monaten dabei über die I2C-Schnittstelle 2
Mikrokontroller zu verbinden. Sie sollen Daten gegenseitig austauschen.
Aber geklappt hat es bis heute noch nicht
Ich setze 2 Freescale Mikrocontroller ein (MC56F8036).
Beide Mikrocontroller können sowohl als Master als auch als Slave
arbeiten. D.h. im Laufe des Programms wird eingestellt welcher
Mikrocontroller als was arbeiten soll (Master oder Slave)
Wenn der Master sendet, dann wiederholt er es solange bis der Slave mit
ACK bestätigt, dass das Datum erfolgrecih gesendet wurde.
Das Problem ist, wenn die Daten gesendet werden, werden sie erst im
Puffer von I2C gespeichert und anschließend kann ich die Daten aus dem
Puffer holen und in mein Array speichern. Und während ich die Daten
bearbeite, kommen schon die nächsten Daten und irgendwann ist alles ganz
durcheinander..
Wie kann ich das verhindern? Wie kann ich den I2C-Bus solange stoppen,
bis der Buffer frei wird, bzw. ich die Daten verarbeitet habe?
Kann mir BITTE jemand eine vernünftige Routine für I2C-Bus sagen?
> Wie kann ich das verhindern? Wie kann ich den I2C-Bus solange stoppen,> bis der Buffer frei wird, bzw. ich die Daten verarbeitet habe?
clock stretching?
clock stretching meint, dass der nicht-taktgebende Kommunikationspartner
(normalerweise der Slave) das Taktsignal einfach mal eben auf festklemmt
(also auf einem Pegel hält). Das merkt der Taktgeber ja dann ("Wie?
Immer noch LOW obwohl ich schon HIGH sage? OK..warten2).
>> clock stretching?> Blödsinn. Der Master kann jederzeit die Datenübertragung stoppen.
Sorry, ich hab das so verstanden, als wäre der Client zu langsam.
@Cimbon Gs: Soso, du beschäftigst dich also seit Monaten mit I2C, weißt
aber nicht was clock stretching ist :)
Das heißt einfach, dass der Client SCL auf low hält und der Master
solange warten muss.
>Sorry, ich hab das so verstanden, als wäre der Client zu langsam.
Tut mir leid, Du hast wahrscheinlich recht, der Client ist zu langsam
und
soll den Master aufhalten.
es ist so:
zu erst sendet MC1 an MC2 einen Befehl zum starten, wenn MC2 seine
Messung beendet hat wird MC2 zu Master und MC1 zu SLave. MC2 sendet das
Ergebnis an MC1 und wenn MC1 das Ergebnis erhalten hat beginnt er mit
seiner eigenen Messung. Danach wird MC1 wieder zu Master und MC2 zu
Slave
In der Zeit, wo MC1 seine Messung durchführt wartet MC2 bis MC1 das
Befehl zum starten sendet. D.h. es könnte und dürfte nie zu einem
überlauf kommen.
(Beide MC's warten immer aufeinander)
Aber es passiert trotzdem, dass MC1 mehr als 4 chars im Buffer hat. D.h.
das irgendwie der MC2 mehrmals seine Messung durchführt und an MC1
sendet..
Dieses Phänomen kann ich einfach nicht verstehen.
Ich meine MC2 muss immer erst auf MC1 warten und dann seine Messung
starten. und wenn MC2 mit der Messung fertig ist, sendet er das Ergebnis
an MC1
Johnny Maxwell wrote:
> @Cimbon Gs: Soso, du beschäftigst dich also seit Monaten mit I2C, weißt> aber nicht was clock stretching ist :)
naja ich habe den Begriff "clock stretching" zum ersten Mal gehört,
daher habe ich es nicht ganz verstanden
naja ich könnte auch mit einfachem Master-Slave modus arbeiten, d.h.
einer ist immer Master und der andere immer Slave. Aber dann habe ich
das Problem, obwohl der Slave seine Daten nicht auf den I2C-Bus gelegt
hat, bekommt der Master lauter Nullen...
Ich könnet eine Routine schreiben, dass solange das empfangene Datum
eine Null ist das Empfangen wiederholt, aber das Ergebnis kann ja auch
Nullen enthalten und das würde wieder alles Verfälschen
>Aber es passiert trotzdem, dass MC1 mehr als 4 chars im Buffer hat. D.h.>das irgendwie der MC2 mehrmals seine Messung durchführt und an MC1>sendet..>>Dieses Phänomen kann ich einfach nicht verstehen.
Das ist kein Phänomen. Das hast du selber programmiert.
Mach eine saubere Master/Slave Verbindung und gut.
Solange der Master nichts anfordert hält der Slave
einfach die Klappe.
holger wrote:
> Solange der Master nichts anfordert hält der Slave> einfach die Klappe.
ja aber wie oben schon erwähnt, wenn der Master von Slave lesen möchte
aber der Slave nocht nicht soweit ist, legt der I2C-Bus Nullen auf die
Leitung..Der Master kann nicht auf "Nicht-Null" prüfen, weil das
Ergebnis auch Nullen enthalten kann..
Beispiel:
Slave hat 4 Bytes zu senden, bzw. Master muss 4 Bytes lesen.
1. Byte 0
2. Byte 1
3. Byte 0
4. Byte 7
d.h. wenn Master auf eine "Nicht-Null" wartet, wird das Ergebnis ganz
falsch :-(
@ Cimbom Gs (cimbomgs)
>ja aber wie oben schon erwähnt, wenn der Master von Slave lesen möchte>aber der Slave nocht nicht soweit ist, legt der I2C-Bus Nullen auf die>Leitung..
Nöö.
>Der Master kann nicht auf "Nicht-Null" prüfen, weil das>Ergebnis auch Nullen enthalten kann..
Nöö. Wenn der Slave noch nicht bereit ist zum antworten, dann antwortet
er einfach nicht. Damit geht die Addressierung mangels ACK "daneben" und
der Master muss es später nochmal versuchen. Ganz einfach. Siehe
I2C- Spezifikiation.
>d.h. wenn Master auf eine "Nicht-Null" wartet, wird das Ergebnis ganz>falsch :-(
Du solltest dich dringend mal mit den grundlagen von I2C befassen.
Dann löst sich dein "Problem" in Luft auf.
MFG
Falk
>ja aber wie oben schon erwähnt, wenn der Master von Slave lesen möchte>aber der Slave nocht nicht soweit ist, legt der I2C-Bus Nullen auf die>Leitung..Der Master kann nicht auf "Nicht-Null" prüfen, weil das>Ergebnis auch Nullen enthalten kann..
Wie Falk schon sagte: Wenn der Slave nicht antworten kann
kommt kein gültiges ACK für den Master. Was in den Datenbits steht ist
dann völlig wurscht.
Falk Brunner wrote:
> Du solltest dich dringend mal mit den grundlagen von I2C befassen.
habe ich schon zum 100. Mal gemacht, aber das Hilft nicht weiter.
Bei Freescale gibt es folgende Eigenschaft:
Empty character - A character being sent when no data is ready to be
transmitted.
>Nöö. Wenn der Slave noch nicht bereit ist zum antworten, dann antwortet>er einfach nicht.
Das hätte ich auch am liebsten, aber dem ist nicht so :-/..Wenn Slave
nicht zu senden hat, antwortet der I2C-Protokoll mit einem "Empty
character"
Und das ist der Grund, warum ich Multi-Master einsetze. Immer der MC,
der als Slave konfiguriert ist wartet bis Master sendet. Daher existiert
kein "Empty character", wenn der eine oder der andere nichts zu senden
hat
@ Cimbom Gs (cimbomgs)
>> Du solltest dich dringend mal mit den grundlagen von I2C befassen.>habe ich schon zum 100. Mal gemacht, aber das Hilft nicht weiter.
Das glaube ich kaum.
>Das hätte ich auch am liebsten, aber dem ist nicht so :-/..Wenn Slave>nicht zu senden hat, sendet der I2C-Protokoll mit einem "Empty>character"
Glaub ich nicht. Kann man sicher abstellen.
>Und das ist der Grund, warum ich Multi-Master einsetze. Immer der MC,>der als Slave konfiguriert ist wartet bis Master sendet.
Dann ist es kein Multmaster!
> Daher existiert>kein "Empty character", wenn der eine oder der andere nichts zu senden>hat
Du drehst dich im Kreis.
MfG
Falk
Falk Brunner wrote:
> Das glaube ich kaum.
glaub mir das habe ich :-(
> Glaub ich nicht. Kann man sicher abstellen.
habe ich schon mehr mals das Datenblatt angeschaut, nirgends ein Zeichen
davon wie man es abstellen kann. Vor allem es wird auch nirgends erwähnt
das es so passiert aber in der Entwicklungsumgebung ist es vorhanden
> Du drehst dich im Kreis.
das weiß ich, aber finde keinen Weg aus dem Kreis rauszukommen.
>Ich kenne den Controller zwar überhaupt nicht, hab aber mal für dich die>Errata rausgesucht:
Kenne ich auch schon, aber Hilft auch nicht wirklich weiter.
Cimbom Gs wrote:
> Das hätte ich auch am liebsten, aber dem ist nicht so :-/..Wenn Slave> nicht zu senden hat, antwortet der I2C-Protokoll mit einem "Empty> character"
Im Philips I2C-Standard gibts keinen "Empty character".
Der Master muß auf die Adresse immer das ACK prüfen und der Slave darf
das NACK setzen, damit der Master kein ACK kriegt.
Falls wider Erwarten der Slave kein NACK setzen können sollte, dann
einfach das Slave-I2C solange disablen.
Wenn der Master das ACK nicht testet, dann kann er ja nicht mal
Standard-I2C Chips bedienen, wie z.B. EEPROMs 24C512 usw..
Diese ICs senden nämlich immer NACK, solange sie intern mit Schreiben
beschäftigt sind.
Dann könnte man sich damit behelfen, das Master-I2C in Software zu
machen (Bitwackeln) und dann das NACK auswerten.
Peter
Peter Dannegger wrote:
> Im Philips I2C-Standard gibts keinen "Empty character".
das weiß ich.. Ach man ich möchte heulen
Im Anhang ist ein Bild von der Entwicklungsumgebung. Das "Empty
character" kann man nirgends abschalten :'(
Cimbom Gs wrote:
> Im Anhang ist ein Bild von der Entwicklungsumgebung. Das "Empty> character" kann man nirgends abschalten :'(
Von solchen Code-Wizzards halte ich nicht viel.
Sie sind in der Regel völlig unausgereift und können natürlich nicht
alle Anwendungsfälle vorhersehen.
Sie können nur ausschließlich das machen, was der Entwickler des
Wizzards vorgedacht hat.
Ich hab auch noch nie gehört, daß jemals jemand mit sowas richtig
arbeiten konnte.
Ich hab sowas noch nie benutzt, ich programmiere immer direkt in C.
Da muß es doch auch ein Datasheet oder Usermanual zu dem Chip geben, wo
die ganze Peripherie beschrieben ist und auch das I2C.
Und da muß dann drinstehen, in welchem IO-Register welche Bits welche
Bedeutung haben.
Und eins davon muß bedeuten, daß ein NACK empfangen wurde.
Peter
P.S.:
In dem Wizzard steht irgendwas von Errorinterrupt, könnte sein, daß das
NACK im Errorinterrupt ausgelesen werden kann.
Cimbom Gs wrote:
> ich verstehe die Welt nicht mehr :'(
Wenn Du mit dem Wizzard arbeitest, muß es doch auch ne Doku und Hilfe
dazu geben, die mußt Du durchlesen.
Ein Wizzard kann ja nicht zaubern.
Du mußt lesen, welche Funktionen er bereitstellt, wenn Du ihn verwenden
willst.
Peter
Peter Dannegger wrote:
> In dem Wizzard steht irgendwas von Errorinterrupt, könnte sein, daß das> NACK im Errorinterrupt ausgelesen werden kann.
wenn Slave ein NACK erzeugt bzw SDA-Leitug auf HIGH beleibt (zBsp. weil
der Slave den I2C deaktiviert hat), dann sieht der Master das NACK und
kann abbrechen oder dem entsprechend reagieren. Aber wenn I2C aktiv ist
aber der Slave keine Daten in TX-Buffer geschrieben hat, antwortet der
I2C-Protokoll mit dem blöden "Empty character" und das entspricht keinen
NACK sondern der Master denkt, er hätte ein Byte vom Slave empfangen.
Das kann ich natürlich beliebig oft wiederholen, der Master würde jedes
Mal das "Empty character" empfangen und würde denken, der Slabe hat die
geforderten Daten herausgegenen.
:'(
Cimbom Gs wrote:
> wenn Slave ein NACK erzeugt bzw SDA-Leitug auf HIGH beleibt (zBsp. weil> der Slave den I2C deaktiviert hat), dann sieht der Master das NACK und> kann abbrechen oder dem entsprechend reagieren.
Heißt das nun, der Slave sendet ein ACK?
In dem Fall ist Dein Fehler in der Slaveprogrammierung und nicht im
Master.
> Aber wenn I2C aktiv ist> aber der Slave keine Daten in TX-Buffer geschrieben hat, antwortet der> I2C-Protokoll mit dem blöden "Empty character" und das entspricht keinen> NACK sondern der Master denkt, er hätte ein Byte vom Slave empfangen.
Das geht nur, wenn Du den Slave nach dem ACK auf die Adreßerkennung
abschaltest.
Ansonsten hält nämlich der Slave das SCL solange auf low, bis Du ein
Datenbyte reinschreibst (Clock Stretching).
Der I2C Bus synchronisiert sich immer auf den langsamsten Teilnehmer.
Es kann nie ein Byte verloren gehen.
Ich würde Dir raten, wenn Du mit den Wizzard nicht klarkommst, ihn über
Board zu schmeißen und Dir selber die I2C-Beschreibung im Datenblatt
durchzulesen.
Zumindest in den Atmel- und Philips-Datenblättern gibt es wunderschöne
Zustandsgraphen und Ablaufdiagramme, die alle Phasen eines I2C-Transfer
ausführlich beschreiben, die Bedeutung aller Statusbits und die darauf
auszuführenden Aktionen.
Peter
@ Cimbom Gs (cimbomgs)
>kann abbrechen oder dem entsprechend reagieren. Aber wenn I2C aktiv ist
a>ber der Slave keine Daten in TX-Buffer geschrieben hat, antwortet der
>I2C-Protokoll mit dem blöden "Empty character" und das entspricht keinen>NACK sondern der Master denkt, er hätte ein Byte vom Slave empfangen.
Wenn man das WIKRLICH nicht abschalten kann, dann muss dein Slave VORHER
überlegen, ob er jetzt das aktuelle Datenpaket vollständig und schnell
genug in den TX-Buffer schreiben kann oder nicht. Wenn nein, wird das
Senden von ACK direkt nach der Adressierung verweigert. Das musst du
dem I2C Modul verklickern.
MfG
Falk
Wow... Der arme kleine I2C Bus...
Also es gibt drei Arten einen I2C Bus zu bremsen. Alle sind
spetifiziert, nur zwei davon sind geeignet Protokoll auf Byte-Ebene zu
bremsen.
Bit-Stretching:
-----------------------
Bit-Stretching (oder Clock-Stretching) ist eine implizite Methode, weil
der langsamere Partner am Bus durch das Ziehen auf LOW von SCL dem
schnelleren Partner signalisiert, dass er mit dem voran gegangenen Bit
noch beschäftigt ist.
Das ist vor allem dann wicht zu wissen, wenn man das Protokoll in
Software emuliert. Man muss nicht nur SCL loslassen, wenn man das
nächste Bit senden will, sondern man muss auch prüfen, ob SCL von allen
Partnern los gelassen wurde. Erst wenn SCL HIGH ist, beginnt die in der
Spec angegeben tHIGH zu laufen, nicht, wenn der Sender denkt, dass er
SCL high gesetzt hat!
Bit-Stretching kann im Übrigen, gerade in der Adressierungsphase, von
allen Chips am Bus genutzt werden, nicht nur von dem, denn man gerade zu
adressieren meint.
Byte-Stretching:
-----------------------
Nach einem Byte kann der SCL-Zyklus bis zum ACK verzögert werden. Dies
ist legal und absichtlich so vorgesehen, da es bei Controller basierten
Lösungen ( egal, ob Hardware- oder Software-Implementation) erforderlich
ist, zuerst einmal das Byte zu speichern und ggf. zu analysieren um
entscheiden zu können, ob nun ein ACK oder ein NACK geantwortet werden
muss.
Physikalisch wird es identisch zum Bit-Stretching behandelt (SCL LOW
halten, bis Antwort erfolgen kann, ACK/NACK an SDA anlegen und SCL los
lassen)
ACK-Polling
-----------------------
Um auf Protokoll-Ebene eine Verzögerung zu realisieren, kann man sein
Device Offline schalten. D.h. es antwortet auf seine Adresse nicht mit
ACK, sondern setzt entweder gezielt ein NACK oder ignoriert den
Busverkehr komplett.
EEPROMs schalten sich z.B. offline so lange sie mit dem internen
Programmieren beschäftigt sind. Möchte man weitere Daten schreiben, so
pollt man das EEPROM auf seiner Adresse, bis man wieder ein ACK erhält.
So kann man z.B. unterschiedlich schnelle EEPROMs mit ihrer maximalen
Geschwindigkeit nutzen, ohne die Software ändern zu müssen.
Auch vernetzte Mikrocontroller sollten diese Art der
Kommunikations-Verzögerung nutzen, da sie einfach zu realisieren ist.
Alle anderen Verzögerungen, wie zum Beispiel das immer wieder gerne
gemachte SCL low NACH DEM ACK sind illegal, tabu, nicht kontrollierbar.
Protokolle
-----------------------
Wer ein Protokoll auf I2C implementiert, sollte I2C komplett betrachten
und dann los legen. Ein Datenrahmen unbekannter Größe wird immer durch
ein START und ein STOP begrenzt. Mehr hat man nicht. Was man tun sollte
ist auch das letzte ACK mit einbeziehen. D.h. wenn ein Partner nicht
mehr zu empfangen hat, dann beantwortet er das letzte Byte mit NACK.
Das Protokoll sollte möglichst früh eine Angabe darüber machen, wie viel
Daten zu erwarten sind. D.h. man könnte es folgendermaßen aufbauen:
{ST}(ADR)[CMD][LEN][DATA]...[DATA]{SP}
{ST} ist die START-Kondition auf dem Bus
(ADR) Adressiert den Partner
[CMD] ist das Kommando
[LEN] die Anzahl der zum Kommando gehörenden und nun folgenden Parameter
[DATA] sind die Parameter oder Daten
{SP} ist die STOP-Kondition
Der Empfänger kann und sollte auf das letzte [DATA] mit NACK antworten.
So hat der Sender hier schon eine Information, ob er genauso viel
gelesen hat, wie er zu senden hatte.
Warum sende ich zuerst CMD und dann LEN? Nun so kann man einfach
dynamische Längen für einen CMD erzeugen und der Empfänger kann vorab
schon mal prüfen, welche Menge an Daten er mindestens und maximal haben
will.
Schon mit dem dann folgenden LEN kann ein Fehler aufgedeckt werden.
Timing
-----------------------
Beim Lesen der I2C Spec sollte man beachten, dass viele Timing-Parameter
als MIN angegeben sind. D.h. hier ist ein Minimum einzuhalten. Ich habe
schon viele Software-Implementationen gesehen, bei denen nahezu alle
Parameter irgendwie mit Gewalt exakt auf die in der Spec angegebenen
Zahlen gepresst wurden. Das ist i.d.R. falsch.
Gruß, Ulrich