Hallo Forum,
ich versuche gerade auf einem Freescale Mikrocontroller (MC56f8036) die
TWI/I²C-Inerface zu implemtieren.
2 Mikrocontroller sollen als Master/Slave kommunitieren.
Für I²C-Schnittstelle nehme ich Pin 1 als SDA und Pin 42 als SCL
(GPIOB6 -> SDA; GPIOB8 -> SCL).
über 2,7 kOhm Widerstände sind beide Leitungen mit 3,3 V verbunden
(Pull-up).
1 Mikrocontroller ist als Master und der andere ist als Slave
konfiguriert.
Damit ich sehe dass die Verbindung funktioniert und die Kommunikation
stattfindet, will ganz einfach STARTEN und ADRESSE vom Slave auswählen.
Wenn ich das hab, dann müsste ich doch ACK vom Slave erhalten oder wenn
die Adresse nicht existiert, dass ich Fehlermeldung erhalte.
Egal welche Adresse ich auswähle, bekomme ich OK Meldung.
Die Entwicklungsumgebung ist CodeWarrior.
Bin für jede Hilfe sehr dankbar
Bob
Ein ACK darf es nur bei übereinstimmender Adresse geben. Beim Datenbyte
ist das ACK bei den meisten Slave-Devices nicht aktiv.
Hast Du bei dem Slave-uC die I2C-Adresse schon programmiert ?
Hast Du technisch die Möglichkeit ein Oszibild von der SCL- und der
SDA-Leitung hier ins Forum zu stellen ?
Ich erkenne auf dem Bild nicht die Adresse 0x10, sondern 0x20, gefolgt
von dem 9. Clock für das ACK. Wenn der Slave auf die Adresse 0x10
reagieren soll, wird er seine SDA-Leitung während des ACK-Pulses nicht
auf Masse ziehen.
Zum Oszibild:
Das erste Byte fängt wohl nach dem etwas verlängerten High-Impuls auf
der SDA-Leitung an. Bei jeder steigenden Flanke der SCK-Leitung wird der
Zustand auf der SDA-Leitung überprüft. Man kommt dann auf das Bitmuster
00100000(1), was hexadezimal 0x20 entspricht.
Zu dem I2C-Tool:
Mir fällt auf, dass dort "7-bit-address" eingestellt ist. Probier das
mal mit "8-bit-address", wenn sich das machen läßt. Das wäre nämlich die
Erklärung, dass er das Byte um einen Clock nach links verschiebt.
Dann versuch's mal mit der Burst durch's Auge und konfigurier den Slave
mit Adresse 0x20, also dem Wert, den ich auf dem Bus erkenne. Dann
sollte das 9.Bit LOW sein, weil der Slave seine Adresse erkannt hat.
hmm.. wenn ich die Slave-Adresse 0x20 auswähle, bekomme ich 0100 0000
(0x40) als Bitmuster.
ist für dich der zweite High-Pegel ACK vom Slave? Warum bekomme ich dann
immer diesen zweiten High-Pegel?
Du sieht 9 mal einen Clock-Impuls pro Byte. Die ersten acht Bit stehen
für das Datenbyte, das letzte bit ist das ACK. Wenn die Adresse erkannt
wird, muss es auf LOW liegen.
Noch eine andere Möglichkeit, wenn's nicht weiterführt : Ich sehe, das
Datenbyte wird ständig gesendet. Interessant wäre das Verhalten nach
einem Reset des I2C-Slaves. Denn wenn einmal ein Bit zuviel oder zuwenig
gesendet wird, "verschluckt" sich der Slave und ist nicht mehr
bytesynchron. Auch auf die Adresse richtige kann er dann nicht mehr
reagieren.
@ M. H.
danke du warst eine große Hilfe.
7bit Adresse ist 7 Bit groß. Das 8. Bit steht für read/write und das 9.
ACK/NACK.
beim 8. Puls durch runterziehen des High-Pegels auf Low bestätigt Slave
das alles OK ist :-)
beim Datenübertragen habe ich Probleme:
wenn ich Daten an Slave sende, wird es in "I2C_DATA"-Register
festgehalten aber wenn ich versuche vom Slave zu lesen, bekomme ich
keine Daten.
Beim Slave werden doch die Daten zum übertragen im "I2C_TXFT"-Register
gespeichert und wenn Master zum lesen auffordert, müsste Master doch die
Daten vom "I2C_TXFT"-Register abholen/bekommen oder stimmt das nicht?
Ich habe gerade das Datenblatt des MC56F8036 überflogen. Da gibt es
zunächst ein Register I2C_DATA, welches als Receive- und
Transmit-Register konzipiert ist. Probier dort mal Dein Byte dort
reinzuschieben.
Das I2C_TXFT ist eher ein Fifo, gedacht für den Fall, dass der Slave
mehrere Bytes zeitlich hintereinander senden soll, aber die Zeit zum
Nachladen des I2C_DATA-Registers möglicherweise nicht ausreicht.
hmmm.. etwas ist faul, aber weiß nicht was faul ist.
beim Slave schreibe schreibe ich ins Data-Register und will beim Master
es auslesen aber es will nicht.
Ich benutze sowohl die Funktion RecvChar() ( ANSIC prototype: byte
RecvChar(byte *Chr) ) als auch das Data-Register beim Master, aber steht
immer eine 0 drin
habe ein Bild vom Oszi eingefügt.
Was passiert nach dem 9.Clock? ( SDA->HIGH; SCL->LOW und SCL ist länger
als sonst)
Und am Ende kommt ein NACK (weil SDA auf HIGH)
Sieht so aus, als ob der Slave tatsächlich 0x00 zurückschickt, der
Fehler liegt wohl an der Slavekonfiguration.
Sind die zugehörigen I2C-Register richtig konfiguriert ? Ich meine
verlangt das Telegramm nach einer Antwort vom Slave ? Wie Du gesehen
hast gibt es Read- und Write-Telegramme. Der Slave muss so konfiguriert
sein, dass sein Datenbyte auch abgefragt wird.
Hast Du mal probiert v o r dem Empfang der I2C-Adresse das
I2C_DATA-Register mit einem Wert zu beschreiben ?
wenn ich vor dem Empfang der I²C-Adresse das I2C_DATA-Register mit einem
Wert zu beschreibe, sendet der Master kein STOP Condition mehr und am
Bus liegt immer dieser Wert, was in das I2C_DATA-Register beschrieben
wurde.
Der Slave muss immer mit ACK/NACK antworten.
Das erste Telegramm beinhaltet (7bit Slaver Adresse + 1bit Read/Write +
ACK/NACK) und alle anderen (8bit für Daten + 1bit ACK/NACK), dh. wenn
Master Daten sendet/empfängt muss Slave mit ACK reagieren
Dass der Slave immer mit einem ACK antwortet ist nicht richtig. Leider
ist da I2C nicht einheitlich. In vielen Fällen wird das Datenbyte mit
NACK quittiert, d.h. das 9.Bit bleibt auf HIGH ! Am besten Du
verifizierst über das Datenblatt, wie sich der I2C des MC56F8036
tatsächlich verhält.
Kann mir bitte jemand helfen??
Ich benutze den selben Mikrocontroller und habe einige Probleme bei der
I²C-Kommunikation.
Mein Problem ist, dass mein Master immer die vorherige Werte vom Slave
erhält und beim ersten Start bekomme ich immer eine Null.
Dh. sobald ich I²C-Bus starte und den Wert vom Slave abhole, erhalte ich
eine Null..UND das nächste Mal erhalte ich die Werte von vorher..
Was kann ich machen? Oder wie kann ich das umgehen??
Da ich 2 Werte vergleiche, brauche ich immer die aktuellen Werte
und noch eine Frage:
Ist es normal, dass man über I²C-Bus immer vom Slave die vorherigen Wert
erhält??
Danke
Doktor Gnadenlos wrote:
> Nein, das ist nicht normal. Was hast Du für ein I2C-Slave dranhängen ?> Hast Du mal im Datenblatt von diesem I2C-Baustein nachgeschaut ?
Ich benutze 2 mal den gleichen Mikrocontroller. Habe den einen als Slave
und den anderen als Master konfiguriert.
Ich weiß nicht voran es liegt aber habe fast alles mögliche ausprobiert
->jedes mal das gleiche.
Wenn du da immer die zu alten Werte zurüc kbekommst, dann ist
wahrscheinlich deine Routine auf dem Slave fehlerhaft.
Ich kann mich erinnern, daß es bei der Freescale implementierung des
Slave nicht ganz einfach war die richtigen Daten auch schnell genug
bereit zu stellen.
Doktor Gnadenlos wrote:
> Bist Du sicher, dass auch der jeweils vorige Wert verschickt wird oder> liegt der Fehler in der Software ?> Hast Du das mal mit einem Oszi überprüft ?
ich benutze parallel dazu einen Oszi aber bringt nicht viel, da die
Werte sich ständig ändern und ich ja die Signale nicht zwischenspeichern
kann.
aber ich benutze 2 PCs und habe Brakepoints gesetzt. Wenn ich das ganze
debugge dann sehe ich ganz genau, dass der Master immer den alten Wert
vom Slave hat. Was aber gar nicht sein sollte. der Slave müsste immer
den aktellen Wert für den Master in den Buffer legen.
ps. auch wenn ich einen Langen delay beim Master einfüge, bekommt Master
das erste Mal immer nur Nullen.
Naja, bis jetzt finde ich noch nichts verdächtiges. Mir fällt auf, dass
es nur ein gemeinsames Register für Senden und Empfangen gibt.
Wann wird der zu sendende Wert des Slaves ins Register I2C_Data
geschrieben ? Etwa schon vor dem I2C-Interupt ?
Evtll. muss das Register bei Auftreten des Interrupt und vor jedem
Senden erst noch gelesen werden, auch wenn der Wert keine Info enthält.
volatile unsigned char bDummy;
bDummy = I2C_Data;
Doktor Gnadenlos wrote:
> Wann wird der zu sendende Wert des Slaves ins Register I2C_Data> geschrieben ? Etwa schon vor dem I2C-Interupt ?
immer dann wenn ein START-Condition ausgelöst wurde. Slave wartet bis
Master gestarte hat, danach wird der Wert in den Register geschieben.
kann mir niemand helfen :'( BITTEEEE
ich drehe noch durch %-(
1
2
I2C1_SetMode(master);
3
do
4
{
5
I2C1_SelectSlave(slave_addr);
6
Err=I2C1_SendBlock(&send_chr,1,&send_temp);
7
}while((Err!=ERR_OK));
8
9
10
oder
11
12
13
I2C1_SetMode(master);
14
do
15
{
16
I2C1_SelectSlave(slave_addr);
17
I2C1_SendChar(send_chr);
18
}while((data_send!=TRUE));// data_send wird in ISR auf TRUE gesetzt
warum wird das Datum gesendet obwohl ich gar kein Slave verbunden habe?!
Ich habe die Verbinding zwischen Master und Slave getrennt aber der
Master behauptet trotzdem er hätte an Slave das Datum gesendet....aaaaa
das kann doch gar nicht sein -> es existiert überhaupt kein Slave
seid einer Woch bin ich dabei den Fehler zu finden, was kann es nur
sein?
Bitte gibt mir paar Tipps, was ich Testen sollte bzw. wie ich den Fehler
entdecken könnte BITTEEEEEEE...
Cimbom Gs wrote:
> warum wird das Datum gesendet obwohl ich gar kein Slave verbunden habe?!> Ich habe die Verbinding zwischen Master und Slave getrennt aber der> Master behauptet trotzdem er hätte an Slave das Datum gesendet....aaaaa> das kann doch gar nicht sein -> es existiert überhaupt kein Slave>
Hast du korrekte Pullups am Bus? Wenn man SDA extern mit Masse
verbindet, denkt der Master immer die Slaves sind da. Außerdem Antworten
die Slaves auf alles mit 0x00.
Und bei deinen verschobenen Antworten denke ich, du stellst die Daten
nicht schnell genug bereit. Deshalb sendet der Slave mit dieser
Verschiebung.
Mike S. wrote:
> Hast du korrekte Pullups am Bus?
ja habe ich
> Und bei deinen verschobenen Antworten denke ich, du stellst die Daten> nicht schnell genug bereit. Deshalb sendet der Slave mit dieser> Verschiebung.
ja aber auch wenn ich eine lange Warteschleife beim Master einfüge,
passiert das Selbe..
o man o man ich weiß echt nicht mehr was ich machen soll :'(..
Kollege von mir hat sich das angeschaut, der hat sich auch gewundert wie
das passieren kann..