Forum: Mikrocontroller und Digitale Elektronik 2 Slaves an I2C


von SPI_OUT (Gast)


Lesenswert?

Hallo,

ich nutze einen Slave1 (AD-Wandler) via I2C. Jeweils 2 Pull-UPs (10K) an 
SCL und SDA, funktioniert wunderbar. Wenn ich jetzt einen zweiten Slave 
an den BUS von SCL hänge (es werden noch keinerlei Routinen von Slave2 
abgearbeitet, sondern nur die reine Hardware Anbindung) funktioniert die 
Kommunikation mit Slave 1 nicht mehr. Natürlich haben die beiden Slaves 
eine andere Device Adresse.

Woran kann/könnte das liegen?

von Max D. (max_d)


Lesenswert?

- Zu lange Leitung => Kapazität zu hoch
- Versorgung von Slave2 aus => er zeiht den Bus rutner
- Slave2 defekt => Bus gestört

Du wirst schon etwas genauer werden müssen.

von Lothar M. (Firma: Titel) (lkmiller) (Moderator) Benutzerseite


Lesenswert?

SPI_OUT schrieb:
> Woran kann/könnte das liegen?
An der Hardware oder an der Software....

Für eine genauere Auskunft fehlen nötige Informationen.

von Oliver R. (orb)


Lesenswert?

Die PullUps sind zu groß. 4,7k gegen 5Volt oder 1,8k gegen 3,3Volt sind 
üblicher.
Allerdings sollte das bei so einem kleinen Aufbau nicht zul Ausfall 
führen.

von Lothar M. (Firma: Titel) (lkmiller) (Moderator) Benutzerseite


Lesenswert?

Oliver R. schrieb:
> bei so einem kleinen Aufbau
Woher weißt du dass der Aufbau klein ist. Hinterher stellt sich raus, 
dass da 20m Kabel mit einem 10k Pullup hochgezogen werden müssen...

von SPI_OUT (Gast)


Lesenswert?

Hmm, es schien wirklich an den Pullups gelegen zu haben, obwohl in den 
Datenblättern beider Slaver 10K postuliert sind. Wie kann sowas sein. 
Mein Aufbau hie rauf dem Steckbrett mit einigen Steckbrücken ist dazu 
sicherlich suboptimal.

von Bernd K. (prof7bit)


Lesenswert?

SPI_OUT schrieb:
> obwohl in den
> Datenblättern beider Slaver 10K postuliert sind. Wie kann sowas sein.

Schau nach welcher Strom maximal in die SDA und SCL Pins hinenfließen 
darf (wenn der Slave die auf Masse zieht) laut deren Datenblättern 
(üblicherweise so um die 5mA). Du kannst die Pullups so lange kleiner 
machen solange dieser Strom nicht überschritten würde, also 1.2k würden 
evtl sogar auch noch gehen bei 5V.

Es gibt auch I²C Bus Treiber, die erlauben noch viel weiter 
runterzugehen mit dem Widerstand und somit längere Strecken zu 
überbrücken.

Ein niedrigerer Pullup verkleinert die Zeitkonstante des RC-Gliedes das 
sich aus Leitungskapazität und Pullup bildet, somit erhöht ein kleinerer 
Pullup die mögliche Taktfrequenz oder erlaubt eine längere Leitung bei 
gleicher Taktfrequenz.

JEDOCH ist das ein zweischneidiges Schwert, ich hab schon Bauteile 
gesehen die hatten schon mit 4.7k ihre liebe Not die Leitung noch 
ordentlich auf Masse ziehen zu können, auch wenn im Datenblatt von 
größeren Strömen die Rede war. Hier wirkt ein zu kleiner Pullup eher 
kontraproduktiv.

Also im Zweifelsfalle mal das Oszi dranhängen (Tastkopf möglichst 
hochomig einstellen) und sich die Signale anschauen.

von Oliver R. (orb)


Lesenswert?

Lothar Miller schrieb:
> Woher weißt du dass der Aufbau klein ist

SPI_OUT schrieb:
> Mein Aufbau hie rauf dem Steckbrett

Meine Glaskugel ist endlich aus der Reparatur zurück ...
Oder einfach nur glücklich geraten.

