Hallo alle Zusammen, seit Tagen versuche ich irgendetwas an meinem LCD zu sehen, jedoch tut sich nichts....egal was ich probiere .. Ich wollte mit meinem Mikrocontroller eine Spannung (0 bis 5V) zu messen und diese am lcd ausgeben lassen... Vielleicht kann mir jemand einen Tipp geben ...
> .equ LCD_PORT=PORTA > .equ LCD_DDR=PORTA Keine Ahnung, ob das der einzige Fehler ist, aber bevor ich weiter suche ...
AmAnfang schrieb: > seit Tagen versuche ich irgendetwas an meinem LCD zu sehen, jedoch tut > sich nichts... Wie sind die beiden miteinander verbunden? Woher hast du den Code? Und was stand dort ursprünglich?: ;PB4..PB5 auf PA1..PA2 ;PB6..PB7 auf PA6..PA7 Denn offenbar(!) ist der Code für einen Anschluss der Datenleitungen 7..4 des Displays an PA3..0 vorgesehen... Das legen diese sich dauernd wiederholenden Zeilen nahe: andi mp2,0b00001111 out LCD_PORT, mp2
:
Bearbeitet durch Moderator
Ist das LCD denn richtig angeschlossen? Hat es schon mal funktioniert? Ist die Kontrast-Spannung OK, d.h. wenn es ein normales xy Zeilen Display ist solltest Du beim Anlegen der Spannung ein Kästchen-Muster sehen. Wenn nicht, ist wahrscheinlich schon was falsch. Ansonsten bin ich kein ASM experte, aber kann es sein, dass die Zeichen nie gesendet werden ???? LOOP: sbic ADCSRA, ADSC rjmp LOOP
> ;fertig initialisiert > ldi mp1,0b00000100 > rcall LCD_command > ret Für dieses 'ret' sehe ich kein 'rcall', es läuft ins Leere, noch vor jeglicher Ausgabe. Erst nochmal gründlich überarbeiten; gilt sehr wahrscheinlich auch für die Hardware.
Hallo Zusammen, ich habe den Quellcode aus dem AVR Tutorial genommen und diesen meine Schaltung angepasst. http://www.mikrocontroller.net/articles/AVR-Tutorial:_LCD AmEnde schrieb: >> .equ LCD_PORT=PORTA >> .equ LCD_DDR=PORTA > > Keine Ahnung, ob das der einzige Fehler ist, aber bevor ich weiter suche > ... Warum ist das falsch? Anbei meine Schaltung und ich denke die ist richtig verschaltet
AmAnfang schrieb: > ich habe den Quellcode aus dem AVR Tutorial genommen und diesen meine > Schaltung angepasst. Ach, Blödsinn. Hast du meinen Post nicht gelesen oder nicht verstanden? Die Portzuordnung im Programm passt NIEMALS auf deine Hardware. Es ist keine gute Idee, vier Datenleitungen, die zusammengehören (Stichwort: Nibble) auf die am weitesten auseinander liegenden Portpins zu verdrahten. Und diese gewaltige Änderung NICHT ins Programm zu übernehmen... >>> .equ LCD_PORT=PORTA >>> .equ LCD_DDR=PORTA > Warum ist das falsch? Weil das Datenrichtungsregister DDRx eine ganz andere Adresse als das Portregister PORTx hat... Warum machst du deine Hardware nicht einfach GENAU SO wie im Tutorial, wenn du schon keinen Schimmer hast, was du anpassen musst und warum du es anpassen musst?
:
Bearbeitet durch Moderator
Muss das Kontrastspannungspoti nicht als Spannungsteiler beschaltet sein?
Ist das mit dem Kontrastpotie so im Datenblatt? Der in dieser Schaltung offene Anschluss gehört normalerweise an +
Danke für die lieben Antworten.. hmm also ich dachte da ich im Gegensatz zu Tutorial Attiny26 anwende muss ich auch den Code ändern und nicht einfach übernehmen... Gemäß meine Schaltung habe ich PB4 mit PA1, PB5 mit PA2, PB6 mit PA6, PB7 mit PA7 verbunden. In Tutorial : DB4-DB7: PD0-PD3 ;; RS: PD4 ;; E: PD5 Daher habe ich den Quellcode verändert :(
Mal von den komplett fehlenden Entkopplungskondensatoren am uC ganz abgesehen. Muss denn jeder jeden Fehler nochmal machen?
AmAnfang schrieb: > Daher habe ich den Quellcode verändert :( Aber nicht genug. Bei Weitem nicht! Im Programm sind immer noch die Datenleitungen als Nibble (=halbes Byte im Viererblock) zusammen gefasst. In deiner Hardware sind sie wild zerpflückt. Warum eigentlich?
:
Bearbeitet durch Moderator
Ohjee ... also meinst du den Teil: push mp2 mov mp2,mp1 swap mp1 andi mp1,0b00001111 out LCD_PORT,mp1 rcall LCD_enable andi mp2,0b00001111 out LCD_PORT, mp2 rcall LCD_enable rcall delay50us pop mp2 ret mir wurde gesagt an diesen Teil sollte ich nichts änder... wäre es dann so richtig: push mp2 mov mp2,mp1 swap mp1 andi mp1,0b11000110 out LCD_PORT,mp1 rcall LCD_enable andi mp2,0b11000110 out LCD_PORT, mp2 rcall LCD_enable rcall delay50us pop mp2 ret
Lothar M. schrieb: > In deiner Hardware sind sie wild zerpflückt. Warum eigentlich? Vielleicht beim Arduino abgeguckt, aber die IO-Abstraktionsschicht in der Software nicht implementiert ;-)
AmAnfang schrieb: > wäre es dann so richtig: > > push mp2 > mov mp2,mp1 > swap mp1 > andi mp1,0b11000110 > out LCD_PORT,mp1 > rcall LCD_enable > andi mp2,0b11000110 > out LCD_PORT, mp2 > rcall LCD_enable > rcall delay50us > pop mp2 > ret Nein. Du hast ja lediglich das 'andi' auf deine Portpins angepasst. Du musst bei deiner Beschaltung aber die Datenbits 7 bis 4 auf deine verteilten Ausgangspins verteilen. Das ist umständlich und unübersichtlich. Ich selbst hab das zu Anfangs auch mal versucht und weiß deshalb, es brigt für Anfänger nur Ärger. Ändere deine Schaltung so dass die LCD-Datenleitungen DB4 bis DB7 am Atmel auch genau an den Portpins 4 bis 7 hängen. RS und E kannst du dann an die unteren Portpins 0-3 hängen. Wurde schon gesagt: Das Kontrastpoti muss an 5V und Masse angeschlossen sein. Mittenabgriff dann ans LCD.
Im "AVR-Tutorial: LCD" steht eigentlich alles Nötige. Falls Sie aber doch eine freie Pin-Zuordnung wollen, anbei ein Beispielprogramm, wie man es lösen könnte. Gar so "umständlich und unübersichtlich" wie igel finde ich es nicht, zumal man es einmal schreibt und dann die nächsten Jahre nicht mehr anfasst.
S. Landolt schrieb: > Gar so "umständlich und > unübersichtlich" wie igel finde ich es nicht, zumal man es einmal > schreibt und dann die nächsten Jahre nicht mehr anfasst. Ja. Wenn man einigermassen programmieren kann. Der TO kann das ganz offensichtlich noch nicht einmal in den Grundzügen.
:
Bearbeitet durch User
Thomas F. schrieb: > > Ändere deine Schaltung so dass die LCD-Datenleitungen DB4 bis DB7 am > Atmel auch genau an den Portpins 4 bis 7 hängen. RS und E kannst du dann > an die unteren Portpins 0-3 hängen. > > Wurde schon gesagt: Das Kontrastpoti muss an 5V und Masse angeschlossen > sein. Mittenabgriff dann ans LCD. Meinst du dass ich die Verbungen so umändern soll? Wenn ich die Pins so umändere muss ich dann nicht viel an den Pins verändern? DB4-DB7: PA4-PA7 ;; RS: PA3 ;; E: PA2
BTW, es gibt eine "Lib" in einer bösen Sprache: Mcucpp. Da kannen man "PinSets" definieren und der Compiler kümmert sich um die Bit-Pfrimelei. Wenn man sich mit dem Lötkolben nicht zu doof angestellt hat und D4..7 schön hintereinander liegen, dann ist das Ergebnis einfachster Maschinen-Code. Wenn nicht dann durchschaut man' weniger schnell, aber man bekäme es von Hand aus nicht schneller hin. HD77480-Treiber hat das Paket von Haus aus.
AmAnfang schrieb: > Meinst du dass ich die Verbungen so umändern soll? Wenn ich die Pins so > umändere muss ich dann nicht viel an den Pins verändern? > > DB4-DB7: PA4-PA7 > ;; RS: PA3 > ;; E: PA2 Wenn man deine Programmierkünste zu Grunde legt, dann ist es viel einfacher, wenn du zum Code aus dem Tutorial zurückkehrst, (aber bitte den richtigen, ganz unten) und dort deinen benutzten Port einträgst und die Leitungen entsprechend dieser Belegung umlötest. Als ADC Eingang nimmst du dann einen vom Port B
:
Bearbeitet durch User
Nach deiner Beschreibung hast du bisher gar nichts gesehen. Wenn das Kontrastpoti richtig angeschlossen ist, sollte das LCD so aussehen: https://www.mikrocontroller.net/attachment/116787/Schwarzer_Balken_2x16_LCD.jpg Dann kannst du mit dem Programmcode weitermachen. Der Vorschlag von Karl Heinz, die Originalbeschaltung aus dem Tut zu verwenden, ist bestimmt die vielversprechendste Methode das schnell zum Laufen zu bekommen: PortPin_0 -> DB4 PortPin_1 -> DB5 usw....
Vorschlag: das obige Programm hat zumindest einen Vorteil: es läuft. Sie können es also zur Kontrolle Ihrer Hardware (HD44780 o.ä. vorausgesetzt) verwenden, müssen dazu nur im '.equ'-Block Ihre Pin-Verdrahtung eintragen. Wenn Sie dann endlich den Text auf dem LCD sehen, können sie es wieder wegwerfen und mit der Eigenentwicklung incl. ADC-Auswertung weitermachen.
> Wenn Sie dann endlich den Text auf dem LCD sehen, können > sie es wieder wegwerfen und mit der > Eigenentwicklung incl. ADC-Auswertung weitermachen. Genau, so macht man das. Mir ist noch aufgefallen, dass im Schaltplan die immer wieder monierten Abblockkondensatoren fehlen.
S. Landolt schrieb: > Wenn Sie dann endlich den Text auf dem LCD sehen, können sie es wieder > wegwerfen sagen wir nicht 'wegwerfen'. Sagen wir: es als Ausgangspunkt für die weitere Entwicklung hernehmen
S. Landolt schrieb: > Vorschlag: das obige Programm hat zumindest einen Vorteil: es > läuft. > Sie können es also zur Kontrolle Ihrer Hardware (HD44780 o.ä. > vorausgesetzt) verwenden, Was heißt das? Sorry ich habe es jetzt nicht verstanden... müssen dazu nur im '.equ'-Block Ihre > Pin-Verdrahtung eintragen. Was alles müsste ich ändern damit ich etwas am LCD sehen kann?
AmAnfang schrieb: > Was alles müsste ich ändern damit ich etwas am LCD sehen kann? Lies den Thread noch mal durch. Den einfachsten Weg hat Karl Heinz beschrieben. Karl H. schrieb: > Wenn man deine Programmierkünste zu Grunde legt, dann ist es viel > einfacher, wenn du zum Code aus dem Tutorial zurückkehrst, ...
Datenblatt [[http://www.bluemoon-lcd.com/gb2312/pdf/C1602A.pdf]] Ohne die richtige Kontrast-Spannung V0 wird man nie etwas sehen und immer blind im Trüben rühren...
> Was alles müsste ich ändern damit ich etwas am LCD sehen kann?
Das ist nicht so leicht zu beantworten, da wahrscheinlich, wie auch
Andere vermuten, die Hardware noch fehlerhaft ist.
Die Einträge im 'Testprogramm' (nennen wir es mal so) müssen der
Verdrahtung entsprechen, also z.B. für das LCD-enable:
.equ DDR_LCDen = DDRA
.equ PORT_LCDen = PORTA
.equ LCDen = 5
Wenn der Schaltplan von oben noch gültig ist, dann fehlt nur noch
LCD-rs, die Datenleitungen stimmen schon; ich habe das Programm
dementsprechend geändert und beigefügt, Sie müssen es nur noch
compilieren und laden.
Was ist den überhaupt die Betriebsspannung ? 3,3V ? 5V ? Weil bei 3,3V benötigst du eine negative Spannung für den Kontrast.
Genau, ohne Kontrastspannung nutzt der schönste Code nichts... aber das scheint der TO einfach nicht verstehen zu wollen.
Entschuldigung, das war falsch, ich hatte noch keinen Kaffee. Hier das richtige Testprogramm.
S. Landolt schrieb: > Entschuldigung, das war falsch, ich hatte noch keinen Kaffee. Hier > das > richtige Testprogramm. Hey, hast du das extra gemäß meinen Schaltplan erstellt?
ich seh schon, der TO sucht immer noch nach ner Lösung.... Pauschal fehlts an einer Menge Grundlagen wie der AVR und ein LCD zusammen fungieren.
Es läuft hier auf meinem Tisch, wenn auch mit einem steinalten LCD und einem ATtiny461 (das Programm gilt aber für Ihren ATtiny26).
AmAnfang schrieb: > sooo...vielen Dank nochmal an allen Noch ein Hinweis: Was S. Landolt dir angeboten hat sind "nur" die Unterprogramme für die LCD-Ansteuerung. Dein Hauptprogramm muss aber auch noch richtig eingebunden werden - denn das war bei deinem ersten Versuch auch ziemlich falsch: Der µC beginnt mit der Abarbeitung des Programms bei Adresse 0, d.h. ganz oben (wenn man keine entsprechenden Assembler-Anweisungen verwendet). Zuerst kommt die Initialisierung, anschließend das Hauptprogramm mit Endlosschleife. Die Unterprogramme, jeweils mit "ret" abgeschlossen, kommen danach. Wenn man die Anordnung verändern will, braucht man an den entsprechenden Stellen Sprünge im Programm. Bei dir ist ein Teil der Initialisierung (Stack, Ports) vorne (richtig!), ein weiterer Teil (Init ADC) hinten (falsch!, es fehlt der Sprung dahin) und ganz am Ende fehlt der Sprung zur Hauptprogramm-Schleife. Gruß Dietrich
> Was S. Landolt dir angeboten hat sind "nur" die Unterprogramme > für die LCD-Ansteuerung. Mitnichten. Es ist ein komplettes Programm, das den Text "Anfang&Ende" auf das LCD ausgibt.
S. Landolt schrieb: > Mitnichten. Es ist ein komplettes Programm, das den Text "Anfang&Ende" > auf das LCD ausgibt. Ja, du hast natürlich recht. Das winzige Hauptprogramm habe ich doch glatt übersehen, Entschuldigung! Dann bleibt für "AmAnfang" aber der Hinweis auf die Mängel bei seinem ehemaligen Hauptprogramm, denn das wurde bis jetzt kaum angesprochen. Gruß Dietrich
da du sicherlich auch die Werte vom ADC aufs LCD ausgeben willst hier noch eine Routine zum umwandeln ins ASCII Format. Ist für eine 10 Bit Wandlung vom ADC gedacht, hatte mal damit eine Ladedruckanzeige gebaut, allerdings im 8 Bit Modus da ich einen Latch als Porterweiterung verwendet habe. Da der Code jetzt nicht ganz so lange ist habe ich ihn einfach mal eingefügt ohne erst ne extra Datei anzulegen.
1 | bin2ascii:
|
2 | clr ASCII1 |
3 | clr ASCII2 |
4 | clr ASCII3 |
5 | clr ASCII4 |
6 | |
7 | Lade1024: |
8 | ; ldi Zahl1l, LOW(999) ;Zahl die umgewandelt werden soll |
9 | ; ldi Zahl1h, HIGH(999) |
10 | |
11 | Lade1000: |
12 | ldi Zahl2l, LOW(1000) |
13 | ldi Zahl2h, HIGH(1000) |
14 | rjmp Vergleich1 |
15 | |
16 | Lade100: |
17 | ldi Zahl2l, LOW(100) |
18 | ldi Zahl2h, HIGH(100) |
19 | ret
|
20 | |
21 | Lade10: |
22 | ldi Zahl2l, LOW(10) |
23 | ldi Zahl2h, HIGH(10) |
24 | ret
|
25 | |
26 | Vergleich1: ;Vergleich ob >1000 |
27 | cp Zahl1l,Zahl2l |
28 | cpc Zahl1h, Zahl2h |
29 | brlo Vergleich2 ;ansonsten Vergleich ob >100 |
30 | |
31 | Rechnung1: |
32 | sub Zahl1l,Zahl2l |
33 | sbc Zahl1h,Zahl2h |
34 | inc ASCII1 |
35 | |
36 | Vergleich2: ;Vergleich ob >100 |
37 | rcall Lade100 |
38 | cp Zahl1l,Zahl2l |
39 | cpc Zahl1h, Zahl2h |
40 | brlo Vergleich3 ;ansonsten Vergleich on >10 |
41 | |
42 | Rechnung2: |
43 | sub Zahl1l,Zahl2l |
44 | sbc Zahl1h,Zahl2h |
45 | inc ASCII2 |
46 | rjmp Vergleich2 |
47 | |
48 | Vergleich3: ;Vergleich ob >10 |
49 | rcall Lade10 |
50 | cp Zahl1l,Zahl2l |
51 | cpc Zahl1h, Zahl2h |
52 | brlo Rechnung4 ;ansonsten Einerstellen übernehmen |
53 | |
54 | Rechnung3: |
55 | sub Zahl1l,Zahl2l |
56 | sbc Zahl1h,Zahl2h |
57 | inc ASCII3 |
58 | rjmp Vergleich3 |
59 | |
60 | Rechnung4: |
61 | mov ASCII4, Zahl1l |
62 | |
63 | Dec2Ascii: |
64 | ldi temp, 48 |
65 | add ASCII1, temp |
66 | add ASCII2, temp |
67 | add ASCII3, temp |
68 | add ASCII4, temp |
69 | mov temp, ASCII1 |
70 | cpi temp, 48 |
71 | brne zurueck |
72 | ldi temp, 32 |
73 | mov ASCII1, temp |
S. Landolt schrieb: > Entschuldigung, das war falsch, ich hatte noch keinen Kaffee. Hier > das > richtige Testprogramm. Ich bin gerade dabei den Code zu verstehen, ist doch etwas anders als wie im Tutorial... Nur noch zwei Fragen undzwar, ich verstehe nicht ganz was da passiert : 1) LCDcmd: ; command byte cbi PORT_LCDrs,LCDrs push tmp0 rcall LCDb pop tmp0 andi tmp0,$FC -------->?? breq pc+2------------------> pc+2?? ret LCDn: ; nibble sbi PORT_LCDen,LCDen -----> Enable high cbi PORT_LCDd7,LCDd7-------> Bit LCDd7 löschen ??? sbrc tmp0,3
www.atmel.com/images/Atmel-0856-AVR-Instruction-Set-Manual.pdf - mit cbi wird ein bestimmtes Bit in einem Register gelöscht. - push und pop sind die beiden Befehle um etwas auf den Stack zu legen und von dort wieder abzuholen, benötigt man um z.B. ein Register kurzzeitig auszulagern weil es für andere Dinge gebraucht wird. - mit andi wird ein Vergleich mit einer Konstanten durchgeführt - mit rcall wird ein Unterprogramm mit Rücksprung aufgerufen, wenn dieses wieder mit ret beeendet wird wird das Programm den nächsten Befehl unterhalb des rcall Befehls ausführen. - breq der nächste Befehl wird übersprungen wenn das Ergebnis des Vergleichs identisch ist. - sbi ist das Gegenteil von CBI - sbrc überspringt den nächsten Befehl wenn ein bestimmtes Bit im Register gelöscht = 0 ist.
Die einzelne Befehle verstehe ich schon aber nicht im Zusammenhang
Das kann doch garnicht sein. Es ist doch alles in der einzig klaren Sprache formuliert! Im Ernst, so ist es eben, wenn jemand unter Doku versteht, jedes Legosteinchen zu erklären. Richtig wäre zu schreiben, warum man sie so übereinandergestapelt hat. Schön sind auch die Magic Numbers. Wehe wenn die Hardware die Bits änderst sortiert.
Sorry , ich habe mich falsch ausgedruckt. Ich meine im 1) warum andi tmp0,$FC (0b11111100) Wie kommt man dadrauf ...und pc+2 2) warum wird der Bit LCDd7 (verbunden mit PB7) gelöscht und dann soll bei gelöschtem Bit3 (PB2??) der nächste Befehl übersprungen werden? 1) LCDcmd: ; command byte cbi PORT_LCDrs,LCDrs push tmp0 rcall LCDb pop tmp0 andi tmp0,$FC -------->?? breq pc+2------------------> pc+2?? ret 2) LCDn: ; nibble sbi PORT_LCDen,LCDen -----> Enable high cbi PORT_LCDd7,LCDd7-------> Bit LCDd7 löschen ??? sbrc tmp0,3
1 | andi tmp0,$FC ; displayclear oder returnhome ? |
2 | breq pc+2 |
3 | ret |
4 | rjmp wait2ms ; > 1.64 ms |
Es wird geprüft, ob die Bits 2..7 im LCD-Befehlswort auf L gesetzt sind. Wenn ja, so muss es sich um einen der LCD-Befehle 'display clear' oder 'return home' handeln, und diese haben eine verlängerte Bearbeitungszeit von 1.64 ms (so zumindest bei meinen LCDs). Alle anderen Befehle sind schneller als 50 us, und sie haben in den Bits 2..7 mindestens ein H. Das Ganze soll nur etwas Laufzeit sparen. ----------
1 | cbi PORT_LCDd7,LCDd7 |
2 | sbrc tmp0,3 |
3 | sbi PORT_LCDd7,LCDd7 |
So muss das gruppiert werden! Der Ausgangspin LCDd7 wird gemaess bit 3 von tmp0 gesetzt. Hier gibt es auch andere und vielleich auch bessere Lösungen, aber es funktioniert. ---------- breq pc+2 springt einfach zwei Worte weiter. Schreiben Sie stattdessen:
1 | breq hop |
2 | ret |
3 | hop: |
4 | rjmp wait2ms ; > 1.64 ms |
Tut mir leid für die nervige Fragen... Ich weiß, dass der Quellcode für selbstverständlich ist und nicht schwer zu verstehen. Aber ich kann dieser immernoch nicht nachvollziehen.. S. Landolt schrieb: > andi tmp0,$FC ; displayclear oder returnhome ? > breq pc+2 > ret > rjmp wait2ms ; > 1.64 ms andi tmp0, 0b11111100 sind diese die Bits von Port A gemeint, also: bit7: 1-> PA7 (PB7) bit6: 1-> PA6 (PB6) bit5: 1-> PA5 (E) bit4: 1-> PA4 (RS) bit3: 1-> PA3 NICHT VERBUNDEN bit2: 1-> PA2 (PB5) bit1: 0-> PA1 (PB4) bit0: 0-> PA0 NICHT VERBUNDEN müsste dann nicht andi tmp0, 0b11110110 sein??? S. Landolt schrieb: > cbi PORT_LCDd7,LCDd7 > sbrc tmp0,3 > sbi PORT_LCDd7,LCDd7 > So muss das gruppiert werden! Der Ausgangspin LCDd7 wird gemaess bit 3 > von tmp0 gesetzt. Hier gibt es auch andere und vielleich auch bessere > Lösungen, aber es funktioniert. sbrc tmp0,3 --Bit 3 welches Bit ist damit gemeint??
Am einfachsten läßt sich ein LCD in C programmieren. Vor allem kann man die 6 LCD-Pins beliebig zuordnen, wie es fürs Layout und die Sonderfunktionen am besten paßt: http://www.avrfreaks.net/forum/tutc-lcd-tutorial-1001
> andi tmp0,$FC Das hat erstmal nichts mit einem Port zu tun, in dem Register tmp0 steht das Argument, das an die Routine LCDcmd übergeben wurde, es handelt sich also um das Kommando, d.h. das Befehlswort für das LCD. Die Verteilung der Register-bits auf die Port-pins erfolgt erst in den Routinen LCDb bzw. LCDn. > sbrc tmp0,3 --Bit 3 welches Bit ist damit gemeint? Die Zählung geht von 0 bis 7, es ist also das viertniederste Bit, s.a. "AVR-Tutorial: IO-Grundlagen", allgemein und umfassend das ganze "AVR-Tutorial". Näheres zum Befehl sbrc finden Sie in "Atmel AVR 8-bit Instruction Set, Instruction Set Manual".
Mich wuerde interessieren ob wenigstens erstmal die "Kaestchen" eines uninitialisieren Displays zu sehen sind. In einem anderen Forum hat der TO vorhin den gleichen Schaltplan mit dem fehlerhaften Kontrastanschluss gepostet. Gruss Asko.
AmAnfang schrieb: > Tut mir leid für die nervige Fragen... Mal zur Klarstellung: (1) Hast du Erfahrung mit µC und Assembler und bekommst nur diesmal diese Routine nicht zum laufen? (2) Hast du keine Erfahrung mit µC und Assembler und willst nur mal fix das LCD zur Anzeige überreden? (3) Interrestierst du dich für (Assembler)programmierung auf dem µC und dachtest, das wäre doch genau der richtige Einstieg?
Asko B. schrieb: > In einem anderen Forum hat der TO vorhin den gleichen Schaltplan > mit dem fehlerhaften Kontrastanschluss gepostet. Die Kontrastspannung muß natürlich stimmen. - manche LCD erlauben direkt GND - manche LCD brauchen irgendwas zwischen GND und VCC - manche LCD brauchen eine negative Spannung - manche LCD stellen die Spannung über Steuerregister ein. Es ist also generell ein Fehler, das konkrete LCD-Datenblatt nicht zu lesen!
Kontrast ist eingestellt, jetzt tut sich was... Poti hatte ich mit VCC und GND verbunden.Ich habe die Verbindung zum GND weg gemacht....
Ralf G. schrieb: > AmAnfang schrieb: >> Tut mir leid für die nervige Fragen... > > Mal zur Klarstellung: > (1) Hast du Erfahrung mit µC und Assembler und bekommst nur diesmal > diese Routine nicht zum laufen? > (2) Hast du keine Erfahrung mit µC und Assembler und willst nur mal fix > das LCD zur Anzeige überreden? > (3) Interrestierst du dich für (Assembler)programmierung auf dem µC und > dachtest, das wäre doch genau der richtige Einstieg? Ich habe bis jetzt keine Erfahrung mit mC und Assembler, ich interessiere mich sehr und möchte diese lernen...
AmAnfang schrieb: > Ich habe die Verbindung zum GND weg gemacht Was war dir an den hier mehrfach gezeigten Schaltbildern unklar? Das Poti soll mit VCC und GND verbunden sein und der Schleifer geht an Vo.
AmAnfang schrieb: > ich > interessiere mich sehr und möchte diese lernen... Auf die Antwort gibt's von mir volle Punktzahl. Ich würde dir jetzt empfehlen, das Display zur Seite zu legen und eine Nummer kleiner anzufangen: - mal 'ne LED ein- und ausschalten (erst im Simulator, dann mal was zusammenstöpseln) - LED blinken lassen (Zusatzfunktion: Schleife zur Verzögerung) Gehe dazu erstmal die Assembler-Referenz im AVR-Studio durch. Einfach Befehl für Befehl. Da sieht man schon, wie so ein Assembler überhaupt 'tickt'. Bei jedem Befehl ist auch ein Beispiel dabei. So kann man sich auf diese 'niedrige Ebene' gut einstellen. Wenn die obigen Aufgaben gelöst sind, ist die Ansteuerung eines LCD nur noch eine Fleißaufgabe. Reine Schreibarbeit.
:
Bearbeitet durch User
Andere Länder, andere Sitten. So habe ich es gelöst. Schau mal rein. Du kannst hierbei das Display quer über alle Ports verstreuen. Um es bei Dir zum laufen zu bringen: 1. Erste Zeile anpassen 2. Block ab Zeile 35 Anpassen 3. Block ab Zeile 114 anpassen (Einiges kann für diesen Zweck entfallen) Das Programm startet immer wieder von neuem. Gruß Jobst
Jobst M. schrieb: > So habe ich es gelöst. Schau mal rein. Und sei dir im Klaren: das ist ein wilder Hack!
1 | ; ================================ |
2 | ; Warten, Zeit verbraten ... |
3 | ; ================================ |
4 | |
5 | WAIT_1s: |
6 | CALL WAIT_100ms |
7 | CALL WAIT_100ms |
8 | : |
9 | : |
10 | CALL WAIT_1us |
11 | CALL WAIT_1us |
12 | CALL WAIT_1us |
13 | WAIT_1us: |
14 | NOP |
15 | NOP |
16 | NOP |
17 | NOP |
18 | NOP |
19 | NOP |
20 | NOP |
21 | RET ; 8 MHz |
Aber das müsste sowieso auch noch an das 1 MHz Taktfrequenz angepasst werden. Sonst läuft der Code mit 8 MHz und aktiver CLKDIV8 8 mal zu langsam...
:
Bearbeitet durch Moderator
Lothar M. schrieb: > Und sei dir im Klaren: das ist ein wilder Hack! Naja, ich würde damit keine Uhr bauen, aber für Timings ist es ideal und einfach. Als wilden Hack würde ich es nicht bezeichnen! Wilde Hacks sind andere Dinge. Dies finde ich relativ einfach durchschaubar. Und: Es benötigt kein zusätzliches Register. Gruß Jobst
Jobst M. schrieb: > Dies finde ich relativ einfach durchschaubar. Ich auch. Aber ich kenne den AVR Assembler schon von Anfang an... > Und: Es benötigt kein zusätzliches Register. Zudem sind die Funktionen reentrant, weil sie ihre Zeit auf dem Stack abhandeln. Die Funktion an sich ist ok, aber wenn jede Funktion mit multiplen Einsprungpunkten daherkäme, dann wäre das der Beginn vom Chaos. Aus diesem Grund: es ist ein wilder Hack.
:
Bearbeitet durch Moderator
Jobst M. schrieb: > Andere Länder, andere Sitten. > So habe ich es gelöst. Schau mal rein. call und jmp auf einem ATmega48 - wie macht man das? Und 'AmAnfang' arbeitet mit einem ATtiny26, der kennt z.B. nur SP.
S. Landolt schrieb: > Jobst M. schrieb: >> Andere Länder, andere Sitten. >> So habe ich es gelöst. Schau mal rein. > > call und jmp auf einem ATmega48 - wie macht man das? > Und 'AmAnfang' arbeitet mit einem ATtiny26, der kennt z.B. nur SP. Man läst den GCC die Funktionen
1 | void _delay_ms (double __ms) |
2 | Void _delay_us (double __us) |
in Maschinen-Code des gewählten AVR umsetzen, hat F_CPU auf den richtigen Wert gesetzt und bekommt sein Delay in der für den Takt möglichen Auflösung korrekt umgesetzt. So einfach. Dann kann man auch den Rest von Fleury übernehmen. Will man wissen wie das geht, dann kann man die .lls Datei anschauen. Man muß aber nicht.
Hallo, so ich saß fast die ganze Nacht dran um diesen Codeteil zu verstehen. sbi PORT_LCDen,LCDen cbi PORT_LCDd7,LCDd7 ;Bit 7 löschen sbrc tmp0,3------> Bit3 ; Den nächsten Befehl überspringen wenn bit3=0 sbi PORT_LCDd7,LCDd7 ;Bit 7 setzen cbi PORT_LCDd6,LCDd6 ; Bit 6 löschen sbrc tmp0,2------->Bit2 ;den nächsten Befehl überspringen wenn bit2=0 sbi PORT_LCDd6,LCDd6 ;Bit sechs setzen cbi PORT_LCDd5,LCDd5 sbrc tmp0,1--------------------------->Bit1 sbi PORT_LCDd5,LCDd5 cbi PORT_LCDd4,LCDd4 sbrc tmp0,0--------------------------->Bit0 sbi PORT_LCDd4,LCDd4 cbi PORT_LCDen,LCDen S. Landolt schrieb: >> sbrc tmp0,3 --Bit 3 welches Bit ist damit gemeint? > Die Zählung geht von 0 bis 7, es ist also das viertniederste Bit was heißt es ist vierniederste Wert? Wie komme ich auf Bit3, Bit 2, Bit 0?? Ich habe mir auch die Seiten zur Bitmanipulation gelesen und viel gegoogelt...
Lothar Miller schrieb: > Funktion mit multiplen Einsprungpunkten > Beginn vom Chaos ... wilder Hack Sie müssen nur die Perspektive ändern. Es handelt sich nicht um eine Funktion mit den Einsprungpunkten WAIT_10us und WAIT_1us, sondern um zwei Funktionen. Es wird lediglich am Ende von WAIT_10us das call WAIT_1us ret ersetzt durch jmp WAIT_1us . Der Unvorsichtige löscht diese Zeile komplett, da an dieser Stelle unnötig, der Vorsichtige wird sie lediglich auskommentieren.
an AmAnfang: Meine pädagogischen Fähigkeiten sind allenfalls rudimentär - es tut mir wirklich leid, ich kann Ihnen nicht weiterhelfen. Vielleicht wäre es das Beste, Sie benutzten mein Testprogramm wirklich nur dazu, Ihre Hardware zum Laufen zu bringen.
AmAnfang schrieb: > was heißt es ist vierniederste Wert? Wie komme ich auf Bit3, Bit 2, Bit > 0?? Ich habe mir auch die Seiten zur Bitmanipulation gelesen und viel > gegoogelt..
1 | viertniederste Bit |
2 | | |
3 | | |
4 | V |
5 | |
6 | Zählweise (Normalo): 8 7 6 5 4 3 2 1 |
7 | 8 Bit: 0 0 0 0 0 0 0 0 |
8 | in der Informatik: Bit7 Bit6 Bit5 Bit4 Bit3 Bit2 Bit1 Bit0 |
gell
:
Bearbeitet durch User
> in der Informatik: Bit7 Bit6 Bit5 Bit4 Bit3 Bit2 Bit1 Bit0
Aber nicht weil die Informatiker spinnen, sondern wegen:
1 | Bit7 Bit6 Bit5 Bit4 Bit3 Bit2 Bit1 Bit0 |
2 | Wert: 128 64 32 16 8 4 2 1 |
3 | oder 2^7 2^6 2^5 2^4 2^3 2^2 2^1 2^0 |
:
Bearbeitet durch Moderator
S. Landolt schrieb: > call und jmp auf einem ATmega48 - wie macht man das? In dem man den richtigen Kompiler benutzt, der selbst entscheiden kann, was an dieser Stelle ausreicht. (gavrasm) Gruß Jobst
> Ändere deine Schaltung so dass die LCD-Datenleitungen DB4 bis DB7 am > Atmel auch genau an den Portpins 4 bis 7 hängen. RS und E kannst du dann > an die unteren Portpins 0-3 hängen. > > Wurde schon gesagt: Das Kontrastpoti muss an 5V und Masse angeschlossen > sein. Mittenabgriff dann ans LCD. So Hab die Schaltung und dementsprechend den Code verändert ... Poti mit Mc GND und VCC verbunden.. Das LCD leuchtet und wenn ich am poti etwas ändere dann sind auch schwarze Balken zu sehen.. Jetzt muss ich nur noch schaffen am LCD eine Buchstabe auszugeben....
Äh Das
1 | ; dreimal hintereinander senden |
2 | |
3 | ldi mp1, 0b00000011 |
4 | out lcd_port,mp1 |
wird aber nichts. Du sollst an den Datenleitungen des LCD eine 0x3 anlegen. Deine Datenleitungen zum LCD liegen aber nicht an den Bits 0 bis 3. Die liegen an den Bits 4 bis 7. Solange du an dieser Stelle noch direkt auf den Port ausgeben musst, bist du noch nicht davon befreit, das Umdenken von Portpins auf die Leitungen zum LCD vergessen zu können. Erst später, wenn du das LCD dann schon im 4 Bit Modus hast, bist du davon befreit,
1 | ; Funktionen setzen |
2 | ;DL=0-->4-Bit-Schnittstelle |
3 | ;N=1--->zwei Zeilen |
4 | ;F=0--->5x8 Matrix |
5 | |
6 | ldi mp1,0b00101000 |
7 | rcall LCD_command |
weil die Routine 'LCD_command' darüber Bescheid weiss und die entsprechende Verschiebung auf die richtigen Pins durchführt.
:
Bearbeitet durch User
Dein ganzer Programmaufbau geht so gar nicht. Kommt mir das nur so vor oder ist dir nicht klar, dass sich der Prozessor nicht die Anweisungen in der richtigen Reihenfolge zusammensucht sondern die Anweisungen stur von oben nach unten abarbeitet, bis er entweder auf einen RJMP oder einen RCALL stösst, der dann ganz einfach an einer anderen Stelle weiter macht? D.h. dein Aufbau wird im Normalfall zb so sein, (solange keine Interrupts im Spiel sind)
1 | ..... Stackpointer initialisieren |
2 | ..... Initialisierungen wie zb Port auf Eingang oder Ausgang schalten |
3 | |
4 | rcall LCD_Init |
5 | |
6 | main: |
7 | .... Logik der Hauptschleife |
8 | rjmp main |
9 | |
10 | ; hier dann die Unterprogramme wie zb |
11 | LCD_Init: |
12 | ... code für LCD_Init |
13 | |
14 | ret ; und zurück zum Aufrufer |
15 | |
16 | ; nächstes Unterprogramm |
17 | LCD_clear: |
18 | ... Code für LCD_clear |
19 | ret ; und zurück woher du gekommen bist |
20 | |
21 | ..... |
Du kannst nicht einfach den Code für LCD_Init an der Stelle einsetzen, an der der rcall steht. Denn wohin soll denn der ret am Ende zurückkehren, wenn es keinen rcall gab? UNd den ret zu entfernen ist auch keine Lösung, wenn du dann auch noch die LCD_Clear mit nach vorne kopiert hast. Denn dann läuft der Prozessor nach dem LCD_Init Teil ganz einfach in den LCD_clear Teil rein und spätestens dort steht dann ein ret. Für den es keinen rcall gab. Dem Prozessor sind deine Labels wurscht! Der sieht die nicht mal. Die sind nur dazu da, damit du dich als Programmierer auf Codestellen beziehen kannst.
:
Bearbeitet durch User
Muß man wärend der Initialisierung nicht so tun, als ob man 8-Bit IF benutzt? LCD_command() zerteilt aber auf 2 Nibbles. Was aktuell ausgegeben wird ist natürlich auch falsch. Die Datenbits sind 4..7, also muß 00110000 (bzw. 00100000) ausgegeben werden. Zudem kann man das etwas kürzen:
1 | ; dreimal hintereinander senden |
2 | |
3 | ldi mp1, 0b00110000 |
4 | out lcd_port,mp1 |
5 | |
6 | rcall lcd_enable ;1 |
7 | rcall delay5ms |
8 | |
9 | rcall lcd_enable ;2 |
10 | rcall delay5ms |
11 | |
12 | rcall lcd_enable ;3 |
13 | rcall delay5ms |
14 | |
15 | ;4-Bit-Modus einstellen |
:
Bearbeitet durch User
Ich würde mich ganz genau an diese Beschreibung aus dem Tutorial halten, denn die funktioniert. Es kommt auch auf die Zeiten an. Die darf man über- aber nicht unterschreiten! --------- Nach dem Anlegen der Betriebsspannung muss eine Zeit von mindestens ca. 15ms gewartet werden, um dem LCD-Kontroller Zeit für seine eigene Initialisierung zu geben $3 ins Steuerregister schreiben (RS = 0) Mindestens 5ms warten $3 ins Steuerregister schreiben (RS = 0) Mindestens 100µs warten $3 ins Steuerregister schreiben (RS = 0) $2 ins Steuerregister schreiben (RS = 0), dadurch wird auf 4 Bit Daten umgestellt Ab jetzt muss für die Übertragung eines Bytes jeweils zuerst das höherwertige Nibble und dann das niederwertige Nibble übertragen werden, wie oben beschrieben Mit dem Konfigurier-Befehl $20 das Display konfigurieren (4-Bit, 1 oder 2 Zeilen, 5x7 Format) Mit den restlichen Konfigurierbefehlen die Konfiguration vervollständigen: Display ein/aus, Cursor ein/aus, etc. --------
:
Bearbeitet durch User
Nur mal eine Zwischenfrage an AmAnfang. Benutzt du das AVR-Studio? Kennst du den Simulator? Zusätzlich mit der Funktion sich die Registerinhalte angucken zu können hat mir das beim Assemblerverstehen sehr geholfen.
ohje ich habe einiges nachzuholen ... Carl D. schrieb: > Muß man wärend der Initialisierung nicht so tun, als ob man 8-Bit > IF > benutzt? > LCD_command() zerteilt aber auf 2 Nibbles. > Was aktuell ausgegeben wird ist natürlich auch falsch. Die Datenbits > sind 4..7, also muß 00110000 (bzw. 00100000) ausgegeben werden. > > Zudem kann man das etwas kürzen:; dreimal hintereinander senden > > ldi mp1, 0b00110000 > out lcd_port,mp1 > > rcall lcd_enable ;1 > rcall delay5ms > > rcall lcd_enable ;2 > rcall delay5ms > > rcall lcd_enable ;3 > rcall delay5ms > > ;4-Bit-Modus einstellen Ich habe mich an dem Datenblatt gehalten und da steht es drin, wie im Tutorial: ldi temp1, 0b00000011 . Wobei ich nachgefragt habe wie man dadrauf kommt, mir wurde nur gesagt das es sich um 4 bit Modus handelt und ich diese so übernehmen soll.... Warum steht da jetzt 0b00110000 ? Was passiert da? J. T. schrieb: > Nur mal eine Zwischenfrage an AmAnfang. > Benutzt du das AVR-Studio? Ja ich benutze AVR-Studio..Ich verwende meistens nur Build um die Fehler zu finden und diese zu korrigieren.
AmAnfang schrieb: > Ja ich benutze AVR-Studio..Ich verwende meistens nur Build um die > Fehler zu finden und diese zu korrigieren. Dann kann ich dir nur ans Herz legen, mal den Simulator zu benutzen, und dabei die Register mitanzuschauen. Du kannst dich dann Asm-Befehl für Asm-Befehl durchklicken, und exakt sehen, was der Prozessor tut, wie lang er dafür braucht usw. Das hat mir wie gesagt sehr geholfen, einige meiner Denkfehler aufzudenken. Der Prozessor tut nämlich exakt das was du ihm sagst, oft sagt man ihm leider nur nicht das was man will ;-) MfG Chaos
AmAnfang schrieb: > Warum steht da jetzt 0b00110000 ? Was passiert da? Genau das was beschrieben wird. Die Datenleitungen D4 bis D7 des LCD bekommen die Bitwerte 0011 zu sehen. Im Tutoral wird deswegen 00000011 ausgegeben, weil die Verdrahtung so aussieht
1 | Prozessor |
2 | |
3 | Pin7 Pin6 Pin5 Pin4 Pin3 Pin2 Pin1 Pin0 |
4 | ----o----o----o----o----o----o----o----o-------- |
5 | | | | | |
6 | | | | | |
7 | +--+ | | | |
8 | | +--+ | | |
9 | | | +--+ | |
10 | | | | +--+ |
11 | | | | | |
12 | ------*----*----*----*----*----*----*----*----- |
13 | D7 D6 D5 D4 D3 D2 D1 D0 |
14 | | | |
15 | +-- die hier -+ |
16 | sind implizit 0 |
17 | LCD |
Damit also das LCD an seinen 8 Eingängen das Bitmuster 00110000 zu sehen bekommt, musst dam Prozessor welches Bitmuster auf die Portpins legen? Genau: da muss xxxx0011 ausgegeben werden (x bedeutet: spielt keine Rolle, weil es sowieso nicht am LCD ankommt. Zumindest nicht an den Datenleitungen. Aber es gibt ja auch noch die Steuerleitungen) Nur: Du hast nicht diese Verdrahtung! Deine Verdrahtung sieht (laut Kommentar) so aus
1 | Prozessor |
2 | |
3 | Pin7 Pin6 Pin5 Pin4 Pin3 Pin2 Pin1 Pin0 |
4 | ----o----o----o----o----o----o----o----o-------- |
5 | | | | | |
6 | | | | | |
7 | +--+ | | | |
8 | | +--+ | | |
9 | | | +--+ | |
10 | | | | +--+ |
11 | | | | | |
12 | ------*----*----*----*----*----*----*----*----- |
13 | D7 D6 D5 D4 D3 D2 D1 D0 |
14 | | | |
15 | +-- die hier -+ |
16 | sind implizit 0 |
17 | |
18 | LCD |
Wieder die Fragestellung: Damit das LCD an seinen Eingängen das Bitmuster 00110000 zu Gesicht bekommt, musst da daher an den Prozessor-Portpins welches Bitmuster ausgeben? Genau. Mit dieser Verdrahtung musst du an den Portpins 0011xxxx ausgeben, damit am LCD des gewünschte Bitmuster entsteht. Wichtig ist, dass das LCD an seinen Eingängen das Bitmuster 00110000 zu Gesicht bekommt. Was du dazu an den Portpins ausgeben musst, hängt davon ab, wie deine Verdrahtung aussieht. Das Bitmuster 00110000 ist dir vorgegeben, das kannst du nicht ändern. Das LCD will das genau so sehen und nicht anders. Also musst du im Prozessor entsprechend deiner Verdrahtung gegensteuern. hier wird das Pferd von hinten aufgezäumt. Ausgangspunkt ist, wie das LCD diese ersten Kommandos präsentiert haben will, welche Bitwerte es haben will. Durch Rückverfolgung der Leitungen ergibt sich daraus was du an den Prozessorportpins einstellen musst, damit sich das auch genau so und nicht anders ergibt.
:
Bearbeitet durch User
> Warum steht da jetzt 0b00110000 ? Was passiert da? Du beschreibst einen 8-Bit Port deines AVR. An Bit4..7 hängen die LCD-Datenbits 4..7 und das sind genau die, die wir hier brauchen. In dem unteren 4 Bits des Ports sind RS und E, die müssen zuerst mal eh 0 sein. E wird von deiner Unterroutine ge-toggled. Zuerst tut man so als hätte man 8-Bit Mode. Das geht für die Initialisierung auch mit 4-Bit Schnittstelle, da dieser Befehl die unteren 4 Bit (zuerst mal) nicht braucht. 3 mal gibt man die 0x30 aus, weil man dann aus jedem möglichen Zustand den 8-Bit Modus erreicht. Wenn mal nämlich den 4-Bit-Mode benutzt und im Betrieb den μC resettet, dann könnte das LCD gerade auf das 2.Nibble warten und alle weiteren Kommandos falsch verstehen. Ist man sicher bei 8-Bit-Mode, dann kann man getschillt auf 4-Bit schalten und danach auch die unteren 4 Bits übertragen. Es geht natürlich auch einfacher, wenn man davon ausgeht, das das LCD nach den Einschalten im 8-Bit-Mode arbeitet. Das sind dann aber die Initialisierungen, die nur nach dem Einschalten funktionieren.
Danke. Ich werde versuchen die Ratschläge umzusetzen .. Die Antworten sind für mich Goldwert...
OT: Ich sehe immer diese bombastische ASCII-Art... womit macht ihr die? Doch wohl hoffentlich nicht von Hand... ???
Tcf K. schrieb: > OT: Ich sehe immer diese bombastische ASCII-Art... womit macht ihr die? > Doch wohl hoffentlich nicht von Hand... ??? na sicher doch.
Tcf K. schrieb: > OT: Ich sehe immer diese bombastische ASCII-Art... womit macht ihr die? > Doch wohl hoffentlich nicht von Hand... ??? Dafür soll es auch Tools geben. Googlestichwort "ASCII-Schaltplangenerator" Ich selbst hab sowas aber noch nicht benutzt. Ich schmeiß für Schaltplan meist doch Spice an und mach nen Screenshot
Karl H. schrieb: > +-- die hier -+ > sind implizit 0 Sie sind von sich aus eigentlich 1, es sei denn, man legt sie auf GND. Lt. Datenblättern (HD44780, SPLC780, KS0066, ST7066 ...) sollen sie im 4-Bit-Mode nicht benutzt werden. (Am deutlichsten steht's beim KS0066: In 4-Bit bus mode, open these pins.) Durch die internen Pullups wird die Stromaufnahme verdoppelt, wenn man sie an GND legt. Mit 1en an diesen Pins funktioniert die Initialisierung genau so gut! ;-) Gruß Jobst
Jobst M. schrieb: > Karl H. schrieb: >> +-- die hier -+ >> sind implizit 0 > > Sie sind von sich aus eigentlich 1, es sei denn, man legt sie auf GND. Danke für die Korrektur.
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.