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 ^^
Falls du C kannst, würde ich Dir empfehlen, von einer C Library abzugucken. Das Datenblatt ist nämlich an vielen Stellen ziemlich unklar.
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.
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 | }
|
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?
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?
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.
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)."
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
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?
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?
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).
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.
int 21h schrieb: > ich möchte mein OLED (SSD1306) mit einem Atmega über TWI ansteuern. > Das ganze natürlich mit Assembler. warum?
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
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.
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??
Kann es sein, dass du das Display noch nicht initialisiert hast? Ich habe dazu noch keinen Programmcode gesehen. Diese Displays brauchen eine umfangreiche Initialisierungssequenz.
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
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
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.
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 :/
> 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.
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.
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)?
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
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!
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
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!
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.
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.
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.
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
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
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.
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
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.
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
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 ;)
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.
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
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.
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.
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.
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.
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?
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.
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.
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.
Stefanus F. schrieb: > und Salae Logic. Saleae nutze ich - da ist es mir noch nicht aufgefallen. Ich schaue mal.
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
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.
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?
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.
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
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.