Hallo, bin gerade dabei mir die LCD Ansteuerung mithilfe des Tutorials beizubringen. Leider Funktioniert es nicht wie gewünscht. Ich habe erstmal nur den Code von http://www.mikrocontroller.net/articles/AVR-Tutorial:_LCD#Routinen_zur_LCD-Ansteuerung_im_4-Bit-Modus und weiter unten das: http://www.mikrocontroller.net/articles/AVR-Tutorial:_LCD#Anwendung kopiert. Ich verwende einen atmega8a und habe .include "m8def.inc" in .include "m8adef.inc" geändert. Da ich des weiteren alles in eine Datei gepackt habe entfällt bei mir das allerletzte .include "lcd-routines.asm". Nun habe ich mir das Datenblatt meines Displays zur Hand genommen http://www.lcd-module.de/pdf/doma/2_16.pdf und auf Seite 4 unter Hinweis folgenden Satz gelesen: "Im 4-Bit Mode ist die Busy-Abfrage vor jedem Bytezugriff notwendig." Sooo nun erstmal die Frage: hat hier schonmal jemand das Display ohne Busy-Flag Abfrage zum laufen bekommen? Im mitgelieferten Datenblatt ist dieser Satz nämlich nicht zu finden. Grüße Flo Rida edit: Meine das DIP162-DNLED, sorry
:
Bearbeitet durch User
Ich denke, dass kaum einer das Busy-Flag liest: dazu müsste man schonmal die R/W-Leitung umschalten zum Lesen, und die liegt bei den allermeisten Beispielen (auch im Tutorial) permanent auf GND. Bei einem LCD kann viel schiefgehen: Leitungen vertauscht oder vergessen, Kontrast nicht richtig eingestellt... Ich empfehle Dir, das Tutorial zunächst 1:1 umzusetzen (so ein Mega8 kostet ja nicht viel), dann Dein Programm anzupassen und dann den Chip zu ändern. Oder wenn Du es bequem haben willst: Mit Bascom ist die LCD-Ansteuerung mit 2 Zeilen erledigt.. :-)
Fabian Rauer schrieb: > "Im 4-Bit Mode ist die > Busy-Abfrage vor jedem Bytezugriff notwendig." Wenn das im Dabla steht(und das tut es definitiv) wird das sicher notwendig sein!
Rainer Unsinn schrieb: > Ich denke, dass kaum einer das Busy-Flag liest: dazu müsste man schonmal > die R/W-Leitung umschalten zum Lesen, und die liegt bei den allermeisten > Beispielen (auch im Tutorial) permanent auf GND. Wenn man sich nicht an die Tutorials hält und einfach alles selbst macht, dann kommt es auf die paar Zeilen auch nicht mehr an:
Aus deinem Datenblatt! Hier ist auch der ganze Port gemeint im 8 bit Modus >HINWEIS >Die in der >Tabelle angegebenen >Ausführungszeiten gelten nur bei >Abfrage des Busy Flags; d.h. vor >jedem Schreib- und Lesezugriff >muß das Busy Flag BF auf 0 >abgefragt werden. Du kannst auch ohne Busy abfrage machen aber die Zeiten sind eben länger. >Wird das Busy >Flag nicht abgefragt, so sind die >Ausführungszeiten zum Teil >wesentlich länger als angegeben. Die Busy abfrage kann im 4 Bit modus wegelassen werden aber die Delays müssen wie oben entsprechend angepasst werden. >Im 4-Bit Mode ist die Busy-Abfrage >vor jedem Bytezugriff notwendig Im 4 Bit Modus sendest du ein Byte in dem du, das obere und untere halbyte sendest und dabei jedesmal die Busy-Abfrage durchführst.
Teo Derix schrieb: > Fabian Rauer schrieb: >> "Im 4-Bit Mode ist die >> Busy-Abfrage vor jedem Bytezugriff notwendig." > > Wenn das im Dabla steht(und das tut es definitiv) wird das sicher > notwendig sein! Das bezieht sich nur darauf, dass im 4 Bit Modus vor jeder Übertragung eines Bytes das Busy Flag abzufragen ist, wenn man überhaupt das Busy Flag verwendet. Man könnte ja auch der Meinung sein, man müsse für jedes Nibble das Busy Flag befragen. Die erste Frage lautet also: Will ich grundsätzlich das Busy Flag abfragen oder warte ich einfach im Code eine gewisse Zeit ab. Nur dann, wenn die Antwort darauf lautet "Jep, ich will Busy Flag abfragen", dann wird der Satz relevant als Antwort auf die Frage: Wie oft muss ich es dann abfragen, wenn ich doch für jedes Daten-Byte 2 Übertragungen benötige.
:
Bearbeitet durch User
Da ham se sich aber SEHR ungeschickt ausgedrückt! Für merkwürdig hab ich das allerdings schon gehalten.
Äh ok. Vielen Dank für eure Meinungen dazu. Also Code passt 100%ig zum LCD? Dann wohl ein Verdrahtungsfehler. Grüße Fabian Rauer
Jetzt muss ich mich leider doch nochmal zurückmelden. Ich habe den folgenden Code irgendwo im Internet gefunden, ich weiß leider nicht mehr wo:
1 | .include "m8adef.inc" |
2 | |
3 | .def temp = r16 |
4 | .def temp1 = r17 |
5 | |
6 | main: |
7 | ldi temp, HIGH(RAMEND) ;Stackpointer initialisieren |
8 | out SPH, temp |
9 | ldi temp, LOW(RAMEND) |
10 | out SPL, temp |
11 | |
12 | ldi temp,0xFF ;Port D auf Ausgang |
13 | out DDRD,temp |
14 | |
15 | |
16 | init: ;ldi temp, 0b00110000 ;3 mal laut Tutorial senden |
17 | ;out PORTD,temp ;(diesen Teil versuchsweise weggelassen) |
18 | ;rcall enable |
19 | ;rcall zeit |
20 | ;rcall enable |
21 | ;rcall zeit |
22 | ;rcall enable |
23 | ;rcall zeit |
24 | |
25 | ldi temp, 0b00100000 ;oberes nibble function set setzt: |
26 | out PORTD,temp ;4 bit modus |
27 | rcall enable |
28 | rcall zeit |
29 | rcall zeit |
30 | rcall zeit |
31 | ldi temp, 0b11000000 ;unteres nibble function set setzt: |
32 | out PORTD,temp ;zweizeiliges Display und 5*10 dit Display |
33 | rcall enable |
34 | rcall zeit |
35 | |
36 | ldi temp, 0b00000000 ;oberes nibble Display on/off control |
37 | out PORTD,temp |
38 | rcall enable |
39 | rcall zeit |
40 | ldi temp, 0b11110000 ;unteres nibble Display on/off control setzt: |
41 | out PORTD,temp ;Display ein,Cursor ein,Cursor blinkt |
42 | rcall enable |
43 | rcall zeit |
44 | |
45 | ldi temp, 0b00000000 ;oberes nibble clear display |
46 | out PORTD,temp |
47 | rcall enable |
48 | rcall zeit |
49 | ldi temp, 0b00010000 ;unteres nibble clear display setzt: |
50 | out PORTD,temp ;Clear display, return cursor to home |
51 | rcall enable |
52 | rcall zeit |
53 | |
54 | ldi temp, 0b00000000 ;oberes nibble entry mode set |
55 | out PORTD,temp |
56 | rcall enable |
57 | rcall zeit |
58 | ldi temp, 0b01100000 ;unteres nibble entry mode set setzt: |
59 | out PORTD,temp ;DD-RAM Adresse inkrementieren |
60 | rcall enable |
61 | rcall zeit |
62 | |
63 | sbi PORTD,3 ;RS=1 |
64 | |
65 | w: rjmp w |
66 | |
67 | |
68 | enable: |
69 | sbi PORTD,1 ;E=1 |
70 | nop |
71 | nop |
72 | nop |
73 | cbi PORTD,1 ;E=0 |
74 | ret |
75 | |
76 | zeit: ldi temp,0xFF ;eine 80ms Warteschleife |
77 | WGLOOP0: ldi temp1,0xFF |
78 | WGLOOP1: dec temp1 |
79 | brne WGLOOP1 |
80 | dec temp |
81 | brne WGLOOP0 |
82 | ret |
natürlich will ich nicht dass ihr das durchschaut. Aber was auffällig ist, dass das untere Nibble immer 0 ist. Nun ist meine Frage wie kann es sein, dass auf meinem Display was erscheint wo ich doch nach der Anleitung im Tutorial gegangen bin? Diese Anleitung sieht nämlich nur eine Anbindung an der Datenbits 4-7 des Displays an die Portpins 0-3 vor? Viele Grüße Fabian Rauer
Fabian Rauer schrieb: > natürlich will ich nicht dass ihr das durchschaut. Das ist dir gründlich misslungen. Ich versteh' das. Mehr noch: es hat mich auch nur zweieinhalb Sekunden gekostet, die Quelle des Codes zu finden... > Aber was auffällig > ist ..., daß du immer nur geklauten Code hier postest. Wie wäre es, wenn du statt dessen einfach mal lernst, den auch zu verstehen, und damit die Kompetenz erlangst, Fehler darin zu suchen und/oder ihn deinen eigenen Bedürfnissen entsprechend anpassen zu können... Programmieren ist nicht wirklich sowas wie ein Puzzle, auch wenn es vielen Copy&Paste-Idioten zunächst vielleicht so vorkommen mag...
Teo Derix schrieb: > Wenn das im Dabla steht(und das tut es definitiv) wird das sicher > notwendig sein! Dann wäre das Display bei den HD44780-kompatiblen ein echter Außenseiter und definitiv nicht kompatibel. Diverse gut ohne Lesebefehl funktionierende EA DIP162 beweisen, dass auch ohne Busy das Display wunderbar funktioniert, wenn man ihm bei einigen länger dauernden Befehlen die Zeit für die Ausführung gönnt. Da das Display ziemlich deterministisch ist und es eigentlich auch keinen Grund gibt, das letzte aus dem Display heraus zu holen und dafür den µC damit zu beschäftigen, das Busy-Flag abzufragen, kann der µC in der Zwischenzeit besser etwas sinnvolles tun.
Nun gut also dann Fange ich woanders an. Ausgangspunkt war folgender: http://www.mikrocontroller.net/articles/AVR-Tutorial:_LCD#Routinen_zur_LCD-Ansteuerung_im_4-Bit-Modus Da steht:
1 | ldi temp1, 0b00000010 ; 4bit-Modus einstellen |
2 | out PORTD, temp1 |
3 | rcall lcd_enable |
4 | rcall delay5ms |
5 | ldi temp1, 0b00101000 ; 4Bit / 2 Zeilen / 5x8 |
6 | rcall lcd_command |
meiner Meinung deckt die zweite Anweisung auch den Befehl des ersten Bitmusters mit ab. Wieso ist das hier so gewählt? Die Anleitung meines HD44780 ermöglicht eine gemeinsame Übertragung der Einstellungen. Grüße Fabi
Fabian Rauer schrieb: > Wieso ist das hier so gewählt? Weil sich der Controller zu diesem Zeitpunkt im 8-Bit-Modus befindet. Das untere Nibble des Befehls steht also nicht zur Verfügung. Die fehlenden zwei Einstellungen müssen also später im 4-Bit-Modus nachgeholt werden. Mache dir auch den Unterschied zwischen lcd_enable und lcd_command klar. Ich finde das AVR-Tutorial einen ungünstigen Einstieg in das Thema LCD (und gehe für diese Aussage schonmal in Deckung). Für einen Anfänger wäre es sicher einfacher, ein LCD zunächst ausschließlich im 8-Bit-Modus zu betreiben. Am Atmega8(A) wird die Sache dann weiter kompliziert, weil man für einen zusammenhängenden Port mit 8 Bit entweder den USART oder die externe Taktversorgung blockieren muss.
Man kann auch ein Latch nehmen um das LCD im 8 Bit Modus zu betreiben und hat den Port jederzeit für andere Dinge zur Verfügung. Habe ich immer so gemacht als ich mit einem ATtiny26 nicht alle Pinsel opfern wollte um möglichst alle ADC Kanäle zu nutzen.
Also ganz ehrlich mein Display scheint kaputt zu sein. Der Anschluss ist wie folgt: PD5 PD4 PD3 PD2 PD1 PD0 E RS D7 D6 D5 D4 Damit ist es wie im Tutorial angeschlossen. Mit folgendem Code initialisiere ich das Display:
1 | .include "m8adef.inc" |
2 | |
3 | .def temp = r16 |
4 | .def temp1 = r17 |
5 | |
6 | init: |
7 | longwait: |
8 | ldi temp, 255 |
9 | rcall zeit ;Diplay bekommt 12,75ms zum selber initialisieren |
10 | dec temp |
11 | brne longwait |
12 | |
13 | ldi temp, 0b00000010 ;setzt Display in |
14 | out PORTD,temp ;function set und data lenght 4-Bit |
15 | rcall enable |
16 | rcall zeit |
17 | |
18 | ldi temp, 0b00000010 ;oberes nibble für: |
19 | out PORTD,temp ;function set und data lenght 4-Bit |
20 | rcall enable |
21 | ldi temp, 0b00001100 ;unteres nibble für: |
22 | out PORTD,temp ;2-Zeilig und 5x8 Font, letzten beiden immer NULL |
23 | rcall enable |
24 | rcall zeit |
25 | |
26 | ldi temp, 0b00000000 ;oberes nibble für: |
27 | out PORTD,temp ;Display ON/OFF control |
28 | rcall enable |
29 | ldi temp, 0b00001111 ;unters nibble für: |
30 | out PORTD,temp ;Display ein, Cursor ein, Cursor blinken |
31 | rcall enable |
32 | rcall zeit |
33 | |
34 | ldi temp, 0b00000000 ;oberes nibble für: |
35 | out PORTD,temp ;Display control |
36 | rcall enable |
37 | ldi temp, 0b00000001 ;unters nibble für: |
38 | out PORTD,temp ;Display löschen, cursor auf 1.Spalte von 1.Zeile |
39 | rcall enable |
40 | rcall zeit ;eigentlich zu kurz, aber ist letzte Übertragung der ans Display geht |
41 | |
42 | enable: |
43 | sbi PORTD,5 ;E=1 |
44 | nop |
45 | nop |
46 | nop |
47 | cbi PORTD,5 ;E=0 |
48 | ret |
49 | |
50 | |
51 | |
52 | zeit: |
53 | ldi temp,0x42 ;eine 50us Warteschleife |
54 | WGLOOP: |
55 | dec temp |
56 | brne WGLOOP |
57 | ret |
58 | |
59 | main: |
60 | ldi temp, HIGH(RAMEND) ;Stackpointer initialisieren |
61 | out SPH, temp |
62 | ldi temp, LOW(RAMEND) |
63 | out SPL, temp |
64 | |
65 | ldi temp,0xFF ;Port D auf Ausgang |
66 | out DDRD,temp |
67 | |
68 | rcall init |
Nur tut sich leider gar nichts. Um auszuschließen, dass das Display in einem undefinierten Zustand ist schalte ich es zu jedem Codetest vorher aus und wieder an. Die SUT_CKSEL steht auf INTRCOSC_4MHZ_6CK_0MS. Kann es sein, dass noch irgendwelche Zeiten nicht stimmen? Grüße Fabi
Fabian Rauer schrieb: > Also ganz ehrlich mein Display scheint kaputt zu sein. Jaja, Hauptsache du hast nichts falsch gemacht. Einfach mal ein paar offensichtliche Fehler in deinem Code: main wird nicht erreicht und schon gar nicht zu Beginn ausgeführt. Anders als in C, beginnt die Ausführung in asm nicht bei main (der Assembler kennt gar keine labels, das ist nur eine Gedächtnisstütze für dich) sondern "oben". Damit sind jedenfalls der SP und das DDR nicht korrekt initialisiert. Du hast da eine schöne Endlosschleife gebaut. Überlege dir doch mal, was da eigentlich passiert. Ich sehe mindestens zwei Fehler. Für den einen gibt deine IDE bestimmt auch eine Warnmeldung aus. Versuch doch endlich mal zu verstehen, was du da in kleinen Variationen abtippst.
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.