Moin,
ich möchte mein OLED (sitzt auf einer Platine) mit meinem Atmega328p
ansprechen.
Die Platine unterstützt die Kommunikation nur über I²C.
Ich lese mich schon seit heute Morgen in das Thema ein und mir ist immer
noch nicht ganz klar, wie ich das ganze anstellen soll.
Mittlerweile weiß ich, wie Daten über das I²C Protokoll übertragen
werden, aber ich weiß nicht, wie man das mit dem Takt regeln soll und
wie man innerhalb einer begrenzten Zeit die jeweiligen Bits übertragen
soll.
Mein Atmega328p ist mit 16mHz getaktet, für das OLED müsste ich
natürlich den Clock Pegel niedriger halten.
Meine Idee wäre, dass ich das mit einem Delay löse, entweder mit einem
Timer Interrupt oder ohne.
Weiter bin ich leider noch nicht gekommen.
Mach mein Ansatz so Sinn?
int 21h schrieb:> Mein Atmega328p ist mit 16mHz getaktet ...
Wie das denn? Solche Quarze sind doch absolut unüblich. Warum wird der
Atmega so "untertaktet" betrieben?
Aber in der Regel wird beim Schreiben eines Bytes über i2c doch der Takt
automatisch durch den Schreibbefehl mit generiert. Warum machst Du das
in deinem Code nicht genauso? Taktsignal setzen, Bit raus, Flanke des
Takts erneut wechseln und so weiter und so weiter.
Tom schrieb:> Wie das denn? Solche Quarze sind doch absolut unüblich. Warum wird der> Atmega so "untertaktet" betrieben?
Ich meine natürlich MHz, falls du das meinst.
(Falls nicht, es liegt am Arduino Uno um genauer zu sein, aber das ist
jetzt nicht Thema :D)
Tom schrieb:> ber in der Regel wird beim Schreiben eines Bytes über i2c doch der Takt> automatisch durch den Schreibbefehl mit generiert. Warum machst Du das> in deinem Code nicht genauso? Taktsignal setzen, Bit raus, Flanke des> Takts erneut wechseln und so weiter und so weiter.
Ok, ich werde mal morgen darüber nachdenken, danke schon mal für den
Hinweis
Hallo, da bin ich wieder.
Ich habe mich mal an die Arbeit gemacht und die Routine zum senden eines
Bytes über das I²C Interface (bzw. TWI) fertig gestellt.
Ich möchte mich nur vergewissern, ob die Routine theoretisch Sinn macht.
1
;Parameter_1 = temp1 (zu sendendes Byte, in dem Fall 0b01101101)
2
;SDA = Pin3, SCL = Pin2
3
oled_send_byte:
4
push temp1
5
push temp2
6
push counter
7
ldi counter, 0x08
8
9
;Start I²C (Sobald SCL High ist und SDA Flanke fällt)
10
ldi temp2, 0b00001100
11
out port, temp2
12
ldi temp2, 0b00000100
13
out port, temp2
14
ldi temp2, 0b00000000
15
out port, temp2
16
17
;Senden der 8 Bits
18
oled_send_byte_loop:
19
com temp2
20
andi temp2, 0b00000100
21
lsl temp1
22
brcs oled_send_byte_0
23
cbr temp2, 0b00001000
24
rjmp oled_send_byte_1
25
oled_send_byte_0:
26
sbr temp2, 0b00001000
27
oled_send_byte_1:
28
out port, temp2
29
com temp2
30
andi temp2, 0b00000100
31
out port, temp2
32
dec counter
33
brne oled_send_byte_loop
34
35
;rcall oled_acknowledge ;(Ist noch nicht fertig)
36
37
pop counter
38
pop temp2
39
pop temp1
40
ret
Ich frage mich halt, ob das ganze so vom SSD1780 richtig verarbeitet
wird, da die Taktrate halt nicht konstant ist, sondern immer
unterschiedlich.
Ich beziehe mich hier also nur auf die Flanken!
Wie man Daten über I²C sendet, habe ich dem Video entnommen:
https://www.youtube.com/watch?v=qVujkT1XUiE
Ich habe das ganze über den AVR Simulator laufen lassen was auch
funktioniert hat.
Ich habe mal ein Diagramm vom Ablauf gezeichnet und hochgeladen.
int 21h schrieb:> Ich möchte mich nur vergewissern, ob die Routine theoretisch Sinn macht.
Nö, macht sie nicht.
Mir fehlen da die diversen Wartezeiten, und der Test ob SDA/SCL
überhaupt ein High erreichen wenn sie es sollten. Man bedenke das z.B.
bei I²C der Slave die Clock stretchen kann...
Jim M. schrieb:> Mir fehlen da die diversen Wartezeiten
Von welchen Wartezeiten sprichst du?
Meinst du, ich sollte zwischen den Flanken ein Delay einbauen?
Jim M. schrieb:> und der Test ob SDA/SCL> überhaupt ein High erreichen wenn sie es sollten
Wieso muss man so etwas testen?
Jim M. schrieb:> Man bedenke das z.B.> bei I²C der Slave die Clock stretchen kann...
Aha... also wird es vorkommen, dass der Slave mit dem Takt nicht
hinterherkommt und man mit dem Master deshalb prüfen muss, ob der Slave
bereit ist für das nächste Bit.
Aber wie signalisiert mir der Slave, dass er fertig ist, den vor dem
Acknowledge Bit vom Slave hat der Master das sagen?
Gibt es eine Möglichkeit, dass ich mich nicht um die TWI Schnittstelle
kümmern muss (evtl. über eine Lib) aber trotzdem den Rest des Codes mit
Assembler anfertige?
Ich könnte dafür C nehmen und eine TWI Lib einbinden, aber dann müsste
ich den Assembler teil in eine Assembler Funktion schreiben oder wie das
halt funktioniert. Das ist nicht so schön.
Hi
>Gibt es eine Möglichkeit, dass ich mich nicht um die TWI Schnittstelle
kümmern muss ...
Warum nutzt du nicht die TWI(i2C)-Schnittstelle deines ATMega328p. Da
brauchst du dich nicht um irgend welche Timings zu kümmern. Kurze
Codebeispiele in ASM und C findest du im Datenblatt.
MfG Spess
spess53 schrieb:> Warum nutzt du nicht die TWI(i2C)-Schnittstelle deines ATMega328p. Da> brauchst du dich nicht um irgend welche Timings zu kümmern. Kurze> Codebeispiele in ASM und C findest du im Datenblatt.>> MfG Spess
Gefunden, danke
(Ist zwar Interrupt basiert, aber etwas anderes habe ich leider nicht
gefunden)
Hi
>(Ist zwar Interrupt basiert, aber etwas anderes habe ich leider nicht>gefunden)
Was ist da Interrupt gesteuert? TWINT ist ein Bit im TWCR-Register ->
Datenblatt.
MfG Spess