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?
- 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.
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.
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.
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...
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.
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.
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.
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.
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
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
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
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".
Ansonsten einfach alle möglichen Adressen von 0 bis 127 durchprobieren, irgend eine wird schon mit ACK antworten, die ist es dann.
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...
> 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 :)
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!
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
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!
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?
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.
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.
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
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)
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).
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
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.