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


von int 21h (Gast)


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

von Stefan F. (Gast)


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.

von Bessa Wissa (Gast)


Angehängte Dateien:

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.

von Bessa Wissa (Gast)


Lesenswert?

1
void ssd1306_command_start (void)
2
{
3
  I2C_SetStart (SSD1306_SA);   // Slave address
4
  I2C_WriteByte (0x00);        // write command
5
}
6
7
void ssd1306_send_command (uint8_t command)
8
{
9
  ssd1306_command_start ();
10
  I2C_WriteByte (command);
11
  I2C_SetStop ();
12
}
13
14
void ssd1306_send_data_start (void)
15
{
16
  I2C_SetStart (SSD1306_SA);   // Slave address
17
  I2C_WriteByte (0x40);        // write data
18
}

von int 21h (Gast)


Angehängte Dateien:

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?

von int 21h (Gast)


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?

von int 21h (Gast)


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.

von int 21h (Gast)


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

von Bessa Wissa (Gast)


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

von Brummbär (Gast)


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?

von int 21h (Gast)


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?

von Bessa Wissa (Gast)


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

von Bessa Wissa (Gast)


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.

von Joachim B. (jar)


Lesenswert?

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

warum?

von Bernd S. (Firma: Anscheinend Corner-Cases ;-)) (bernd_stein)


Angehängte Dateien:

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 :
1
;Program is made for the Atmega328p for connecting with the SSD1306 OLED
2
;Made by int 21h
3
4
.def temp1 = r16
5
.def temp2 = r17
6
.def temp3 = r18
7
8
.equ SLAVE_ADDRESS_W = 0b01111010
9
10
;******************************
11
;      INIT
12
;******************************
13
14
  clr   temp2
15
  clr   temp3
16
17
  ;Init Stackpointer
18
  ldi   temp1, HIGH(RAMEND)
19
  out   SPH, temp1
20
  ldi   temp1, LOW(RAMEND)
21
  out   SPL, temp1
22
23
  ldi   temp1, 0xFF
24
  out   DDRD, temp1
25
  out   DDRC, temp1 ;Don't know if needed or not
26
27
;******************************
28
;      MAIN
29
;******************************
30
31
  ldi   temp1, 0b00110011
32
  ;8*8 Dotmatrix
33
  rcall oled_send_data
34
  rcall oled_send_data
35
  rcall oled_send_data
36
  rcall oled_send_data
37
  rcall oled_send_data
38
  rcall oled_send_data
39
  rcall oled_send_data
40
  rcall oled_send_data
41
42
end:
43
  rjmp  end
44
45
;******************************
46
;      ROUTINEN
47
;******************************
48
49
oled_send_command:
50
  ;Not worked on this yet
51
  ret
52
53
oled_send_data:
54
  push  temp1
55
  rcall oled_start
56
  
57
  ;Send Slave Addres
58
  ldi   temp1, SLAVE_ADDRESS_W
59
  sts   TWDR, temp1
60
  ldi   temp1, (1 << TWINT)|(1 << TWEN)
61
  sts   TWCR, temp1
62
oled_send_data_0:
63
  lds   temp1, TWCR
64
  sbrs  temp1, TWINT
65
  rjmp  oled_send_data_0
66
67
  ;Send Control Byte
68
  ldi   temp1, 0x40
69
  sts   TWDR, temp1
70
  ldi   temp1, (1 << TWINT)|(1 << TWEN)
71
  sts   TWCR, temp1
72
oled_send_data_1:
73
  lds   temp1, TWCR
74
  sbrs  temp1, TWINT
75
  rjmp  oled_send_data_1
76
77
  ;Send Byte
78
  pop   temp1
79
  push  temp1
80
  sts   TWDR, temp1
81
  ldi   temp1, (1 << TWINT)|(1 << TWEN)
82
  sts   TWCR, temp1
83
oled_send_data_2:
84
  lds   temp1, TWCR
85
  sbrs  temp1, TWINT
86
  rjmp  oled_send_data_2
87
88
  rcall oled_stop
89
  pop   temp1
90
  ret
91
92
oled_start:
93
  push  temp1
94
  ldi   temp1, (1 << TWINT)|(1 << TWSTA)|(1 << TWEN)
95
  sts   TWCR, temp1
96
oled_start_0:
97
  lds   temp1, TWCR
98
  sbrs  temp1, TWINT
99
  rjmp  oled_start_0
100
  ;Check Status Code
101
  lds   temp1, TWSR
102
  andi  temp1, 0x08
103
  sbrs  temp1, 3
104
  rcall oled_error
105
  pop   temp1
106
  ret
107
108
oled_stop:
109
  push  temp1
110
  ldi   temp1, (1 << TWINT)|(1 << TWSTO)|(1 << TWEN)
111
  sts   TWCR, temp1
112
oled_stop_0:
113
  lds   temp1, TWCR
114
  sbrs  temp1, TWINT
115
  rjmp  oled_start_0
116
  pop   temp1
117
  ret
118
119
;If an error occurs, toggle the LED
120
oled_error:
121
  push  temp1
122
  ldi   temp1, 0x01
123
  out   PORTD, temp1
124
  pop   temp1
125
  ret



Bernd_Stein

von int 21h (Gast)


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.

von int 21h (Gast)


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

von Stefan F. (Gast)


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.

von Bessa Wissa (Gast)


Lesenswert?

int 21h schrieb:
> Welchen Zweck hat das ganze den??

Damit er auch was mit labern kann.

von int 21h (Gast)


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

von Bernd S. (Firma: Anscheinend Corner-Cases ;-)) (bernd_stein)


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

von Stefan F. (Gast)


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.

von int 21h (Gast)


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 :/

von Stefan F. (Gast)



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.

von int 21h (Gast)


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.

von int 21h (Gast)


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

von Joachim B. (jar)


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

von Stefan F. (Gast)


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!

von Joachim B. (jar)


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
von Stefan F. (Gast)


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!

von int 21h (Gast)


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.

von int 21h (Gast)


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.

von Joachim B. (jar)


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.

von Stefan F. (Gast)


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

von Joachim B. (jar)


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
von Stefan F. (Gast)


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.

von Klaus (Gast)


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

von m.n. (Gast)


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.

von Klaus (Gast)


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

von M. K. (sylaina)


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

von Ralf D. (doeblitz)


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.

von Joachim B. (jar)


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
von m.n. (Gast)


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.

von Stefan F. (Gast)


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.

von Stefan F. (Gast)


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.

von Stefan F. (Gast)


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.

von int 21h (Gast)


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?

von Dieter F. (Gast)


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.

von Dieter F. (Gast)


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.

von Stefan F. (Gast)


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.

von Dieter F. (Gast)


Lesenswert?

Stefanus F. schrieb:
> und Salae Logic.

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

von Stefan F. (Gast)


Angehängte Dateien:

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

von Dieter F. (Gast)


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.

von int 21h (Gast)


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?

von Thomas W. (diddl)


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.

von Stefan F. (Gast)


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?

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.