von Dieter W. (dds5)


Lesenswert?

Bernd K. schrieb:
> Ein niedrigerer Pullup verkleinert die Zeitkonstante des RC-Gliedes das
> sich aus Leitungskapazität und Pullup bildet ...

Nicht zu vergessen die Eingangs- bzw. Ausgangskapazitäten der 
angeschlossenen IC.

von SPI_OUT (Gast)


Lesenswert?

Vielen Dank für die ausführlichen Anmerkungen.

Ich habe das Problem, dass jetzt der Slvae2 (24LC64 EEPROM von 
Microchip) nicht mit einem ACK auf die Deviaadresse reagiert. Ich 
spreche das EEPROM mit demselben Code an mit dem ich schon andere Slaves 
per I2C angesprochen habe.
A0 = High, A1, A2 = LOW:
1
// Address from 0x0000 to 0x1FFF
2
// DataByte from 0x00 to 0xFF
3
void Write_Byte_To_24LC64_EEPROM(unsigned int Address, unsigned char DataByte)
4
{
5
    BOOL    Success = TRUE;
6
    I2C_7_BIT_ADDRESS   SlaveAddress;
7
    I2C_FORMAT_7_BIT_ADDRESS(SlaveAddress, EEPROM_24LC64_ADDRESS, I2C_WRITE);
8
9
    Nop();
10
    Nop();
11
12
     // Start the transfer to write device address to the HY3118
13
    if( !StartTransfer(FALSE) )
14
    {
15
        while(1);
16
    }
17
18
19
    // Slave Adresse muss von ACK bestätigt werden
20
21
22
    // Transmit deviceaddress byte
23
    if(TransmitOneByte(SlaveAddress.byte))
24
    {
25
            Nop();
26
    Nop();
27
        // Verify that the byte was acknowledged
28
        if(!I2CByteWasAcknowledged(EEPROM_24LC64_I2C_BUS))
29
        {
30
// HIER Bleibt MCU in der Schleife hängen
31
           DBPRINTF("Error: Sent byte was not acknowledged\n");
32
           Success = FALSE;
33
        }
34
...
35
    }
36
37
38
39
40
41
#define EEPROM_24LC64_I2C_BUS       I2C2        // I2C1 problematisch -> selbe wie HY3118
42
#define EEPROM_24LC64_ADDRESS       81          // device Address EEPROM: 1 | 0 | 1 | 0 | A2 | A1 | A0 | R/W = 1 | 0 | 1 | 0 | 0 | 0 | 1 | R/W (A0 = HIGH)
43
44
45
46
int main()
47
{
48
   // Enable the I2C bus
49
    I2CEnable(EEPROM_24LC64_I2C_BUS, TRUE);
50
    Write_Byte_To_24LC64_EEPROM(0x0001, 'd');
51
52
}

MCU ist ein PIC32.

Jemand eine Ahnung woran das liegen könnte. Habe jetzt kürzere Kabel 
genommen, PULL UPs rumexperimentiert und das EEPROM ausgetauscht.
Ohne Erfolg

von Sebastian F. (sf-e)


Lesenswert?

Hallo,

sind das beides die gleichen ICs? Ansonsten kann es natürlich sein, dass 
die nicht auf dieselbe Weise angesprochen werden können.

Was sind es denn für ICs, die beiden Slaves?

MfG Sebastian

von SPI_OUT (Gast)


Lesenswert?

Ich habe das EEPROM 24LC64 von Microchip jetzt ausgelagert und versuche 
nur dieses anzusprechen. Nach Datenblatt und wie bei I2C gewohnt wird 
nach der Sendung der Deviceadresse ein ACK erwartet. Das Empfangen der 
Deviceadresse wird aber nicht vom EEPROM mit einem ACK bestätigt und das 
Programm hängt in der oben angegebenen Schelife fest.

Dieselbe Routine hat bei einem anderen Slave jedoch schon einwandfrei 
funktioniert. Ich vermute also eher keinen Softwarefehler. Was nach 
Sendung der Deviceadresse kommt ist ja ersteinmal irrelevant, weil diese 
Kommunikation schon nicht funktioniert.

Die beiden EEPROMs sind schon recht alt, eigentlich aber unberührt. Wie 
kann ich testen ob diese überhuapt noch funktionstüchtig sind?

Gruß und Danke

von Easylife (Gast)


Lesenswert?

1 | 0 | 1 | 0 | A2 | A1 | A0 | RW

sind 8 bit.
Die Adresse ist also bei dir (A0 = High, A1, A2 = LOW)

1 0 1 0 0 0 1 x (x ist das read/write bit)

Da deine Funktion Write_Byte_To_24LC64_EEPROM() eine 7-bit Adresse 
erwartet, und hinten das R/W bit anhängt, musst du ihr folgende Adresse 
geben (ohne das R/W bit):

1 0 1 0 0 0 1 = 0x51

Wenn das nicht funktioniert, probiere mal 0x82, vielleicht täusche ich 
mich auch mit dem "R/W bit wird hinten angehängt".

von Easylife (Gast)


Lesenswert?

Ansonsten einfach alle möglichen Adressen von 0 bis 127 durchprobieren, 
irgend eine wird schon mit ACK antworten, die ist es dann.

von Lothar M. (Firma: Titel) (lkmiller) (Moderator) Benutzerseite


Lesenswert?

SPI_OUT schrieb:
> Das Empfangen der Deviceadresse wird aber nicht vom EEPROM mit einem ACK
> bestätigt
Hast du ein Oszilloskop?

Das was du da gerade machst ist, wie mit verbundenen Augen Angeln, dann 
gleich Grillen und dann probieren ob es ein Fisch war.

Mit einem Oszilloskop könntest du dir diese "Augenbinde" abnehmen und 
deinen "Fang" besser bewerten...

von SPI_OUT (Gast)


Lesenswert?

> 1 0 1 0 0 0 1 x (x ist das read/write bit)


über
1
I2C_FORMAT_7_BIT_ADDRESS(SlaveAddress, EEPROM_24LC64_ADDRESS, I2C_WRITE);

wird dann in der Tat das WRITE BIT über I2C_WRITE hinden an die Adresse 
angehangen.

-> 0x51 = 81

Müßte also passen.

> alle 127 Addressen durchprobieren

sehr witzig :)

