Forum: Mikrocontroller und Digitale Elektronik Freescale I²C/TWI Implementierung


von Bob (Gast)


Lesenswert?

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

von M. H. (doktorgnadenlos)


Lesenswert?

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 ?

von Bob (Gast)


Angehängte Dateien:

Lesenswert?

ich übergebe dem Slave die Adresse 0x10 und damit muss doch die Adresse 
festgelegt sein..

ich war gerade dabei ein Bild von Oszi zu machen :-)

von M. H. (doktorgnadenlos)


Lesenswert?

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.

von Bob (Gast)


Angehängte Dateien:

Lesenswert?

wie erkennst du dass es 0x20 ist?

Habe für "Slave Address" 0x10 eingetragen.

von M. H. (doktorgnadenlos)


Lesenswert?

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.

von Bob (Gast)


Lesenswert?

:-( es gibt aber nur 7bit oder 10bit Adresse

von M. H. (doktorgnadenlos)


Lesenswert?

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.

von M. H. (doktorgnadenlos)


Lesenswert?

"Brust", nicht "Burst" :-)

von Bob (Gast)


Lesenswert?

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?

von Bob (Gast)


Lesenswert?

auch bei der Slave-Adresse 0x20 bleit alles gleich

von M. H. (doktorgnadenlos)


Lesenswert?

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.

von Bob (Gast)


Angehängte Dateien:

Lesenswert?

@ 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 :-)

von Bob (Gast)


Lesenswert?

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?

von M. H. (doktorgnadenlos)


Lesenswert?

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.

von Bob (Gast)


Lesenswert?

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

von Bob (Gast)


Angehängte Dateien:

Lesenswert?

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)

von M. H. (doktorgnadenlos)


Lesenswert?

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 ?

von Bob (Gast)


Lesenswert?

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

von M. H. (doktorgnadenlos)


Angehängte Dateien:

Lesenswert?

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.

von Cimbom G. (cimbomgs)


Lesenswert?

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

von Doktor Gnadenlos (Gast)


Lesenswert?

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 ?

von Cimbom G. (cimbomgs)


Lesenswert?

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.

von Mike R. (thesealion)


Lesenswert?

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.

von Doktor Gnadenlos (Gast)


Lesenswert?

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 ?

von Cimbom G. (cimbomgs)


Lesenswert?

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.

von Doktor Gnadenlos (Gast)


Lesenswert?

Okay, mit welchem Controller arbeitest Du ?
Im Datenblatt muss es ein Hinweis geben, der das Verhalten erklärt.

Ich schau mir das gern mal an.

von Cimbom G. (cimbomgs)


Lesenswert?

Freescale Mikrocontroller (MC56f8036)

ich habe das Datenblatt mehrmals durchblättert aber finde nichts :-(

von Doktor Gnadenlos (Gast)


Lesenswert?

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;

von Cimbom G. (cimbomgs)


Lesenswert?

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.

von Cimbom G. (cimbomgs)


Lesenswert?

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...

von Mike R. (thesealion)


Lesenswert?

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.

von Cimbom G. (cimbomgs)


Lesenswert?

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..

Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.