So, lange hats nicht gedauert bis etwas wieder nicht so funktioniert wie ich es will. Ich habe vor ein paar Stunden das Forum um Hilfe bei einem LCD (44780, Atmega16, 16MHz) gebeten. Das hat nach einer Weile auch geklappt. Allerdings habe ich dort noch mit Timern gearbeitet. Ich jetzt aber das Busyflag benutzen, nur das geht nicht wie ich es will. Der Code ist im Anhang Kann mir jemand meinen Fehler zeigen? mfg
Das Busy Flag ist nur gültig, während E aktiv ist. Danach ist der Bus wieder hochohmig. Du fragst zum falschen Zeitpunkt ab.
Ok, ich habs jetzt nochmal geändert, allerdings funktioniert es immer noch nicht :(
1) Kann es sein, dass du die Eingänge über PINB abfragen musst? 2) Wenn du den gesamten PORT auf Input setzt, hat das LCD dann keine definierten Pegel an den Eingängen > ldi R16, 0x00 > out LCD_DDR, R16
zu 1.) Also so wie ich es im Tutorial (hier auf dieser Seite) gelesen habe, sollte es mit
1 | sbic |
funktionieren. zu 2.) Das sollte eigentlich egal sein, da der Modus auf "lesen" gesetzt ist. Da muss man eigentlich keine Pegel definieren.
Samuel J. schrieb: > Das sollte eigentlich egal sein Beim R/W, RS und vor allem Enable wird es dem LCD nicht egal sein. >sbic LCD_PORT, DB7 ;Wenn Busyflag gesetzt, nicht mehr > ;zu check_busyflag >springen Das müsste vllt. so ausschauen: sbic PINB, DB7 Kann auch sein, dass ich falsch liege. Ich programmiere eigentlich nur PIC
@Max: stimmt auch wieder. Ich habs geändert, allerdings löst das immer noch nicht das Problem :/
Ja natürlich, das muss PINB heißen facepalm Allerdings geht es immernoch nicht :D
1 | check_busyflag: |
2 | |
3 | cbi LCD_PORT, RS ;RS auf Low legen |
4 | sbi LCD_PORT, RW ;RW auf High legen |
5 | nop |
6 | sbi LCD_PORT, E ;Enable auf High |
7 | |
8 | ldi R16, 0b11110000 ;Port, an dem das LCD hängt, auf Eingang schalten |
9 | out LCD_DDR, R16 |
10 | |
11 | sbic LCD_PORT, DB7 ;Wenn Busyflag gesetzt, nicht mehr zu check_busyflag springen |
12 | rjmp check_busyflag |
Du springst ja wieder hoch und lässt die Bits erneut zappeln.
1 | check_busyflag: |
2 | |
3 | cbi LCD_PORT, RS ;RS auf Low legen |
4 | sbi LCD_PORT, RW ;RW auf High legen |
5 | nop |
6 | sbi LCD_PORT, E ;Enable auf High |
7 | |
8 | ldi R16, 0b11110000 ;Port, an dem das LCD hängt, auf Eingang schalten |
9 | out LCD_DDR, R16 |
10 | check: |
11 | sbic LCD_PORT, DB7 ;Wenn Busyflag gesetzt, nicht mehr zu check_busyflag springen |
12 | rjmp check |
Probier mal das.
Bastler schrieb: > Du springst ja wieder hoch und lässt die Bits erneut zappeln. Wenn die bits gesetzt/gelöscht sind sollte es doch egal sein, wenn sie nochmal gesetzt/gelöscht werden. Die Ausgänge verden ja gesetzt/gelöscht und nicht getoggelt.
@Bastler ich habs geändert, leider bringt auch das keine Veränderung :/
Samuel J. schrieb: > nur das geht nicht wie ich es will Was genau geht nicht? Kannst du messen, ob das Busy-Flag gesetzt wird?
@Max: Das Problem ist, dass am LCD nur in der ersten Zeile schwarze Kästchen angezeigt werden, die Initialisierung also noch nicht richtig abgeschlossen ist. Nein leider nicht, ich habe zu Hause kein Oszi. Ich kann fühestens am Freitag in der Schule messen.
ungefähr so :
1 | .equ LCD_PORT = PORTC |
2 | .equ LCD_DDR = DDRC |
3 | .equ LCDS_PORT = PORTB |
4 | .equ LCDS_DDR = DDRB |
5 | |
6 | .equ LCD_RS = 4 ;PB4 |
7 | .equ LCD_RW = 3 ;PB3 |
8 | .equ LCD_E = 5 ;PB5 |
9 | |
10 | |
11 | |
12 | .def temp = r16 |
13 | .def arg = r17 ;argument for calling subroutines |
14 | .def arg2 = r18 ;argument for mathematics |
15 | .def return = r19 ;return value from subroutines |
16 | |
17 | LCD_getchar: |
18 | in temp, LCD_DDR ;make sure the data lines are inputs |
19 | andi temp, 0b00001111 ;so clear their DDR bits |
20 | out LCD_DDR, temp |
21 | sbi LCDS_PORT, LCD_RS ;we want to access the char data register, so RS high |
22 | sbi LCDS_PORT, LCD_RW ;we also want to read from the LCD -> RW high |
23 | sbi LCDS_PORT, LCD_E ;while E is high |
24 | nop |
25 | in temp, PinC ;we need to fetch the HIGH nibble |
26 | andi temp, 0b00001111 ;mask off the control line data |
27 | swap temp ;******** wir haben jetzt die unteren bits also nach oben damit |
28 | mov return, temp ;and copy the HIGH nibble to return |
29 | cbi LCDS_PORT, LCD_E ;now take E low again |
30 | nop ;wait a bit before strobing E again |
31 | nop |
32 | sbi LCDS_PORT, LCD_E ;same as above, now we're reading the low nibble |
33 | nop |
34 | in temp, PinC ;get the data |
35 | andi temp, 0b00001111 ;and again mask off the control line bits |
36 | ;swap temp ******* jetzt muss hier das swap raus da wir eh schon die low bits haben |
37 | ;temp HIGH nibble contains data LOW nibble! so swap |
38 | or return, temp ;and combine with previously read high nibble |
39 | cbi LCDS_PORT, LCD_E ;take all control lines low again |
40 | cbi LCDS_PORT, LCD_RS |
41 | cbi LCDS_PORT, LCD_RW |
42 | ret ;the character read from the LCD is now in return |
43 | |
44 | LCD_getaddr: ;works just like LCD_getchar, but with RS low, return.7 is the busy flag |
45 | in temp, LCD_DDR |
46 | andi temp, 0b00001111 |
47 | out LCD_DDR, temp |
48 | cbi LCDS_PORT, LCD_RS |
49 | sbi LCDS_PORT, LCD_RW |
50 | sbi LCDS_PORT, LCD_E |
51 | nop |
52 | in temp, PinC |
53 | andi temp, 0b00001111 |
54 | swap temp |
55 | mov return, temp |
56 | cbi LCDS_PORT, LCD_E |
57 | nop |
58 | nop |
59 | sbi LCDS_PORT, LCD_E |
60 | nop |
61 | in temp, PinC |
62 | andi temp, 0b00001111 |
63 | ;swap temp |
64 | or return, temp |
65 | cbi LCDS_PORT, LCD_E |
66 | cbi LCDS_PORT, LCD_RW |
67 | ret |
68 | |
69 | LCD_wait: ;read address and busy flag until busy flag cleared |
70 | |
71 | rcall LCD_getaddr |
72 | andi return, 0x80 ;bit 4 /4bit high bit (80) |
73 | brne LCD_wait |
74 | ret |
Du schaltest hiermit ... ldi R16, 0b11110000 ;Port, an dem das LCD hängt, auf Eingang schalten out LCD_DDR, R16 ... dein Pin an dem das Busyflag hängt auf Ausgang.
Bastler schrieb: > ldi R16, 0b11110000 ;Port, an dem das LCD hängt, auf Eingang >... dein Pin an dem das Busyflag hängt auf Ausgang Samuel J. schrieb: > RS auf PB4 > RW auf PB5 > E auf PB6 > DB7-DB4 auf PB3-0
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.