von Lothar M. (Firma: Titel) (lkmiller) (Moderator) Benutzerseite


Lesenswert?

SPI_OUT schrieb:
> Müßte also passen.
Wenn alles passt, dann müsste es auch gehen. Hast du meinen Post nicht 
gelesen oder nicht gesehen?

Merke: wenn du an einer Schraube drehst, und es ändert sich nichts, dann 
war es die Falsche!

von Klaus (Gast)


Lesenswert?

Bernd K. schrieb:
> Schau nach welcher Strom maximal in die SDA und SCL Pins hinenfließen
> darf (wenn der Slave die auf Masse zieht) laut deren Datenblättern
> (üblicherweise so um die 5mA). Du kannst die Pullups so lange kleiner
> machen solange dieser Strom nicht überschritten würde, also 1.2k würden
> evtl sogar auch noch gehen bei 5V.

Das hilft dir garnicht. Da beide Seiten die Leitungen auf low ziehen 
können müssen, zählt der Treiber mit dem kleinsten Strom. Viel einfacher 
ist es den Wert aus der I2C Spec zu nehmen: 3mA

MfG Klaus

von SPI_OUT (Gast)


Lesenswert?

Lothar Miller schrieb:
> SPI_OUT schrieb:
>> Müßte also passen.
> Wenn alles passt, dann müsste es auch gehen. Hast du meinen Post nicht
> gelesen oder nicht gesehen?
>
> Merke: wenn du an einer Schraube drehst, und es ändert sich nichts, dann
> war es die Falsche!

Ich habe leider kein Oszi, darf ich jetzt erst weitermachen, wenn ich 
mir eins gekauft habe?

Danke trotzdem für den Hinweis. Ich möchte hier nicht als 
beratungsresistent rüberkommen und fbin für alle Tipps dankbar!

von SPI_OUT (Gast)


Lesenswert?

