Mehrere Fragen zur I2C Deklaration

Hey Leute habe bezüglich I2C übertragungen noch nie wirklich etwas gemacht, haben in der Schule nur schnell ein Programm gezeigt bekommen jedoch ohne Erklärung. (ist eigentlich noch einiges länger, jedoch hier ein ausschnitt dazu)

I2C.begin();
I2C.beginTransmission(B10000010>>1);
I2C.write(1);
I2C.write((uint8_t)B00000000);
I2C.endTransmission();

Habe ich richtig erkannt dass bei "I2C.beginTransmission.....)
das Byte erst noch "geschoben" wird und dann eigentlich (B01000001); heißt?
Dann wäre der Dezimalwert zu diesem Binärwert nämlich 65 und
das würde nämlich laut Datenblatt für den angewendeten Baustein passen, den PCF8574, da dieser
bei dem wert 65 der I2C BUS SLAVE 8-BIT READ ADDRESS zustimmen würde

und warum wurde zu dem "I2C.write" noch ein uint8_t in die Klammer genommen? hätte man nicht einfach so B00000000); schreiben können?

wäre echt dankbar für hilfe :slight_smile:

Habe ich richtig erkannt dass bei "I2C.beginTransmission.....)
das Byte erst noch "geschoben" wird und dann eigentlich (B01000001); heißt?

Ja!

und warum wurde zu dem "I2C.write" noch ein uint8_t in die Klammer genommen? hätte man nicht einfach so B00000000); schreiben können?

Nein!
Denn:

  1. Konstanten sind per default vom Type int
  2. Wire.write() ist polymorph
    Das Resultat wäre also ein anderes.
    Wenn man in die Lib schaut, sieht man, dass der cast sowieso schon gemacht wird.

Also ja, der cast ist überflüssig.

Hier ist ein Link, wo die Verwendung des PCF8574 recht ordentlich beschrieben.

http://forum.arduino.cc/index.php?topic=107467.0

retro_:
...
I2C.beginTransmission(B10000010>>1);
...

Ich halte diese Zeile für dämlichen Blödsinn. Vielleicht ist das in dem Zusammenhang, in dem Du das gesehen hast, sinnvoll, aber ich programmiere immer so, dass man sich für überflüssiges Zeug keinen Knoten ins Hirn machen muss. Wenn ein Befehl eine Adresse benötigt, dann kommt da die Adresse in knotenfrei assoziierbarer Form hin. Von mir aus kann da ein Variablenname stehen oder eine Adresse in Hexadezimalschreibweise – aber nichts, wofür man erst klöppeln muss, um die eigentliche Bedeutung zu ergründen.

Also zum Beispiel

...
#define ADDRESS 5
...
I2C.beginTransmission(ADDRESS);
...

oder

...
byte address=x^2*PI/5;
...
I2C.beginnTransmission(address);
...

Kann sein, dass ich mit meiner Meinung faslch liege.

Gregor

Ich halte diese Zeile für dämlichen Blödsinn. Vielleicht ist das in dem Zusammenhang, in dem Du das gesehen hast, sinnvoll, aber ich programmiere immer so, dass man sich für überflüssiges Zeug keinen Knoten ins Hirn machen muss. Wenn ein Befehl eine Adresse benötigt, dann kommt da die Adresse in knotenfrei assoziierbarer Form hin. Von mir aus kann da ein Variablenname stehen oder eine Adresse in Hexadezimalschreibweise - aber nichts, wofür man erst klöppeln muss, um die eigentliche Bedeutung zu ergründen.

Naja.....

Nehmen wir mal das Datenblatt zu einem üblichen I2C EEProm....
Die default Adresse ist 0x50
Nur findet man diese Adresse nirgendwo im Datenblatt.

Was man aber findet, ist das Bitmuster für (0x50<<1), plus dem r/w bit.

Resultat:
Um Wire zu verstehen, muss man sich sowieso die Gehirnwindungen verbiegen.

Wenn du write(0) machst kann der Compiler nicht unterscheiden ob du Null als Integer oder einen NULL-Zeiger übergeben willst. Einfach weil write(char*) auch existiert. Lass den Cast mal weg, dann siehst du den Fehler.

Das mit dem Schieben hängt damit zusammen dass es 8 Bit und 7 Bit Adressen gibt, aber der Arduino nur mit 7 Bit arbeitet. Wenn man dann 8 Bit Adressen hat schiebt man einmal. Wird auch in der Doku erwähnt (bei "Note"):

combie:
Nehmen wir mal das Datenblatt zu einem üblichen I2C EEProm....
Nur findet man diese Adresse nirgendwo im Datenblatt.
Was man aber findet, ist das Bitmuster für (0x50<<1), plus dem r/w bit.

Dann sollten die Datenblätter besser werden. Aber vielleicht finden es die Schreiber solcher Dinge ja auch toll, aus sowas eine Art „Geheimwissen“ zu machen.

combie:
Um Wire zu verstehen, muss man sich sowieso die Gehirnwindungen verbiegen.

Das hört sich ein bisschen an wie: Das Leben ist eh hart, also bekommt heute jeder eins von mir auf die Klatsche.

Gruß

Gregor

