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
voidsetup()
7
{
8
// I²C - Bus als Master initialisieren
9
Wire.begin();
10
}
11
12
voidloop()
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
voidsetup()
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
voidloop()
17
{
18
delay(0x64);
19
}
20
21
voidreceiveData(intlength)
22
{
23
bytetimeout=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?