Die Funktionen laufen jetzt soweit. Was nicht funktioniert ist das 
Schreiben ins EEPROM und das direkt darauffolgende Lesen. D.h. ich muss 
zuerst schreiben, dann z.b. Controller reseten und warten und dann erst 
Lesen. Wie kann das sein?

von Easylife (Gast)


Lesenswert?

SPI_OUT schrieb:
>> alle 127 Addressen durchprobieren
>
> sehr witzig :)

War tatsächlich ernst gemeint.
Dafür gibt es ja Schleifen.
An deinem Code verstehe ich sowieso nicht, dass die Funktion 
Write_Byte_To_24LC64_EEPROM()
als ersten Parameter "Address" erwartet, die du dann aber gar nicht 
verwendest, da du direkt in der Funktion EEPROM_24LC64_ADDRESS 
verwendest.

Würdest du hier "Address" verwenden, und den Aufruf in main() so machen:
1
Write_Byte_To_24LC64_EEPROM(EEPROM_24LC64_ADDRESS, 'd');

könntest du auch locker alle 127 Adressen in main() durchprobieren 
lassen, und müsstest halt in Write_Byte_To_24LC64_EEPROM()
DBPRINTF("Error: Sent byte was not acknowledged\n");
rausnehmen, und stattdessen die geackte Adresse anzeigen lassen.

von SPI_OUT (Gast)


Lesenswert?

EEPROM_24LC64_ADDRESS  ist die "Device Adresse". Die richtige Adresse im 
EEPROM wird nach dem Senden der Device Adresse geschickt (im obigen Code 
noch nicht zu sehen -> erst high dann Low Byte).

Wie gesagt es funktioniert jetzt. Einzige Unklarheit ist warum direktes 
Lesen auf Schreiben noch nicht funktioniert.

von Karl H. (kbuchegg)


Lesenswert?

SPI_OUT schrieb:

> Wie gesagt es funktioniert jetzt.

Und. Was hast du geändert?
Lass uns nicht dumm sterben. Wenn wieder mal wer mit ähnlichen Symptomen 
kommt, werden sich einige erinnern und überlegen ob sein Fall ähnlich 
gelagert sein könnte.

: Bearbeitet durch User
von Michael .. (gismi)


Lesenswert?

SPI_OUT schrieb:
> Was nicht funktioniert ist das
> Schreiben ins EEPROM und das direkt darauffolgende Lesen. D.h. ich muss
> zuerst schreiben, dann z.b. Controller reseten und warten und dann erst
> Lesen. Wie kann das sein?

Du musst warten bis das EEProm die Daten Programmiert hat.
Im Datenblatt findest du die ungefähren Zeiten.

Ob das Programmieren abgeschlossen ist, findest du durch das sogenannte 
"ACKNOWLEDGE POLLING" heraus. (Datenblatt Seite 9)

von Bernd K. (prof7bit)


Lesenswert?

Klaus schrieb:
> Da beide Seiten die Leitungen auf low ziehen
> können müssen, zählt der Treiber mit dem kleinsten Strom.

Hab ich doch gesagt (implizit zumindest).

von SPI_OUT (Gast)


Lesenswert?

Karl Heinz schrieb:
> SPI_OUT schrieb:
>
>> Wie gesagt es funktioniert jetzt.
>
> Und. Was hast du geändert?



Der Fehler war wieder einmal auf eine Unkonzentriertheit zurückzuführen. 
Ich habe beim Lesebefehl bei der Device-adressierung das falsche Makro 
eingefügt, nämlich
1
#define EEPROM_24LC64_I2C_BUS       I2C2
2
#define EEPROM_24LC64_ADDRESS       80
3
4
5
I2C_FORMAT_7_BIT_ADDRESS(SlaveAddress, EEPROM_24LC64_I2C_BUS, I2C_READ);
6
// anstatt
7
I2C_FORMAT_7_BIT_ADDRESS(SlaveAddress, EEPROM_24LC64_ADDRESS, I2C_READ);

so konnte natürlich nie der richtige Slave adressiert werden. Vielen 
Dank auch nochmal an Michael für die Ausführungen bzgl. des ACKNOWLEDGE 
POLLING.

Gruß

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.