mikrocontroller.net

Forum: Mikrocontroller und Digitale Elektronik Kleine Frage zu TWI bzw. I²C Ansteuerung


Announcement: there is an English version of this forum on EmbDev.net. Posts you create there will be displayed on Mikrocontroller.net and EmbDev.net.
Autor: int 21h (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Moin,

ich möchte mein OLED (SSD1306) mit einem Atmega über TWI ansteuern.
Das ganze natürlich mit Assembler.
Ich habe bereits die Liste mit den ganzen Befehlen für das OLED 
vorbereitet, aber ich kann aus dem Datenblatt nicht genau entnehmen, wie 
ich ein loses Datenbyte sende um das GDDRAM zu beschreiben (bzw. ein 
Segment von der jeweiligen Page).
Ich lese etwas von "Data/Command Section Bit" und "Continuation Bit".

Natürlich sagt der Name bereits alles, aber wie und in welcher 
Reihenfolge setze ich das "Data/Command Bit"?
(In dem Diagramm vom Hersteller ist das nicht ganz ersichtlich finde 
ich)

Und wozu braucht man ein "Continuation Bit", denn dafür ist doch das 
senden/unterdrücken vom Stop Signal da.

Dankö schon mal ^^

Autor: Stefanus F. (stefanus)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Falls du C kannst, würde ich Dir empfehlen, von einer C Library 
abzugucken. Das Datenblatt ist nämlich an vielen Stellen ziemlich 
unklar.

Autor: Bessa Wissa (Gast)
Datum:
Angehängte Dateien:

Bewertung
0 lesenswert
nicht lesenswert
int 21h schrieb:
> Natürlich sagt der Name bereits alles, aber wie und in welcher
> Reihenfolge setze ich das "Data/Command Bit"?
> (In dem Diagramm vom Hersteller ist das nicht ganz ersichtlich finde
> ich)

Ich kann das "nicht ersichtlich Finden" nicht nachvollziehen.

Ist im Diagramm klar dargestellt.

Autor: Bessa Wissa (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
void ssd1306_command_start (void)
{
  I2C_SetStart (SSD1306_SA);   // Slave address
  I2C_WriteByte (0x00);        // write command
}

void ssd1306_send_command (uint8_t command)
{
  ssd1306_command_start ();
  I2C_WriteByte (command);
  I2C_SetStop ();
}

void ssd1306_send_data_start (void)
{
  I2C_SetStart (SSD1306_SA);   // Slave address
  I2C_WriteByte (0x40);        // write data
}

Autor: int 21h (Gast)
Datum:
Angehängte Dateien:

Bewertung
0 lesenswert
nicht lesenswert
Ich hänge noch mal einen Ausschnitt vom Diagramm an.
Daraus entnehme ich, dass man nach der Slave Adresse immer ein "Control 
Byte" mitgibt (und davon Bit 5-0 immer Low sind).
Aber ich verstehe immer noch nicht den Zweck des Continuation Bits.
Und dem Diagramm ist zu entnehmen, dass nach jedem Databyte wider ein 
Controlbyte folgt. Könnte man sich das nicht sparen?

Autor: int 21h (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Bessa Wissa schrieb:
> void ssd1306_command_start (void)
> {
>   I2C_SetStart (SSD1306_SA);   // Slave address
>   I2C_WriteByte (0x00);        // write command
> }
>
> void ssd1306_send_command (uint8_t command)
> {
>   ssd1306_command_start ();
>   I2C_WriteByte (command);
>   I2C_SetStop ();
> }
>
> void ssd1306_send_data_start (void)
> {
>   I2C_SetStart (SSD1306_SA);   // Slave address
>   I2C_WriteByte (0x40);        // write data
> }

Bei ssd1306_command_start sowie bei ssd1306_send_data_start ist das 
"Data command selection Bit" auf Low.
Nur bei send_data setzt du das "Co" Bit auf High.
Aber macht das Sinn?

Autor: int 21h (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Edit:

int 21h schrieb:
> Bei ssd1306_command_start sowie bei ssd1306_send_data_start ist das
> "Data command selection Bit" auf Low.
> Nur bei send_data setzt du das "Co" Bit auf High.
> Aber macht das Sinn?

Sorry, das D/C Bit wird doch gesetzt, hatte mich bei der Umrechnung 
verlesen.

Autor: int 21h (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Ich habe die "ssd1306_send_data" Routine soweit fertig gestellt.
Auf meinem OLED wird aber noch nichts dargestellt.
Um mich jetzt noch einmal auf Fehlersuche zu begeben, muss noch etwas 
geklärt werden.

Mal Angenommen ich möchte jetzt ein Datenbyte an das OLED senden um 8 
Pixel vom Display weiß darzustellen.
Das mache ich mit der TWI Schnittstelle vom Atmega328p folgendermaßen:

-> START einleiten
-> TWI Datenregister mit der SLAVE_ADD+W beschreiben
-> TWI Datenregister ausgeben
-> TWI Datenregister mit dem Controlbyte beschreiben (0x40)
-> TWI Datenregister ausgeben
-> TWI Datenregister mit dem jeweiligen Byte beschreiben
-> TWI Datenregister ausgeben
-> STOP einleiten

Mir ist jetzt nicht ganz klar, wie sich die Slave Adresse darstellt.
Laut meinen Quellen über TWI besteht die Slave Adresse immer auf 7 Bit!
Das letzte Bit sagt dann aus ob das GDDRAM gelesen oder beschrieben 
werden soll.
In dem Diagramm (siehe oben) stehen aber nur 6 Bits für die Adresse.
Wofür ist das nächste Bit (SA0) da, also Bit 1?
Laut Datenblatt:
"For the SSD1306, the slave address is either “b0111100” or “b0111101” 
by changing the SA0 to LOW or HIGH (D/C pin acts as SA0)."

Autor: Bessa Wissa (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
int 21h schrieb:
> In dem Diagramm (siehe oben) stehen aber nur 6 Bits für die Adresse.

In "unserem" Fall muss die Device Adresse linksbündig stehen damit
für das R/W Bit noch Platz bleibt.

Also Device Adresse = xxxx_xxxY, Y=R/W

Autor: Brummbär (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
int 21h schrieb:
> In dem Diagramm (siehe oben) stehen aber nur 6 Bits für die Adresse.

Ohne das Datenblatt gelesen zu haben. Können durch SA0 vielleicht 
verschiedene Register/Teile des Displays angesprochen werden?

Autor: int 21h (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hier noch einmal der Komplette Quellcode falls jemand interessiert ist 
(was ich nicht glaube ^^)
https://pastebin.com/Ww91e33e


Bessa Wissa schrieb:
> int 21h schrieb:
>> In dem Diagramm (siehe oben) stehen aber nur 6 Bits für die Adresse.
>
> In "unserem" Fall muss die Device Adresse linksbündig stehen damit
> für das R/W Bit noch Platz bleibt.
>
> Also Device Adresse = xxxx_xxxY, Y=R/W

Kann ich das SA0 Bit also auf Low setzen?

Autor: Bessa Wissa (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
int 21h schrieb:
> Kann ich das SA0 Bit also auf Low setzen?

Wirst du vermutlich sogar müssen, denn diese Displays haben
normalerweise eine Device Adresse von 0x78 (linksbündig).

Autor: Bessa Wissa (Gast)
Datum:

Bewertung
1 lesenswert
nicht lesenswert
int 21h schrieb:
> falls jemand interessiert ist (was ich nicht glaube ^^)

Was ich auch nicht glaube, denn wenn man das Display wirklich
nutzbringend ansteuern will dann ist noch "ein wenig" mehr an
Assembler-Arbeit erforderlich.

Du hast auf Assembler-Ebene auch keinerlei Zeitvorteil da die
Geschwindigkeitsbegrenzung im I2C-BusTransfer zu suchen ist,
nicht im ansteuernden Code.

Autor: Joachim B. (jar)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
int 21h schrieb:
> ich möchte mein OLED (SSD1306) mit einem Atmega über TWI ansteuern.
> Das ganze natürlich mit Assembler.

warum?

Autor: Bernd S. (bernd_stein)
Datum:
Angehängte Dateien:

Bewertung
0 lesenswert
nicht lesenswert
int 21h schrieb:
> Hier noch einmal der Komplette Quellcode falls jemand interessiert ist
> (was ich nicht glaube ^^)
> https://pastebin.com/Ww91e33e
>
Hallo,

schön das sich noch jemand für AVR-Assembler interessiert.
Der I2C-Bus in AVR8ASM ist sogar auch mein ( längeres ) Thema, 
allerdings Interruptbasiered. D.h. ich polle nicht TWCR.TWINT.

Damit schlage ich mich herum => Auslesen eines Wii Nunchuk.

Beitrag "AVR8ASM TWI Interrupt"


Ich setze mal das von dir verlinkte Listing hier rein und auch als 
Anhang, damit andere sich daraus einfach Passagen kopieren, edidieren 
und wieder hier reinsetzen können :

;Program is made for the Atmega328p for connecting with the SSD1306 OLED
;Made by int 21h

.def temp1 = r16
.def temp2 = r17
.def temp3 = r18

.equ SLAVE_ADDRESS_W = 0b01111010

;******************************
;      INIT
;******************************

  clr   temp2
  clr   temp3

  ;Init Stackpointer
  ldi   temp1, HIGH(RAMEND)
  out   SPH, temp1
  ldi   temp1, LOW(RAMEND)
  out   SPL, temp1

  ldi   temp1, 0xFF
  out   DDRD, temp1
  out   DDRC, temp1 ;Don't know if needed or not

;******************************
;      MAIN
;******************************

  ldi   temp1, 0b00110011
  ;8*8 Dotmatrix
  rcall oled_send_data
  rcall oled_send_data
  rcall oled_send_data
  rcall oled_send_data
  rcall oled_send_data
  rcall oled_send_data
  rcall oled_send_data
  rcall oled_send_data

end:
  rjmp  end

;******************************
;      ROUTINEN
;******************************

oled_send_command:
  ;Not worked on this yet
  ret

oled_send_data:
  push  temp1
  rcall oled_start
  
  ;Send Slave Addres
  ldi   temp1, SLAVE_ADDRESS_W
  sts   TWDR, temp1
  ldi   temp1, (1 << TWINT)|(1 << TWEN)
  sts   TWCR, temp1
oled_send_data_0:
  lds   temp1, TWCR
  sbrs  temp1, TWINT
  rjmp  oled_send_data_0

  ;Send Control Byte
  ldi   temp1, 0x40
  sts   TWDR, temp1
  ldi   temp1, (1 << TWINT)|(1 << TWEN)
  sts   TWCR, temp1
oled_send_data_1:
  lds   temp1, TWCR
  sbrs  temp1, TWINT
  rjmp  oled_send_data_1

  ;Send Byte
  pop   temp1
  push  temp1
  sts   TWDR, temp1
  ldi   temp1, (1 << TWINT)|(1 << TWEN)
  sts   TWCR, temp1
oled_send_data_2:
  lds   temp1, TWCR
  sbrs  temp1, TWINT
  rjmp  oled_send_data_2

  rcall oled_stop
  pop   temp1
  ret

oled_start:
  push  temp1
  ldi   temp1, (1 << TWINT)|(1 << TWSTA)|(1 << TWEN)
  sts   TWCR, temp1
oled_start_0:
  lds   temp1, TWCR
  sbrs  temp1, TWINT
  rjmp  oled_start_0
  ;Check Status Code
  lds   temp1, TWSR
  andi  temp1, 0x08
  sbrs  temp1, 3
  rcall oled_error
  pop   temp1
  ret

oled_stop:
  push  temp1
  ldi   temp1, (1 << TWINT)|(1 << TWSTO)|(1 << TWEN)
  sts   TWCR, temp1
oled_stop_0:
  lds   temp1, TWCR
  sbrs  temp1, TWINT
  rjmp  oled_start_0
  pop   temp1
  ret

;If an error occurs, toggle the LED
oled_error:
  push  temp1
  ldi   temp1, 0x01
  out   PORTD, temp1
  pop   temp1
  ret




Bernd_Stein

Autor: int 21h (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Bessa Wissa schrieb:
> int 21h schrieb:
>> falls jemand interessiert ist (was ich nicht glaube ^^)
>
> Was ich auch nicht glaube, denn wenn man das Display wirklich
> nutzbringend ansteuern will dann ist noch "ein wenig" mehr an
> Assembler-Arbeit erforderlich.

Ja das ist mir klar, danke.
Aber erst einmal muss ich diese eine Routine zum laufen bekommen.
Der Rest klärt sich dann von selbst.
Mein Ziel wird es später sein, mit diesen Mitteln ein kleines Spiel zu 
entwickeln.
Sei es so geringfügig wie Snake oder ein Klicker Simulator.

Autor: int 21h (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Bernd S. schrieb:
> Ich setze mal das von dir verlinkte Listing hier rein und auch als
> Anhang, damit andere sich daraus einfach Passagen kopieren, edidieren
> und wieder hier reinsetzen können :

Welchen Zweck hat das ganze den??

Autor: Stefanus F. (stefanus)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Kann es sein, dass du das Display noch nicht initialisiert hast? Ich 
habe dazu noch keinen Programmcode gesehen. Diese Displays brauchen eine 
umfangreiche Initialisierungssequenz.

Autor: Bessa Wissa (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
int 21h schrieb:
> Welchen Zweck hat das ganze den??

Damit er auch was mit labern kann.

Autor: int 21h (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Stefanus F. schrieb:
> Kann es sein, dass du das Display noch nicht initialisiert hast? Ich
> habe dazu noch keinen Programmcode gesehen. Diese Displays brauchen eine
> umfangreiche Initialisierungssequenz.

Ich habe das Display nicht initialisiert, da ich es bis her nicht für 
nötig gehalten habe. Ich wollte mich erstmal auf die Voreinstellungen 
beschränken (Page-Addressing Mode, x=0, y=0).
Aber vielleicht liegt ja wirklich hier der Fehler.
Ich werde mich noch mal von neuem einlesen.

Bessa Wissa schrieb:
> int 21h schrieb:
>> Welchen Zweck hat das ganze den??
>
> Damit er auch was mit labern kann.

XD

Autor: Bernd S. (bernd_stein)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
int 21h schrieb:
> Bernd S. schrieb:
>> Ich setze mal das von dir verlinkte Listing hier rein und auch als
>> Anhang, damit andere sich daraus einfach Passagen kopieren, edidieren
>> und wieder hier reinsetzen können :
>
> Welchen Zweck hat das ganze den??
>
Naja, du scheinst es ja ( AVR8ASM ) noch lernen zu wollen und Anderen 
machst du es dann etwas einfacher dir ihre Version kund zu tun.


Bernd_Stein

Autor: Stefanus F. (stefanus)
Datum:

Bewertung
1 lesenswert
nicht lesenswert
int 21h schrieb:
> Ich habe das Display nicht initialisiert, da ich es bis her nicht für
> nötig gehalten habe.

Plonk.

> Aber vielleicht liegt ja wirklich hier der Fehler.

Nicht nur vielleicht, sondern 100% sicher. Es sind ungefähr 26 Bytes zur 
Initialisierung nötig. Du darfst hiervon abgucken: 
http://stefanfrings.de/esp8266/WIFI-Kit-8-OLED.zip Die 
Initialisierungssequenz beginnt in oled.cpp Zeile 257.

: Bearbeitet durch User
Autor: int 21h (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Stefanus F. schrieb:
> Nicht nur vielleicht, sondern 100% sicher. Es sind ungefähr 26 Bytes zur
> Initialisierung nötig.

Ich habe mir die von dir mitgegebene Initialisierungs Routine mal 
angeschaut.
Die meisten von denen bzw. fast alle wären bei mir gar nicht nötig, da 
diese bereits beim Reset gesetzt werden.

Laut Datenblatt kann man 0x12 nicht als Parameter auswählen:
> i2c_send(0xDA); // com pins hardware configuration
> i2c_send(0x12);

Wieso versetzt du den uC in den sleep mode:
> i2c_send(0xAE); // display off
Wird übrigens von alleine durch den Reset gesetzt.

Also ist die ganze Initialisierungs Routine sozusagen überflüssig... 
schade :/

Autor: Stefanus F. (stefanus)
Datum:
Angehängte Dateien:

Bewertung
0 lesenswert
nicht lesenswert
> Die meisten von denen bzw. fast alle wären bei mir gar nicht
> nötig, da diese bereits beim Reset gesetzt werden.

Kann sein. Ich habe es gemäss dem angehängten Datenblatt programmiert 
und dann so gelassen, da es funktioniert. Auf ein paar Bytes mehr oder 
weniger kommt es am Ende nicht an.

> Laut Datenblatt kann man 0x12 nicht als Parameter auswählen:
>> i2c_send(0xDA); // com pins hardware configuration
>> i2c_send(0x12);

In dem angehängten Datenblatt ist der Wert 0x12 vorgegeben und so 
funktioniert das Display auch.

> Wieso versetzt du den uC in den sleep mode

Weil das im Datenblatt so empfohlen wird.

> Also ist die ganze Initialisierungs Routine sozusagen überflüssig...

Das bezweifle ich. Der Chip ist für viele unterschiedliche Displays 
geeignet und hat mehrere Optionen zur Stromversorgung. Er muss dazu 
passend konfiguriert werden.

Ich kann Dir nur empfehlen, mit einem bewährten Code zu beginnen und den 
dann ggf. auf das Nötigste zu reduzieren. Wunder Dich dann aber nicht, 
wenn es beim nächsten Display nicht mehr funktioniert. Die Chinesen 
bauen oft gleichnamige Chips, die sich nicht exakt gleich verhalten.

Wir hatten diese Diskussion auch schon öfters bezüglich HD44780 
kompatible Displays. Fast immer wenn ein Programm nicht funktionierte, 
lag es daran, dass der Programmierer sich nicht an die Vorgaben des 
Datenblattes gehalten hat - in dem Glauben, er könne etwas weglassen 
oder schneller machen. So etwas funktioniert dann oft mit einem Display, 
aber nicht mit jedem vermeintlich baugleichen.

: Bearbeitet durch User
Autor: int 21h (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Stefanus F. schrieb:
> Du darfst hiervon abgucken:
> http://stefanfrings.de/esp8266/WIFI-Kit-8-OLED.zip Die
> Initialisierungssequenz beginnt in oled.cpp Zeile 257.

Manche Routinen sind mir in dem Code noch nicht ganz klar.
1. Wieso taucht immer wieder "OLED_I2C_DELAY;" auf?
2. Bei der Funktion "bool OLED::i2c_send(uint8_t byte)" verarbeitest du 
jedes
   Bit aus der Variable byte einzeln. Bei mir erledigt es das 
integrierte TWI
   Module vom uC selbstständig.
   Das macht es sehr schwer, deinen Code mit meinem Assembler zu 
vergleichen,
   da du eine ganz andere Vorgehensweisen nutzt.
3. ich würde mir gerne die beiden Funktionen digitalWrite/Read genauer
   anschauen wollen, wäre das möglich?

Sonst ist alles genauso wie bei mir.
Deine Initialisierungsschritte sind die selben wie bei mir.

Autor: int 21h (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Noch eine Frage, hinter meinem OLED steht die Slave Adresse "0x78", 
müsste ich diese bei der Übertragung dann auch schicken oder die hälfte 
vom Wert?
Also (0x78 << 1) oder (0x3C << 1)?

Autor: Joachim B. (jar)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
int 21h schrieb:
> Noch eine Frage, hinter meinem OLED steht die Slave Adresse "0x78",
> müsste ich diese bei der Übertragung dann auch schicken oder die hälfte
> vom Wert?

kommt halt auf die Interpretation an, ich arbeite seit der vor Arduino 
Zeit mit 0x78 weil das Bit 0 read oder write meint.

Es ist ja egal ob man 0x78 | 0x01 macht oder (0x3C<<1) | 0x01 macht

Beides ist machbar

Autor: Stefanus F. (stefanus)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
int 21h schrieb:
> 1. Wieso taucht immer wieder "OLED_I2C_DELAY;" auf?

Damit die Kommunikation nicht zu schnell wird. Das Display ist bis 
400kHz Taktrate spezifiziert. Darüber hinaus muss man aber auch gewisse 
Abstände zwischen den Signalwechseln an SCL versus SDL einhalten.

> 2. Bei der Funktion "bool OLED::i2c_send(uint8_t byte)" verarbeitest du
> jedes Bit aus der Variable byte einzeln.

Ja, das nennt man Bit-Banging. Diese Library nutzt nicht das TWI 
Interface, sondern normale I/O Pins.

> Bei mir erledigt es das integrierte TWI

Wenn möglich ist das sicher die bessere Wahl.

> Das macht es sehr schwer, deinen Code mit meinem Assembler zu
> vergleichen, da du eine ganz andere Vorgehensweisen nutzt.

Es sind doch nur drei Funktionen:

OLED::i2c_start() sendet eine START Bedingung
OLED::i2c_stop() sendet eine STOP Bedingung
OLED::i2c_send(uint8_t byte) sendet ein Byte und liefert die Antwort 
(ACK oder NACK) zurück.

und Empfangen wird gar nicht.

Ob du das wie ich per Bitbanging oder durch ein TWI Interface 
austauschst, spielt doch für den Rest des Quelltextes keine Rolle.

> 3. ich würde mir gerne die beiden Funktionen digitalWrite/Read genauer
>    anschauen wollen, wäre das möglich?

Dann lade Dir die Arduino IDE herunter und gucke in die Quelltexte rein. 
Sicher kannst du deren Quelltext auch irgendwo auf Github finden. Doch 
da gibt es nichts spannendes zu sehen. digitalWrite setzt einen 
einzelnen I/O Pin auf High oder Low und digitalRead liest den Zustand 
eines I/O Pins ein.

> Sonst ist alles genauso wie bei mir.

Sicher? Noch vor wenigen tagen schriebst du:
> Ich habe das Display nicht initialisiert, da ich es bis her nicht für
> nötig gehalten habe.
> Also ist die ganze Initialisierungs Routine sozusagen überflüssig...

Die Adresse wird in den oberen 7 Bit übertragen. Das niederwertigste Bit 
signalisiert, ob du lesen oder schreiben willst. Siehe 
https://www.nxp.com/docs/en/user-guide/UM10204.pdf

0x78 ist keine gültige I²C Adresse, weil das nicht in 7 Bit passt. Aber 
wenn du die richtige Adresse 0x3C um ein Bit nach links schiebst, um 
Platz für das R/W Bit zu machen, und dieses R/W Bit auf 0 setzt, dann 
kommt dabei 0x78 heraus. Das ist das Byte, dass du zur Adressierung 
senden musst.

Besorge Dir mal einen Logic Analyzer, damit kannst du deine 
Kommunikation überprüfen. Die Dinger kosten nur ca 10 Euro!

: Bearbeitet durch User
Autor: Joachim B. (jar)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Stefanus F. schrieb:
> 0x78 ist keine gültige I²C Adresse, weil das nicht in 7 Bit passt. Aber
> wenn du die richtige Adresse 0x3C

was ist schon richtig, es ist eine Frage der Interpretation.

Die ersten LIBs vor Arduino und Datenblätter wiesen 0x78 aus, das passt 
in 7 Bit rechtsshift!
Das read/write Bit gehört als 8tes Bit ja wohl dazu, also falsch ist es 
nicht.

: Bearbeitet durch User
Autor: Stefanus F. (stefanus)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Joachim B. schrieb:
> Stefanus F. schrieb:
>> 0x78 ist keine gültige I²C Adresse, weil das nicht in 7 Bit passt. Aber
>> wenn du die richtige Adresse 0x3C
>
> was ist schon richtig, es ist eine Frage der Interpretation.
>
> Die ersten LIBs vor Arduino und Datenblätter wiesen 0x78 aus, das passt
> in 7 Bit rechtsshift!
> Das read/write Bit gehört als 8tes Bit ja wohl dazu, also falsch ist es
> nicht.

Oh, 0x78 passt ja doch in 7 Bit. Facepalm.

Jedenfalls sollte man da klar unterscheiden. I²C Adressen sind immer 
7-bit (oder 10-bit) lang. Das achte Bit gehört nicht zur Adresse. Wenn 
das so wäre, dann müsste in der Spezifikation etwa das stehen:

"The device address is reserved for write operation. The following 
address (+1) is reserved for read operation."

Aber so steht das dort nicht. Sondern:

"7-bit slave address" (Absatz 3.1.0)

Absatz 3.1.10 zeigt detailliert, wie die 7-bit Adresse und das R/W Bit 
übertragen werden. Dort ist ganz klar die Adresse von R/W-bit getrennt 
gezeichnet. Und dann gibt es ja noch die 10-bit Adressierung, auch dort 
ist die Adresse klar von anderen Bits getrennt dargestellt.

Wer jetzt irgendwo von einer 8-bit Adresse oder einen 8-bit Wert 
schreibt, der hat es nicht verstanden und stiftet unnötige Verwirrung. 
Ich weiß dass sogar einige Datenblätter es nicht richtig darstellen oder 
zumindest unklar.

Wenn ich eine Funktion write_i2c(addr,buffer,len) oder 
read_i2c(addr,buffer,len) oder so ähnlich anbiete, dann muss klar sein, 
dass addr entweder eine 7-bit oder 10-bit Adresse ist. Irgendwelche 
protokollspezifischen Shift Operationen sind Aufgabe der 
Schnittstellen-Implementierung, nicht des Aufrufers. Willst du etwa bei 
der 10-bit Adressierung das Shiften auch dem Aufrufer überlassen? Das 
wäre Wahnsinn!

: Bearbeitet durch User
Autor: int 21h (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Danke für deine Hilfe Stefanus, jetzt ist mir alles klar geworden.
Ich denke, jetzt sollten meine weiteren Fragen aufkommen.

P.s. Ich hatte die Bitrate nicht eingestellt, vielleicht liegt das 
Problem unter anderem daran.

Autor: int 21h (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Stefanus F. schrieb:
> Besorge Dir mal einen Logic Analyzer, damit kannst du deine
> Kommunikation überprüfen. Die Dinger kosten nur ca 10 Euro!

Sehr gute Sache das Teil, ich habe es direkt in meinen Warenkorb gelegt.

Autor: Joachim B. (jar)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Stefanus F. schrieb:
> Wer jetzt irgendwo von einer 8-bit Adresse oder einen 8-bit Wert
> schreibt, der hat es nicht verstanden

ich frage mich gerade WER was nicht verstanden hat, man muss auf jeden 
FALL 8 Bit senden, das die Adresse hier 7-bittig ist ist doch 
schnurzpiepegal ohne 8tes Bit R/W schickt man NICHTS, aber dreh dich nur 
weiter, DU hast IMMER Recht und alle anderen sind doof.

Autor: Stefanus F. (stefanus)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Joachim B. schrieb:
> Stefanus F. schrieb:
>> Wer jetzt irgendwo von einer 8-bit Adresse oder einen 8-bit Wert
>> schreibt, der hat es nicht verstanden
>
> ich frage mich gerade WER was nicht verstanden hat, man muss auf jeden
> FALL 8 Bit senden, das die Adresse hier 7-bittig ist ist doch
> schnurzpiepegal ohne 8tes Bit R/W schickt man NICHTS, aber dreh dich nur
> weiter, DU hast IMMER Recht und alle anderen sind doof.

Das kommt dabei heraus, wenn man einzelne Sätze aus dem Zusammenhang 
reißt ohne den Rest zu beachten. Ich habe klar geschrieben, dass

a) die Adresse 7-bit oder 10-bit groß ist, und
b) dass die 7-bit Adresse mit dem R/W bit zusammen als 8-bit gesendet 
wird.

Es gibt bei I²C keine 8-bit Adresse

: Bearbeitet durch User
Autor: Joachim B. (jar)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Stefanus F. schrieb:
> Es gibt bei I²C keine 8-bit Adresse

klar mit R/W, steht in Datenblätter die ich bis jetzt gelesen hatte mit 
R/W

z.B. beim PCF8574(a), DS3231, DS1307
https://datasheets.maximintegrated.com/en/ds/DS3231.pdf
https://www.sparkfun.com/datasheets/Components/DS1307.pdf

http://www.ti.com/lit/ds/symlink/pcf8574.pdf
#Seite12

lesen 0x79
schreiben 0x78

immer 8-bit
http://homepage.hispeed.ch/peterfleury/doxygen/avr-gcc-libraries/group__pfleury__ic2master.html

Es gab ein Leben vor Arduino

: Bearbeitet durch User
Autor: Stefanus F. (stefanus)
Datum:

Bewertung
1 lesenswert
nicht lesenswert
Habe ich ja geschrieben, einige Datenblatter machen das meiner Meinung 
nach falsch. Philips (jetzt NXP) hat die Adressen spezifiziert, meine 
Meinung nach ist da kein Raum für Abweichungen von 7 und 10 bits.

Autor: Klaus (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Stefanus F. schrieb:
> Habe ich ja geschrieben, einige Datenblatter machen das meiner Meinung
> nach falsch. Philips (jetzt NXP) hat die Adressen spezifiziert, meine
> Meinung nach ist da kein Raum für Abweichungen von 7 und 10 bits.

Richtig, für I2C gibt es eine aufgeschriebene Dokumentation. Und dort 
kommen nur 7 Bit oder 10 Bit Adressen vor. Das Datenblatt eines Chips 
ist nur Sekundärliteratur.

Daß in einem Byte 2 verschiedene Informationen übertragen werden (hier 
Adresse und Richtung der folgenden Übertragung) scheint für manche zu 
kompliziert zu sein. Etwas komplexere Protokolle, bei denen noch mehr 
als zwei unabhängige Informationen in ein Byte kodiert werden, würden 
die nie verstehen.

MfG Klaus

Autor: m.n. (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Stefanus F. schrieb:
> Philips (jetzt NXP) hat die Adressen spezifiziert

So ist es und Philips/NXP darf das.
Und sieht man in ein Datenblatt von NXP beispielsweise für den PCF8583 
https://www.nxp.com/documents/data_sheet/PCF8583.pdf, dann steht dort 
auf der 1. Seite:
"Slave addresses: A1h or A3h for reading, A0 or A2 for writing"
Für mich sind das eindeutig 8 Bit Werte ;-)

Man tut sich im übrigen keinen Gefallen, IIC-Adressen mit 7 Bit 
rechtsbündig anzugeben. Denn sobald man sich die Signale auf dem Bus 
ansieht, passt das nicht mehr zusammen.

Autor: Klaus (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Aus der I2C Spec:

> This address is 7 bits long followed by an eighth bit
> which is a data direction bit (R/W)

m.n. schrieb:
> Man tut sich im übrigen keinen Gefallen, IIC-Adressen mit 7 Bit
> rechtsbündig anzugeben. Denn sobald man sich die Signale auf dem Bus
> ansieht, passt das nicht mehr zusammen.

Das stimmt so nicht, mein i2c Dekoder zeigt sie mir als 7-Bit Wert an 
und getrennt davon das R/W Bit. Das krieg ich aber auch im Kopf leicht 
hin.

Nur weil manche nicht in der Lage sind etwas abstrakter zu denken, 
sollte man das eigene Niveau nicht daran anpassen. Es gibt noch 
wesentlich komplexere Kodierungen. Ein Fall ist z.B. die 10 Bit I2C 
Adresse oder noch etwas komplexer Base64.

MfG Klaus

Autor: M. K. (sylaina)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
m.n. schrieb:
> Man tut sich im übrigen keinen Gefallen, IIC-Adressen mit 7 Bit
> rechtsbündig anzugeben. Denn sobald man sich die Signale auf dem Bus
> ansieht, passt das nicht mehr zusammen.

Tja, das ist bei den hier beschriebenen Displays aber die Regel und wenn 
man sich in die Materie einarbeitet wird auch der Vorteil dabei klar ;)

Autor: Ralf D. (doeblitz)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
m.n. schrieb:
[...]
> Man tut sich im übrigen keinen Gefallen, IIC-Adressen mit 7 Bit
> rechtsbündig anzugeben. Denn sobald man sich die Signale auf dem Bus
> ansieht, passt das nicht mehr zusammen.

Einen Tod muß man sterben. Aber ich halte es auch für sinnvoller, die 
I2C-Adressen als 7bit- oder 10bit-Wert anzugeben, also natürlich 
rechtsbündig.

Dann kannst du in der Lib entscheiden wie die Adresse zusammen mit dem 
R/W-Bit auf den Bus gegeben werden muss. Das ist bei 10bit-Adressen dann 
schon nicht mehr so trivial im LA-Trace zu erkennen (wohl dem, der einen 
guten Protokoll-Dekoder hat).

In der Applikation musst du dich dann nicht um die Interna des 
Protokolls (wie wird eine Adresse auf dem Bus dargestellt) kümmern. Im 
Allgemeinen wird eine solche Abstraktion als positiv und erstrebenswert 
angesehen. YMMV.

Autor: Joachim B. (jar)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Klaus schrieb:
> Das stimmt so nicht, mein i2c Dekoder zeigt sie mir als 7-Bit Wert an
> und getrennt davon das R/W Bit.

und meiner (Software) I2C-Scanner zeigt beides an, so what?

Stefanus F. schrieb:
> .... einige Datenblatter machen das meiner Meinung
> nach falsch.

also sorry wenn ich den Datenblätter mehr vertraue als dir!
Deine Meinung lasse ich dir gerne, die darf ruhig anders sein.

m.n. schrieb:
> Und sieht man in ein Datenblatt von NXP beispielsweise für den PCF8583
> https://www.nxp.com/documents/data_sheet/PCF8583.pdf, dann steht dort
> auf der 1. Seite:
> "Slave addresses: A1h or A3h for reading, A0 or A2 for writing"
> Für mich sind das eindeutig 8 Bit Werte ;-)

ganz meine Meinung!

> Man tut sich im übrigen keinen Gefallen, IIC-Adressen mit 7 Bit
> rechtsbündig anzugeben. Denn sobald man sich die Signale auf dem Bus
> ansieht, passt das nicht mehr zusammen.

eben

im Übrigen ist das egal, man muss sich nur auf eine Regelung einigen, 
das kann je nach Quelle mal schief gehen, ist aber kein wirkliches 
Problem und behebbar, dann shifte ich halt, mal links, mal rechts nach 
Bedarf.
Lohnt nicht darüber zu streiten.......

: Bearbeitet durch User
Autor: m.n. (Gast)
Datum:

Bewertung
-1 lesenswert
nicht lesenswert
Klaus schrieb:
> Das stimmt so nicht, mein i2c Dekoder zeigt sie mir als 7-Bit Wert an
> und getrennt davon das R/W Bit.

Wie Du siehst, taugt das Ding nichts! ;-)

Der IIC-Bus wurde Anfang der 80er von Philips entwickelt. Folglich hat 
man auch die Vorgaben des Urhebers Übernommen, zum Beispiel für den 
PCF8385 die Adressen A0 und A2 als Basisadressen zu verwenden.
Dass die heutige Jugend das nicht mehr weiß, ist nicht mein Problem.

Autor: Stefanus F. (stefanus)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Klaus schrieb:
> Daß in einem Byte 2 verschiedene Informationen übertragen werden (hier
> Adresse und Richtung der folgenden Übertragung) scheint für manche zu
> kompliziert zu sein.

Genau deswegen würde ich Schnittstellentreiber ("Libraries") immer so 
auslegen, dass jeder Aufrufparameter genau eine Funktion hat. Also eben 
nicht Adresse mit R/W Bit kombinieren. Spätestens wenn man das mal auf 
10-bit erweitert wird das ganz besonders wichtig, denn da steckt das R/W 
bit mitten drin.

: Bearbeitet durch User
Autor: Stefanus F. (stefanus)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
m.n. schrieb:
> Und sieht man in ein Datenblatt von NXP beispielsweise für den PCF8583
> https://www.nxp.com/documents/data_sheet/PCF8583.pdf, dann steht dort
> auf der 1. Seite:
> "Slave addresses: A1h or A3h for reading, A0 or A2 for writing"
> Für mich sind das eindeutig 8 Bit Werte ;-)

Tolle Wurst, die legen es wohl drauf an, ihre Kunden zu verwirren.

> Man tut sich im übrigen keinen Gefallen, IIC-Adressen mit 7 Bit
> rechtsbündig anzugeben. Denn sobald man sich die Signale auf dem Bus
> ansieht, passt das nicht mehr zusammen.

Die beiden mir bekannten Logic Analyzer Programme können die Adresse 
wahlweise in beiden Formaten anzeigen.

: Bearbeitet durch User
Autor: Stefanus F. (stefanus)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Joachim B. schrieb:
> Deine Meinung lasse ich dir gerne, die darf ruhig anders sein.

Dito, wir müssen uns nicht auf einen gemeinsamen Konsens einigen - 
jedenfalls nicht für diese Pillepalle.

Autor: int 21h (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Ich wollte heute mal wieder an dem Programm für die TWI Kommunikation 
weiterarbeiten.
Als nach vielen Versuchen immer noch nichts am Display zu sehen war, 
beschloss ich spaßeshalber noch einmal das OLED Arduino Sketch von 
Adafruit drauf zu spielen.
Auf dem Display war allerdings nichts zu sehen.
Vor wenigen Tagen lief das Programm noch und heute nicht mehr.
Die Schaltung ist die selbe geblieben, unverändert!
Dann habe ich test weise ein Programm zum auslesen der TWI Adresse 
geladen, dass auch funktioniert hat (0x3C kam raus).
Ist das GDDRAM vom OLED defekt?
Geht das wirklich so leicht?

Autor: Dieter F. (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Klaus schrieb:
> mein i2c Dekoder zeigt sie mir als 7-Bit Wert an
> und getrennt davon das R/W Bit

Den kennen hier sicher alle :-)

Joachim B. schrieb:
>> "Slave addresses: A1h or A3h for reading, A0 or A2 for writing"
>> Für mich sind das eindeutig 8 Bit Werte ;-)
>
> ganz meine Meinung!

Sehe ich auch so - man achte auf das letzte Bit.

Autor: Dieter F. (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Stefanus F. schrieb:
> Die beiden mir bekannten Logic Analyzer Programme können die Adresse
> wahlweise in beiden Formaten anzeigen.

Kannst Du die bitte benennen? Die hätte ich auch gerne.

Autor: Stefanus F. (stefanus)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Dieter F. schrieb:
> Stefanus F. schrieb:
>> Die beiden mir bekannten Logic Analyzer Programme können die Adresse
>> wahlweise in beiden Formaten anzeigen.
>
> Kannst Du die bitte benennen? Die hätte ich auch gerne.

Sigrok/PulseView und Salae Logic.

: Bearbeitet durch User
Autor: Dieter F. (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Stefanus F. schrieb:
> und Salae Logic.

Saleae nutze ich - da ist es mir noch nicht aufgefallen. Ich schaue mal.

Autor: Stefanus F. (stefanus)
Datum:
Angehängte Dateien:

Bewertung
0 lesenswert
nicht lesenswert
Ganz rechts bei I2C Analyzer musst du auf das Zahnrad klicken, dann auf 
Edit Settings,dann erscheint der gezeigte Dialog.

7-bit Address bits only
8-bit read/write bit included

Und dann gibt es noch eine Option, die ich für Quatsch halte:
8-bit read/write bit set as 0

Autor: Dieter F. (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Stefanus F. schrieb:
> Ganz rechts bei I2C Analyzer musst du auf das Zahnrad klicken, dann auf
> Edit Settings,dann erscheint der gezeigte Dialog.

Danke - werde ich bei Gelegenheit ausprobieren. War mir echt unbekannt. 
Vielen Dank.

Autor: int 21h (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Das habe mir jetzt alle Initialisierungs Commands herausgesucht, die 
unbedingt nötig sind um etwas darzustellen.
Dabei stieß ich auf den Command "Charge Pump Regulator", der anscheinend 
unbedingt aktiviert werden muss.
(Der Grund weshalb ich diesen Befehl erst jetzt im Datenblatt entdeckt 
habe, ist weil der ganz unten im Datenblatt steht und auch nicht in der 
Command Table eingetragen ist!)
Kann mir jemand bitte erklären, was dieser genau macht, da ich nicht 
viel von Elektronik verstehe?

Autor: Thomas W. (diddl)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
int 21h schrieb:
> Kann mir jemand bitte erklären, was dieser genau macht, da ich nicht
> viel von Elektronik verstehe?

Klingt für mich nach Ladungspumpe.

Das verwendet man zb. um eine höhere Betriebsspannung zu erzeugen.

Autor: Stefanus F. (stefanus)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Warum kopierst du nicht einfach die von mir empfohlene 
Initialisierungssequenz aus dem Datenblatt des Displays (nicht dem 
Datenblatt des COB)? Meinst du die schreiben das zum Spaß dort hinein?

Antwort schreiben

Die Angabe einer E-Mail-Adresse ist freiwillig. Wenn Sie automatisch per E-Mail über Antworten auf Ihren Beitrag informiert werden möchten, melden Sie sich bitte an.

Wichtige Regeln - erst lesen, dann posten!

  • Groß- und Kleinschreibung verwenden
  • Längeren Sourcecode nicht im Text einfügen, sondern als Dateianhang

Formatierung (mehr Informationen...)

  • [c]C-Code[/c]
  • [avrasm]AVR-Assembler-Code[/avrasm]
  • [code]Code in anderen Sprachen, ASCII-Zeichnungen[/code]
  • [math]Formel in LaTeX-Syntax[/math]
  • [[Titel]] - Link zu Artikel
  • Verweis auf anderen Beitrag einfügen: Rechtsklick auf Beitragstitel,
    "Adresse kopieren", und in den Text einfügen




Bild automatisch verkleinern, falls nötig
Bitte das JPG-Format nur für Fotos und Scans verwenden!
Zeichnungen und Screenshots im PNG- oder
GIF-Format hochladen. Siehe Bildformate.

Mit dem Abschicken bestätigst du, die Nutzungsbedingungen anzuerkennen.