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 ...
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
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:_LCDAmEnde 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?
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 :(
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?
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.
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
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, ...
> 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.
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?
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.
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.
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
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:
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!
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.
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
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.
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
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....
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.
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.
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:
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.
--------
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.
> 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.
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.