2 Slaves an I2C

Gast #3929611
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?
Gast #3929641
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.
#3929763
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.
Gast #3929876
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
Gast #3929960
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
Gast #3929986
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".
Moderator (Firma: Titel) Persönliche Seite #3930027
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...
Gast #3930505
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 :)
Gast #3930526
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
Gast #3930652
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!
Gast #3931062
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?
Gast #3931071
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.
Gast #3931084
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.
#3931139
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)
Gast #3934378
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ß

Antwort schreiben

Bitte melde dich an, um einen Beitrag zu schreiben.

oder

Mit Google-Account einloggen

Die Registrierung ist kostenlos und dauert nur eine Minute.

Jetzt registrieren