Forum: Mikrocontroller und Digitale Elektronik Arduino I²C Adressevergabe


von Torsten O. (Gast)


Lesenswert?

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

von A.H. (Gast)


Lesenswert?

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);

von Michael A. (Gast)


Lesenswert?

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.

von Klaus (Gast)


Lesenswert?

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

von A.H. (Gast)


Lesenswert?

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.

von Torsten O. (Gast)


Lesenswert?

@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

von Klaus (Gast)


Lesenswert?

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

von Torsten O. (Gast)


Angehängte Dateien:

Lesenswert?

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

von Matthias (Gast)


Lesenswert?

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 ...

von Matthias (Gast)


Lesenswert?

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.

von Torsten O. (Gast)


Lesenswert?

Was genau verstehst du denn nicht?

von Michel (Gast)


Lesenswert?

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.

von Torsten O. (Gast)


Lesenswert?

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

von Matthias (Gast)


Lesenswert?

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

von Torsten O. (Gast)


Lesenswert?

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

von Matthias (Gast)


Lesenswert?

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.

von Torsten O. (Gast)


Lesenswert?

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

von A.H. (Gast)


Lesenswert?

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.

von Daniel S. (weasel)


Lesenswert?

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

von Rufus Τ. F. (rufus) Benutzerseite


Lesenswert?

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
Noch kein Account? Hier anmelden.