Dann sollten die Datenblätter besser werden. Aber vielleicht finden es die Schreiber solcher Dinge ja auch toll, aus sowas eine Art „Geheimwissen" zu machen.

Nee, nee...
Wire spielt uns den Streich...
Das unterschlägt das r/w Bit und zwingt uns zum schieben.
Die Datenblätter sind schon OK, und beschreiben genau das, was uns der LogikAnalyser auch zeigt.

Wire ist ok und meistens sehr einfach zu nutzten wenn man es mal versteht. Aber bis dahin gibt es so viele Ungereimtheiten.
z.B. sollte write() eher enqueue() oder vielleicht writeToBuffer() heißen. Das schreibt die Daten nur in den Ausgangspuffer. Die werden aber erst mit endTransmission() gesendet.

Bei den Event Handler gibt es auch eine nicht dokumentierte Gemeinheit: man kann in onRequest() nur ein einziges mal write() (d.h. man muss einzelne Werte in ein Array packen)

Bei den Datenblättern kann man auch viel ignorieren. Den kann Start/Stop-Condition Kram macht die Lib auch intern. Da ist es schon gut, dass man sich nicht darum kümmern muss.

combie:
Nee, nee...
Wire spielt uns den Streich...
Das unterschlägt das r/w Bit und zwingt uns zum schieben.
Die Datenblätter sind schon OK, und beschreiben genau das, was uns der LogikAnalyser auch zeigt.

Dann ist das mit der Schieberei aber dermaßen wichtig, dass die Info dazu nicht nur in irgendeiner „Note:“ stehen (wird gerne überlesen), sondern rot umrahmt als must-have-Basiswissen kommen sollte.

Gruß

Gregor

Also, danach beurteilt, sollte man für jeden was anders rot umrahmen.
Vermutlich würden dann die ganzen roten Rahmen alles wirklich wichtige verdrängen...
8)

combie:
Also, danach beurteilt, sollte man für jeden was anders rot umrahmen.
Vermutlich würden dann die ganzen roten Rahmen alles wirklich wichtige verdrängen...

Das sehe ich anders. Immerhin ist das mit der Adresse für Leute, die sonst nicht so Computer-affin sind, ein wirklich übler Stolperstein. Selbst ich hatte damit zuerst schwere Probleme, obwohl mir Englisch echt leicht fällt.

Was da in Datenblättern gefaselt und an Timing-Diagrammen gezeigt wird ... boah ...

Gruß

Gregor

Immerhin ist das mit der Adresse für Leute, die sonst nicht so Computer-affin sind, ein wirklich übler Stolperstein.

Dem stimme ich zu!
Darum finde ich ja auch das Wire Verfahren so bescheiden!

Denn das unterscheidet sich eben um >>1 von der Wirklichkeit.

combie:
Denn das unterscheidet sich eben um >>1 von der Wirklichkeit.

Meinst Du nicht vielleicht 1>>? :stuck_out_tongue:

Schön’ Amd!

Gregor

Hmmm...

Ich meine "Wirklichkeit"!
Meine Wirklichkeit.

Nicht Realität!

(Merksatz(für mich selber): Ich darf nicht meine Wirklichkeit, mit der Realität verwechseln!)

Hey Leute,

dankeschön euch :wink: hatte erst jetzt Zeit dies zu lesen.

Also schiebt es das Byte um 1 nach Rechts, da nur 7Bit Adressen übertragen werden bei Wire und durch das schieben eine 8Bit Adresse "erzeugt wird"?

I2C.beginTransmission(B10000010>>1); wäre ja dann "B01000001".
Allerdings ist das doch schon eine 8Bit Adresse oder wie muss ich das ganze verstehen?
Auf jedenfall würde die Adresse ja Stimmen für mein Baustein PCF8574 dann wäre mein LSB nämlich das Bit zur bestimmung ob Read oder Write siehe http://i.imgur.com/cFBzmm9.png.

Und woher bekommt es in unserem Fall zu einer Startbedingung? Denn ich brauche ja ein Sprung von 0 auf 1 als Startbedingung.

Zudem hätte ich noch eine kleine Frage.
Im weiterem Verlauf des Codes gibt es ziemlich viele I²C übertragungen.
Beispiel:
case 17:
I2C.beginTransmission(B10000010>>1); //Case17 beginn,
I2C.write(1);
I2C.write(B00000011|B00001100); //Bitweise Oder = B00001111
I2C.endTransmission();

Jedesmal wird I2C.write(1); und danach I2C.write(Adresse|Adresse) geschrieben.
was sagt mir dieses "I2C.write(1) davor aus? bzw wie verhält es sich dann auf die 2. Write Zeile?

Bin leider echt nicht so das Genie was das ganze angeht, hoffe aber dass ihr mir helfen könnt :slight_smile:
Danke schon einmal!

Und woher bekommt es in unserem Fall zu einer Startbedingung? Denn ich brauche ja ein Sprung von 0 auf 1 als Startbedingung.

Denke gar nicht darüber nach. Das machst Wire intern

Und die Adresse kannst du einmal global deklarieren. Also z.B.:

const int DEVICE_ADR = 0x41;

Dann musst du dir sonst keine Gedanken darum machen

Statt Binär kannst du die Daten als Hex schreiben. Das ist einfacher lesbar.