Hallo, ich bin gerade dabei einen DA-Wandler zu basteln, d.h. ich nutze als Wandler den DAC7573 von TI und möchte diesen gerne mit einem Arduino via I²C ansteuern. Ich habe da ein Problem mit der Adressvergabe. Laut DAC-Datenblatt sind die oberen fünf Bits werksseitig festgelegt, nämlich zu : #10011 Nun folgen noch drei Bits, zwei für die Hardwareseitige Adresse (die lege ich mit Pins fest, in meinem Fall sind sie auf +5V) und das Lese-/Schreibbit. Es ergibt sich also folgende Adresse : #10011110. Bevor ich den DAC angeschlossen habe, habe ich eine Kommunikation mit zwei Arduino (Uno) aufgebaut um mal zu testen wie das mit dem I²C funktioniert. Gleichzeitig habe ich ein Oszi mit seriellem Dekoder angeschlossen um zu sehen ob die richtigen Daten gesendet werden. Mache ich diesen Test mit den beiden Arduinos und der Adresse 0x02 funktioniert alles unproblematisch. Wenn ich allerdings die Adresse des DAC's verwende wird das oberste Bit (also das MSB) verschluckt. D.h. als Adresse wird nur #00011110 gesendet. Somit kann der DAC natürlich nicht antworten weil das nicht seiner Adresse entspricht. Hat vielleicht jemand einen Tipp wie ich das Problem lösen kann? lg Torsten
Die Arduino Wire-Bibliothek, die du vermutlich verwendest, hat die dumme Angewohnheit, die I²C Adresse nur als 7 Bit breit zu betrachten. Daher muss man die Adressen aus dem Datenblatt erst einmal nach rechts shiften. Bei dir also so: Wire.beginTransmission(0x9E>>1);
A.H. schrieb: > Die Arduino Wire-Bibliothek, die du vermutlich verwendest, hat die dumme > Angewohnheit, die I²C Adresse nur als 7 Bit breit zu betrachten. Die I2C Adresse ist definitionsgemäß 7-Bit. Die ganze Verwirrung rührt daher, dass das erstes Datenbyte (zusammengesetzt aus 7-Bit Adresse und R/W Flag) oft fälschlicherweise mit der I2C-Adresse gleichgesetzt wird.
Torsten Ohne schrieb: > Laut DAC-Datenblatt sind die oberen fünf Bits werksseitig festgelegt, > nämlich zu : #10011 > > Nun folgen noch drei Bits, zwei für die Hardwareseitige Adresse (die > lege ich mit Pins fest, in meinem Fall sind sie auf +5V) und das > Lese-/Schreibbit. Es ergibt sich also folgende Adresse : #10011110. Hier wird das Datenblatt falsch interpretiert. Es folgen 2 Bits, festgelegt durch die Pins. Eine I2C Adresse hat 7 Bit, so steht's in der Spec. A.H. schrieb: > Wire.beginTransmission(0x9E>>1); Das ist überflüssig, wenn man die Adresse gleich richtig macht. Außerdem wird das R/W Bit, daß vorher reingesetzt wurde, wieder entfernt. Ich kenne die Library nicht, das R/W Bit muß aber irgendwie gesetzt werden. Also noch mal die Doku lesen. MfG Klaus
Im DAC7573 Datenblatt ist die Adresse so angegeben:
1 | Address Byte |
2 | MSB LSB |
3 | 1 0 0 1 1 A1 A0 R/W |
Anschließend wird weiterhin vom "Address Byte" gesprochen, das unmittelbar nach START gesendet wird. Die andere übliche Darstellung der Adresse in Datenblättern ist die hexadezimale Angabe einer "Basisadresse", in diesem Beispiel 0x98. In der Theorie mag die I2C Adresse nur 7 Bit haben und so mag es auch in den I2C Protokollspezifikationen stehen. Aber in der Praxis wird die Adresse in den mir bekannten Datenblättern der größeren Hersteller immer linksbündig angegeben. Damit kann man die Angaben aus den Datenblättern direkt ohne Herumrechnen in die Register schreiben. Es sei denn, eine Library in der Mitte sieht das anders... Mein Vorschlag, "0x9E >> 1" zu schreiben, gründet auch darauf, dass man diesen Wert leichter den Werten im Datenblatt zuordnen kann als z.B. "0x4F". Außerdem ist dann auch gleich klar, warum man shiftet... :-) Zur Wire Lib: Bei ihr werden die zu sendenden Daten zwischengespeichert. Die eigentliche Übertragung findet erst bei "Wire.endTransmission()" statt. Bis dahin merkt sie sich auch die Schreib/Lese-Richtung. Aber da der TO zwischen zwei Arduinos ja schon kommunizieren kann, stellt das vermutlich kein Problem dar.
@Klaus : Ich glaube nicht, dass ich das Datenblatt falsch interpretiert habe. Denn die Sache mit den Adressbits und dem R/W-Bit habe ich doch in meinem Beitrag erwähnt, oder? @A.H. : Danke für den Tipp mit dem Sendezeitpunkt. Das hatte ich so noch nicht mitbekommen. Ich werde die Geschichte mit dem Shiften mal testen und ggfs. auch den Quelltext und einen Screenshot vom Oszi online stellen sobald ich wieder im Labor bin. Also erstmal vielen Dank für die Tipps, ich melde mich sobald ich mehr weiß. Schönes Wochenende euch allen. lg Torsten
A.H. schrieb: > Im DAC7573 Datenblatt ist die Adresse so angegeben: > Address Byte > MSB LSB > 1 0 0 1 1 A1 A0 R/W > > Anschließend wird weiterhin vom "Address Byte" gesprochen, das > unmittelbar nach START gesendet wird. Na da stehts ja doch. "Address Byte" (AKA erstes Byte eines I2C Telegramms) nicht Adresse. Außerdem wird auch ganz fein durchgezählt: A0, A1, 1, 1, 0, 0, 1 --> 0x46 - 0x4f für die Adresse. Oder kennst du die Zählweise der Bits A-1, A0, A1 ... An anderer Stelle aus dem Datenblatt: > The master then generates the SCL pulses, and transmits the 7-bit > address... Soll ich jetzt daraus schließen, daß TI nicht zu den größeren Herstellern zählt? MfG Klaus
G' Morgen, so, nun habe ich mal die Quelltexte und einen Screenshot des Oszis dabei. Der Master sieht wie folgt aus :
1 | /* Programm : voltage.pde
|
2 | Funktion : analoge Spannungsausgabe */
|
3 | |
4 | #include <Wire.h> |
5 | |
6 | void setup() |
7 | {
|
8 | // I²C - Bus als Master initialisieren
|
9 | Wire.begin(); |
10 | }
|
11 | |
12 | void loop() |
13 | {
|
14 | Wire.beginTransmission(0xfe); |
15 | Wire.send(0xd2); |
16 | Wire.send(0xff); |
17 | Wire.send(0xf0); |
18 | Wire.endTransmission(); |
19 | |
20 | delay(0x0400); |
21 | }
|
Der Slave sieht wie folt aus :
1 | /* Programm : slave.pde
|
2 | Funktion : serielle Ausgabe */
|
3 | |
4 | #include <Wire.h> |
5 | |
6 | void setup() |
7 | {
|
8 | // serielle Schnittstele initialisieren
|
9 | Serial.begin(9600); |
10 | |
11 | // I²C - Bus als Slave initialisieren
|
12 | Wire.begin(0xfe); |
13 | Wire.onReceive(receiveData); |
14 | }
|
15 | |
16 | void loop() |
17 | {
|
18 | delay(0x64); |
19 | }
|
20 | |
21 | void receiveData(int length) |
22 | {
|
23 | byte timeout = 0xff; |
24 | |
25 | do
|
26 | {
|
27 | if (Wire.available()) |
28 | {
|
29 | Serial.write(Wire.receive()); |
30 | timeout = 0x00; |
31 | } else |
32 | {
|
33 | timeout--; |
34 | }
|
35 | } while (timeout != 0x00); |
36 | }
|
Screenshot des Oszis siehe Anhang. Also der Master soll an den Slave mit der Adresse (0xfe) Daten senden. Den Slave habe ich genau mit dieser Adresse eingerichtet (siehe setup() des Slaves). Das niederwertigste Bit der Adresse stellt nun das R/W-Bit dar, eine "null" bedeutet "Master will senden", richtig soweit? Auf dem Screenshot ist deutlich die Adresse (türkis) sowie die übermittelten Daten (dunkelblau) zu erkennen. Aufgrund der Anzeige der Adresse von 0x7e lässt sich schlussfolgern, dass das höchstwertigste Bit offensichtlich von der Arduinosoftware ignoriert wird. Oder habe ich tatsächlich einen ganz doofen Denkfehler? lg Torsten
A.H. schrieb: > In der Theorie mag die I2C Adresse nur 7 Bit haben und so mag es auch in > den I2C Protokollspezifikationen stehen. Das tut es. In der I2C-Spezifikation von NXP/Phillips (Rev. 3 Jun 2007) steht 3.10 The slave address and R/W bit steht "...This address is 7 bits long followed by an eighth bit which is a data direction bit (R/W)— ..." http://www.nxp.com/documents/user_manual/UM10204.pdf Klare Worte vom Erfinder/Patentinhaber des I2C. Also immer schön wachsam sein ...
Torsten Ohne schrieb: > > Auf dem Screenshot ist deutlich die Adresse (türkis) sowie die > übermittelten Daten (dunkelblau) zu erkennen. Aufgrund der Anzeige der > Adresse von 0x7e lässt sich schlussfolgern, dass das höchstwertigste Bit > offensichtlich von der Arduinosoftware ignoriert wird. Schicke doch versuchsweise mal ein Read-Commando an die Adresse 0x38 und poste das Oszillogramm. Damit sollte besser zu verstehen sein, was da passiert.
Torsten Ohne schrieb: > Was genau verstehst du denn nicht? Wenn im Oszillogramm als erstes Datenbyte 0xFC zu sehen ist, also ein Write an die (7-Bit) I2C Adresse 0x7E, dann deutet das darauf hin, dass Wire.beginTransmission() als Parameter eine (7-Bit) I2C Adresse erwartet und das 8-te Bit einfach wegmaskiert, weil 0xFE als Adresse nicht existiert.
Soweit, dass das achte Bit ausmaskiert wird waren wir ja nun schon - genau das ist ja das Problem. Die Frage ist nach der Abhilfe? Ich stelle mir auch die Frage welchen Sinn es ergeben sollte, die I²C-Adressen zu minimieren indem man das achte Bit ignoriert? Falls das tatsächlich so sein sollte, müssten sich die Leute von Arduino etwas dabei gedacht haben, oder sehe ich das falsch? lg Torsten
Michel schrieb: > ... und das 8-te Bit einfach wegmaskiert, weil 0xFE als Adresse nicht > existiert. Torsten Ohne schrieb: > ..., dass das höchstwertigste Bit offensichtlich von > der Arduinosoftware ignoriert wird. ... > Oder habe ich tatsächlich einen ganz doofen Denkfehler? Michel interpretiert das ganz richtig. Das 8-te Bit wird genaugenommen nicht von der Arduinosoftware ignoriert sondern ist in der I2C Spezifikation gar nicht vorgesehen, so dass der Software nichts anderes übrigbleibt, als dein 0xFE erstmal auf die als I2C Adresse zulässigen 7 Bit zurechtzustutzen. MfG
So dachte ich mir es eben auch. Das würde bedeuten, ich muss das achte Bit welches im Datenblatt des DAC's steht gedanklich um eine Stelle nach rechts schieben - und alle anderen dann auch. Sehe ich das richtig? lg Torsten
Torsten Ohne schrieb: > Sehe ich das richtig? Ja, nicht ohne Grund unterscheidet TI im Datenblatt von "Address" (z.B. in Fig. 34) und "Address Byte". Die Arduinosoftware weiss die Datenrichtung auf Grund der aufgerufenen Methode (beginTransmission) und fügt der übergebenen 7-Bit Adresse das R/W-Bit automatisch hinzu. Sonst hätte dein Oszillogramm 0x7F als Adresse zeigen müssen.
Ah alles klar, jetzt funktioniert es und der DAC macht das was er soll. Nämlich Spannungen ausgeben. Doof nur, dass er manchmal abschaltet - naja, den Fehler finde ich auch noch. Vielen herzlich Dank euch allen lg Torsten
Torsten Ohne schrieb: > So dachte ich mir es eben auch. Das würde bedeuten, ich muss das achte > Bit welches im Datenblatt des DAC's steht gedanklich um eine Stelle nach > rechts schieben - und alle anderen dann auch. Sehe ich das richtig? A.H. schrieb vorher im Beitrag #2247091: > Daher muss man die Adressen aus dem Datenblatt erst einmal nach rechts > shiften. ... Scheinbar führen viele Wege nach Rom ;-) Hauptsache es funktioniert jetzt.
Torsten Ohne schrieb: > Ah alles klar, jetzt funktioniert es und der DAC macht das was er soll. > Nämlich Spannungen ausgeben. Doof nur, dass er manchmal abschaltet - > naja, den Fehler finde ich auch noch. > > Vielen herzlich Dank euch allen > > > lg Torsten Wie genau sehen denn deine ersten Bytes aus die du in den DAC schickst? Bzw. die ersten Befehle vom Arduino? Gruß Weasel
Daniel Schweda schrieb: > Wie genau sehen denn deine ersten Bytes aus die du in den DAC schickst? Glaubst Du, daß nach knapp vier Jahren noch jemand auf Deine Frage gewartet hat?
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.
