Die Datei „lcd-routines.asm“ vom Ende des AVR-Tutorial: LCD habe ich
(hoffentlich) verbessert und um folgendes erweitert:
* sämtliche veränderte Register außer SREG werden
gerettet (einschließlich Parameter)
* unbenutzte Pins am DB-Port werden nicht beeinflusst
* Anschluss von DB4..7 wahlweise auch an Pins 4..7 (statt 0..3)
* lcd_data und lcd_command zu lcd_write zusammengefasst
* Busy-Flag-Abfrage (optional)
Da ich momentan keine Möglichkeit habe, den Code zu testen, würde ich
mich freuen, wenn ihn jemand real auf einem ATmega8 + LCD ausprobieren
könnte.
Insbesondere bin ich mir unsicher, ob die Initialisierungsroutine mit
der Abfrage des Busy-Flags so funktioniert.
In der Hoffnung auf Rückmeldungen, viele Grüße
... warum "verändert / verbessert" man etwas, wenn man keine Möglichkeit
hat, seine Änderungen zu testen und veröffentlicht dieses dann auch noch
ungetestet?
> ... keine Möglichkeit habe, den Code zu testen ...
Dann waren Sie voreilig.
Aber doch zumindest zum Assemblieren - z.B. wenn der AVR mit mehr als
15.36 MHz läuft ...
Assembly failed 8 errors 8 warnings
C:\Users\***\Documents\Test_1.asm(40): warning: Use of undefined or
forward referenced symbol 'PORTD' in .equ/.set
C:\Users\***\Documents\Test_1.asm(50): error: Undefined symbol: PORTB
und so geht das weiter.
Das include file fürs Target in use fehlt auch.
(Target hier ausgetestet der AtMega8515, der gute alte...)
Die Busyabfrage ist vom Prinzip her richtig beim 4-Bit Modus.
Zweimal enable. Keine Ausgaberoutine nach dem zweiten enable.
Aber "Verkapselung" ist besser, wenn man mit I2C bzw. TWI noch arbeiten
möchte.
ciao
gustav
Die sehe ich bei Dir nicht.
S. Landolt schrieb:>> ... keine Möglichkeit habe, den Code zu testen ...> Dann waren Sie voreilig.
Soweit ich das sehe, hat er den code noch nicht (im Tutorial)
hochgeladen.
Karl B. schrieb:> (Target hier ausgetestet der AtMega8515, der gute alte...)
Wobei das Tutorial eigentlich für den ATmega8 ist.
Karl B. schrieb:> Assembly failed 8 errors 8 warnings> C:\Users\***\Documents\Test_1.asm(40): warning: Use of undefined or> forward referenced symbol 'PORTD' in .equ/.set> C:\Users\***\Documents\Test_1.asm(50): error: Undefined symbol: PORTB> und so geht das weiter.
Der Code ist als Library zu verstehen – also bin ich natürlich davon
ausgegangen, dass die Datei von einer anderen eingebunden wird, die die
LCD-Routinen wie im Tutorial beschrieben aufruft (also z. B.
lcd_flash_string) und selbstverständlich auch eine Include-Direktive für
"m8def.inc" bzw. einen anderen Controller enthält. Bei mir gab es keine
Fehlermeldungen beim Assemblieren, weil ich die Datei in einem
Microchip-Studio-Projekt für den ATmega8 habe, sodass "m8def.inc"
automatisch eingebunden wird.
Karl B. schrieb:> Aber "Verkapselung" ist besser, wenn man mit I2C bzw. TWI noch arbeiten> möchte.
Das verstehe ich nicht, was meinst du mit Verkapselung?
Alexander S. schrieb:> Welche genau, diese> https://www.mikrocontroller.net/wikifiles/9/96/Lcd-routines.asm ?
Ja, genau diese.
Alexander S. schrieb:> Die> enthält zu Beginn auch> ;sendet ein Datenbyte an das LCD> lcd_data:> ; sendet einen Befehl an das LCD> lcd_command:> Die sehe ich bei Dir nicht.
Diese beiden Routinen habe ich, wie eingangs schon geschrieben, zu
„lcd_write“ mit dem zusätzlichen Parameter temp0 zusammengefasst. Ist
temp0==0, wird temp1 als Befehl gesendet, bei temp0==1 als Datenbyte.
Motivation dazu war es, Code-Duplikation zu vermeiden und auch Flash zu
sparen, da die beiden originalen Routinen ja genau dasselbe machen, wenn
man vom Setzen des RS-Bits in der einen absieht.
Alexander S. schrieb:> S. Landolt schrieb:>>> ... keine Möglichkeit habe, den Code zu testen ...>> Dann waren Sie voreilig.>> Soweit ich das sehe, hat er den code noch nicht (im Tutorial)> hochgeladen.
Habe ich natürlich noch nicht. Deshalb ja hier dieser Thread, in der
Hoffnung, dass jemand den Code ausprobieren könnte.
Johannes F. schrieb:> Alexander S. schrieb:>> S. Landolt schrieb:>>>> ... keine Möglichkeit habe, den Code zu testen ...>>> Dann waren Sie voreilig.>>>> Soweit ich das sehe, hat er den code noch nicht (im Tutorial)>> hochgeladen.>> Habe ich natürlich noch nicht ...
Hat damit nichts zu tun. Also ich würde warten, bis ich eine
Testmöglichkeit habe (und dann gründlich testen), bevor ich hier im
Forum Halbfertiges zur Diskussion stelle.
Ich sag mal, die Zeiten, sich noch mit Assembler abquälen zu müssen,
sind schon einige Jahrzehnte vorbei.
Der AVR-Assembler ist obendrein eine Sackgasse, da er keine linkbaren
Objekte erzeugt. D.h. man kann nicht später Assembler und C zusammen
linken, sondern nur den Assemblercode komplett wegschmeißen.
Man müßte also schon alles in GNU-Assembler schreiben (ist im AVR-GCC
enthalten).
> mit Assembler abquälen zu müssen
"quälen", "müssen"? Schon wieder diese unsägliche Stichelei.
Und überhaupt: es gibt zum Beispiel Menschen, die sich noch immer mit
Dampflokomotiven "abquälen" - und eine Menge Spaß dabei haben!
S. Landolt schrieb:> z.B. wenn der AVR mit mehr als> 15.36 MHz läuft ...
Dass man dann die Delay-Routinen anpassen muss, steht bereits im
AVR-Tutorial: LCD, aus dem diese ohne Änderung übernommen wurden.
BTW, wie kommt man auf 15,3*6* MHz? Bei mir sind es
XTAL = 255 · 3 · 1.000.000 / 50 = 15.300.000 (Hz).
Peter D. schrieb:> Der AVR-Assembler ist obendrein eine Sackgasse, da er keine linkbaren> Objekte erzeugt. D.h. man kann nicht später Assembler und C zusammen> linken, sondern nur den Assemblercode komplett wegschmeißen.> Man müßte also schon alles in GNU-Assembler schreiben (ist im AVR-GCC> enthalten).
Welche Unterschiede zwischen Atmel-AVR-Assembler und GNU-Assembler
müsste man denn dann beachten?
Also die Zeiten, wo man ganze „Anwendungen“ in Assembler schreibt sind
im Prinzip seit es C-Compiler gibt vorbei. Bei zeitkritischen
Anwendungen sieht das auch heute noch anders aus.
Dabei ist es in der Regel allerdings Usus Assembler mit C zu mischen.
Bei GCC oder XC8 am besten direkt initial, oder als library projekt
(GNU) zum späteren Einbinden. Dann muss man auch nicht seine Register
retten unter der Voraussetzung dass man seinen Compiler kennt und
versteht. Es gibt bei GCC z.B. eine Menge Register die beim Verfahren "C
call’s Assembly" frei benutzt werden können. Es gibt für die
unterschiedlichsten Platformen und Compiler in der Regel von allen
Herstellern entsprechende Apnotes zum Thema „mixing c and assembly“
Wenn man den C-Compiler allerdings eines Besseren belehren möchte, dann
sollte man auch ein guter Assemblerprogramierer sein. Ein guter
Assemblerprogrammierer ist aber mindestens in der Lage seinen Code
selbst zu testen. Wer das nicht kann bleibt aber tatsächlich besser bei
C. LCD Displays sind im übrigen nicht Zeitkritisch. Hier macht es
höchstens Sinn auf Codegröße zu optimieren. Das sieht allerdings anders
aus.
Was ich nicht verstehe:
Der ATmega8 ist 20 Jahre alt, das Display ist noch viel älter. In
Assembler programmiert heute kaum noch jemand. Der Code ist seit vielen
Jahren bekannt und erfüllt seinen Zweck.
Wie kommt man auf die Idee, diesen Code optimieren zu wollen, obwohl man
dazu nicht mal einen konkreten Anwendungsfall hat?
Verschlimmbessern nennt man das.
Johannes F. schrieb:> Dass man dann die Delay-Routinen anpassen muss
Da kann der AVR-GCC punkten. Da muß man nur die Konstante F_CPU in Hz
definieren und alle Delays stimmen.
Dem Macro _delay_us() wird einfach die Zeit in µs als Argument
übergeben.
Johannes F. schrieb:> * lcd_data und lcd_command zu lcd_write zusammengefasst
Nun ja, es ist ein Tutorial, also für Anfänger. Als solches sollte der
Code leicht verständlich sein. Die bisherigen getrennten Routinen für
Data und Command finde ich da weit besser verständlich als deine Version
mit den ganzen ifs und elses. Und so viel Flash-Speicher brauchen die
beiden Routinen nun auch nicht.
Ein ganzes Register nur für das Data/Command Bit zu verschwenden halte
ich auch für falsch. Register sind in Assembler immer Mangelware. Warum
kein Flag wie das T-Flag nutzen?
Ich habe nun schon einige Routinen für LCDs in ASM geschrieben und
benutze immer getrennte Data- und Command-Routinen da ich das
übersichtlicher und einfacher empfinde. Und das bischen mehr an Flash
fällt nicht ins Gewicht.
Johannes F. schrieb:> Karl B. schrieb:>> Aber "Verkapselung" ist besser, wenn man mit I2C bzw. TWI noch arbeiten>> möchte.>> Das verstehe ich nicht, was meinst du mit Verkapselung?
Tja,
die Frage hatte ich gestern Abend schon insgeheim erwartet.
Dabei hatte ich Dir schon eine Eselsbrücke gebaut. Dachte, Du würdest
auf den Köder anbeißen.
Offensichtlich sind Dir aber die Probleme bei der I2C LCD-Ansteuerung
mit den PCFs Expansion Moduls noch nicht über den Weg gelaufen.
Aber ich möchte hier niemanden im Regen stehen lassen:
Wie willst Du die Steuersignale RS, R/Wquer, Enable übertragen, wenn
keine "Drähte" dafür vorgesehen sind?
Eben.
Mit Verkapselung. Und diese bringt für "normale" Ansteuerung auch
Denkanstöße, die man zur Ökonomisierung des Codes eventuell verwenden
könnte.
Man nimmt den Vierbit-Modus und deklariert die
"Hardware"-Steuersignal-Pins als Bits im 8-Bit-Byte, das auch
sequenziell über TWI- oder I2C- (oder USI-) Routinen übertragen werden
kann.
Anbei der kommentierte ausgetestete Codeschnipsel für ein
SainSmart-4-Zeiler LCD mit dem Expansion Module.
ciao
gustav
Karl B. schrieb:> Anbei der kommentierte ausgetestete Codeschnipsel für ein> SainSmart-4-Zeiler LCD mit dem Expansion Module.
Und dann sind wir auch schon bei dem Problem, dass man in asm eben nicht
vernünftig kapseln und abstrahieren kann. Sinnvoll wäre hier die
Funktion des LCD-Controllers HD44780 von der Funktion des Interface
PCF8547 und von der Funktion des Transports I2C zu trennen, wie man das
etwa in C/C++ kann. Nur so entstehen wiederverwendbare Komponenten.
S. Landolt schrieb:>> mit Assembler abquälen zu müssen>> "quälen", "müssen"? Schon wieder diese unsägliche Stichelei.
Alter ego von "ttloop" auf Heise?
Wilhelm M. schrieb:> Nur so entstehen wiederverwendbare Komponenten.
...und leichte Portierbarkeit von einem Target zum anderen.
Vom AtTiny4313 zum ATMega32U2 zum Beispiel bei Programmen, die vom
Speicherbedarf und sonstigen Design her auf beiden µCs lauffähig wären.
Und auch sind, wenn man die Sache erst nachgearbeitet hat.
Bei C macht das ein halbwegs vernünftiger Compiler schon von sich aus,
ohne dass man so weit runter auf die Befehlsebene gehen müsste
Generell gesprochen:
Für didaktische Zwecke ist das Beispiel der LCD-Initialisierung im
Tutorial vielleicht ganz nützlich. Ich sehe da aber eigentlich keinen
essenziellen Verbesserungsbedarf. Die Idee des TO in allen Ehren, aber
mich hätte das als Absolut-Einsteiger erst einmal völlig aus der Spur
gebracht, weil wieder weitere Konstrukte, so was Ähnliches wie Makros
mit dem if und endif etc. pp. zusätzlich aufgedrückt werden.
Wenn ich schon mit ASM arbeite, dann so, dass die Befehle halbwegs
nachvollzogen werden können. Sonst wird das sehr schnell ein
unübersehbarer Wust an Spaghetticode. Ohne geremte Text-Kommentare geht
es so wie so nicht.
ciao
gustav
Karl B. schrieb:> Für didaktische Zwecke ist das Beispiel der LCD-Initialisierung im> Tutorial vielleicht ganz nützlich. Ich sehe da aber eigentlich keinen> essenziellen Verbesserungsbedarf.
Es gibt schon einige Unschönheiten in dem Quelltext des Tutorials, die
auch in Diskussion:AVR-Tutorial: LCD bereits vor vielen Jahren von
anderen angesprochen wurden:
In der Initialisierungsroutine ist das „Entry Mode Set“-Kommando
fehlerhaft (Dekrementierung statt Inkrementierung des Cursors), es
enthält eine unkommentierte Sicherung eines unbenutzten LCD-Port-Pins
(aber nicht des zweiten), einige Routinen retten Register, andere nicht
…
Karl B. schrieb:> Die Idee des TO in allen Ehren, aber> mich hätte das als Absolut-Einsteiger erst einmal völlig aus der Spur> gebracht, weil wieder weitere Konstrukte, so was Ähnliches wie Makros> mit dem if und endif etc. pp. zusätzlich aufgedrückt werden.
So schwierig zu verstehen sind If-Else-Konstrukte nun ja wohl nicht.
Wer die Flexibilität nicht braucht, kann sie auch wieder rausnehmen. Sie
erlauben halt das Anschließen an andere Pins bzw. das Benutzen oder
Nichtbenutzen des Busy-Flags, ohne verschiedene Versionen des
Quelltextes warten zu müssen.
Karl B. schrieb:> Ohne geremte Text-Kommentare geht> es so wie so nicht.
Was sind denn „geremte Text-Kommentare“?
Johannes F. schrieb:> Es gibt schon einige Unschönheiten in dem Quelltext des Tutorials, die> auch in Diskussion:AVR-Tutorial: LCD bereits vor vielen Jahren von> anderen angesprochen wurden:
Hi,
gib 'mal den Link an, wo das zugehörige asm-File zu sehen ist.
Sonst reden wir womöglich aneinander vorbei.
Und: Entry Mode ist flexibler, als man denkt.
Siehe Video. Man kann auch dekrementieren. Das ist erst einmal so
gesehen prinzipiell kein Fehler. Kommt drauf an, was man möchte.
Der Witz ist ja dabei gerade, dass nicht jedesmal explizit eine
locate-Anweisung ausformuliert werden muss. Das übernimmt dann die im
Entry Mode Set angestoßene, bereits implementierte Routine.
ciao
gustav
Hi,
auch wenn es schon Gegenstand der Diskussion war:
Nur einige Zeilen aus besagtem Tutorial-File rausgesucht:
in temp3, LCD_PORT
andi temp3, 0x80
or temp1, temp3
Überflüssiger Ballast, wenn man, wie in den meisten Fällen, ohne
Busyflag-Abfrage arbeitet.
Und temp3 kann man sich schenken. Und wieso wird temp1 nicht auch
gepushed/gepopt?
Ich drehe es um. Zuerst unteres Nibble ausblenden und oberes übergeben,
da diese Reihenfolge vom LCD Controller so vorgegeben ist. Erst beim
zweiten Durchgang wird geswappt. Warum Verwirrung stiften, indem man den
Swap zuerst durchführt und dann wieder das andere Nibbel aus"und"et.
Ist doch anders viel anschaulicher und LCD-logisch nachvollziehbarer, es
so zu machen, wie im von mir oben aufgezeigten Beispiel.
Im Klartext zum Mitschreiben nochmal:
LCD Controller verlangt zwingend im Vierbit-Modus z u e r s t das obere
Nibble, dann das untere, und zwar in zwei Schritten, die jeweils mit
einem Enable-Impuls quittiert werden müssen. Macht man das anders, dann
sieht das vielleicht wie im Video aus.
Statt "Hallo" sieht man die Ascii Zeichen, wo in der Charactertabelle
Zehner- und Einerstelle vertauscht sind. (Oder MSB und LSB vertauscht).
Man muss auch nicht die ganze Komplexität der unterschiedlichen Befehle
zur Schau stellen. Ich fände es gerade für den Absolut-Anfänger besser,
sich mit einer Handvoll gängiger Instructions zu bescheiden. Denn es
funktioniert auch so. Gerade die vermeintlich unterschiedlichen
Bit-Setz-Befehle bzw. Sprünge mit sbrc etc. pp. bieten hier bereits zur
Genüge durchgekauten Diskussionsstoff.
Es gibt nämlich eine Reihe von "unechten", sondern Atmel AVR
spezifischen Instructions. Die unter anderem auch auf verschiedenen
Targets nicht alle zur Verfügung stehen müssen.
Also: Je einfacher, je weniger "Extrawürste", desto schneller wird der
Anfänger ein Erfolgserlebnis verzeichnen können.
ciao
gustav
Karl B. schrieb:> in temp3, LCD_PORT> andi temp3, 0x80> or temp1, temp3>> Überflüssiger Ballast, wenn man, wie in den meisten Fällen, ohne> Busyflag-Abfrage arbeitet.
Ich denke, diese drei Zeilen haben eher weniger mit dem Busy-Flag zu
tun, sondern sollen das unbenutzte Bit 7 vom LCD_PORT sichern. Daraus
erheben sich die Kritikpunkte, die schon auf
https://www.mikrocontroller.net/articles/Diskussion:AVR-Tutorial:_LCD
bemerkt wurden: fehlende Kommentierung, warum wird nur Bit 7 gesichert
und nicht das ebenfalls unbenutzte Bit 6? U.a. diese Punkte habe ich in
meinem eingangs geposteten Code verbessert: Sicherung der unbenutzten
Bits in Abhängigkeit der Symboldefinitionen.
Karl B. schrieb:> Und wieso wird temp1 nicht auch> gepushed/gepopt?
Ein weiterer Kritikpunkt, den ich ausgemerzt habe: siehe oben, im
Eröffnungsbeitrag.
Karl B. schrieb:> Ich drehe es um. Zuerst unteres Nibble ausblenden und oberes übergeben,> da diese Reihenfolge vom LCD Controller so vorgegeben ist. Erst beim> zweiten Durchgang wird geswappt. Warum Verwirrung stiften, indem man den> Swap zuerst durchführt und dann wieder das andere Nibbel aus"und"et.> Ist doch anders viel anschaulicher und LCD-logisch nachvollziehbarer, es> so zu machen, wie im von mir oben aufgezeigten Beispiel.
Dass das Swap im Originalcode zuerst kommt, liegt daran, dass im
Tutorial der Datenbus DB4..7 des LCD an den LCD_PORT-Pins 0..3 des AVRs
angeschlossen ist. Ich habe das in meinem Code flexibel umgesetzt,
mithilfe der Assemblerdirektiven. Ist der Anschluss an AVR-Pins 4..7,
erfolgt das Swap erst vor dem zweiten Durchgang.
Karl B. schrieb:> LCD Controller verlangt zwingend im Vierbit-Modus z u e r s t das obere> Nibble, dann das untere, und zwar in zwei Schritten, die jeweils mit> einem Enable-Impuls quittiert werden müssen.
Das ist mir bekannt ...
Karl B. schrieb:> Also: Je einfacher, je weniger "Extrawürste", desto schneller wird der> Anfänger ein Erfolgserlebnis verzeichnen können.
Okay, also die ursprüngliche Datei im Tutorial wird einfach gehalten,
keine „.ifdef“s und „.endif“s und ohne Busy-Flag. Trotzdem kann man ja
einiges verbessern, wie das oben diskutierte Sichern der unbenutzten
Pins – entweder vollständig und gut kommentiert oder ganz weglassen; und
vorallem Retten aller Register.
Hi,
verstehe die Absicht des TO schon, für unterschiedliche Konfigurationen
ein
möglichst passendes, allgemeingültiges Programm zu kreieren.
Das findet schon meine Wertschätzung.
Einen etwas anderen Weg einzuschlagen, ist vielleicht auch nicht ganz
falsch. Also, erst einmal herausfinden, wie die spezifische Pinbelegung,
Portbelegung etc. ist. Dann das Programm entsprechend anpassen.
Dabei ein Grundgerüst verwenden. Ins Programm eingreifen muss man ja so
oder so.
Hatte mal sowas gemacht:
Ist aber noch nicht überarbeitet. Ohne Gewähr.
Hompage war mir auf die Dauer zu teuer.
Aber ich möchte es niemandem vorenthalten.
Vieles ist vielleicht zu ausführlich.
Aber die Intention war ja, das LCD zum Laufen zu bringen, wenn
noch keinerlei Kenntnisse damit vorliegen.
Viel Spaß!
ciao
gustav
P.S:
Ziel speichern unter...und im Browser öffnen ...sonst kommt nur der
Quellcode.
Falls es noch jemanden interessiert:
Ich habe nun meinen eingangs angehängten Code selbst getestet und er hat
auf Anhieb funktioniert. Lediglich bei der Warteschleifen-Version musste
ich die Delays noch deutlich erhöhen, damit mein LCD (Displaytech 162)
keine Zeichen „verschluckt“. Darin ist somit ein Vorteil der
Busy-Flag-Abfrage zu sehen, bei der man nicht mit den Wartezeiten
herumexperimentieren muss.
Überlege gerade, ob ich am Ende des AVR-Tutorial: LCD noch einen
Abschnitt zur Busy-Flag-Auswertung schreibe. Schließlich heißt es dort
„Für professionellere Sachen also lieber den IO-Pin opfern und Busy
abfragen.“ Auch wenn das jetzt sicher wieder einige infrage stellen
werden.
Hi,
gerade mit der Busyflag-Abfrage handelt man sich oft noch Probleme ein.
Weil Cursor undefiniert springt.
Der Fehler liegt meistens darin, dass der Adresscounter erst dann,
nachdem das Busy-Flag resettet wurde, eine Adresse weitergeht.
Hier helfen noch ein paar "nops".
Also auch hier evtl. ebenso Feinjustierungsbedarf.
Zitat:
"...Note: — indicates no effect.
* After execution of the CGRAM/DDRAM data write or read instruction, the
RAM address counter is incremented or decremented by 1. The RAM address
counter is updated after the busy flag turns off. In Figure 10, t ADD is
the time elapsed after the busy flag turns off until the address
counter is updated..."
/Zitat
Quelle: Hitachi HD44780 manual Seite 25
Apropos Zeitschleifen:
Mit den 16-Bittern fahre ich mittlerweile ganz gut.
Die Werte stehen ganz unten im angehängten asm-File. Natürlich auch
abhängig von der Taktfrequenz.
ciao
gustav
Wilhelm M. schrieb:> Und dann sind wir auch schon bei dem Problem, dass man in asm eben nicht> vernünftig kapseln und abstrahieren kann.
Das ist doch kompletter Quatsch. Natürlich kann man das.
> Sinnvoll wäre hier die> Funktion des LCD-Controllers HD44780 von der Funktion des Interface> PCF8547 und von der Funktion des Transports I2C zu trennen, wie man das> etwa in C/C++ kann.
Und du glaubst, dass das in Asm nicht möglich wäre? Dann kannst du halt
schlicht kein Asm.
Das einzige, was in Asm natürlich nicht möglich ist: Die Sache für
verschiedene Architekturen zu implementieren. Aber auch in C/C++ gelingt
das typisch nur mit übelsten #ifdef-Orgien (je tiefer in der
Treiber-Hierarchie, desto mehr), die der Lesbarkeit und Wartbarkeit des
Codes keinesfalls gut tuen.
Ich muss allerdings zugeben, das auch in Asm für nur eine Architektur
(AVR8) inzwischen die .ifdef-Orgien recht umfangreich werden können.
Leider hat der Hersteller selber in sehr vielen Fällen unnötigerweise
dafür gesorgt...
Karl B. schrieb:> Der Fehler liegt meistens darin, dass der Adresscounter erst dann,> nachdem das Busy-Flag resettet wurde, eine Adresse weitergeht.> Hier helfen noch ein paar "nops".> Also auch hier evtl. ebenso Feinjustierungsbedarf.
Aus den Angaben auf S. 25 des HD44780-Datenblatts folgt, dass diese
Verzögerung etwa 6 µs beträgt (bei f_OSC = 270 kHz). Damit müsste doch
die zweite Enable-Flanke zur Abfrage des zweiten Nibbles (bei mir insg.
10 µs) als Wartezeit für das Update des Adresszählers schon reichen?
Außerdem könnte dieses Problem theoretisch ja auch beim Verzicht auf
Busyflag-Abfrage auftreten, wenn die Wartezeit gerade „an der Schwelle“
liegt, also kurz nach dem Busy-0 aber vor dem Adresscounter-Update
endet?
Was mich noch interessieren würde: Ich habe in meiner Version das
Busy-Flag bereits in der Initialisierungsroutine abgefragt, also
sämtliche Delays durch Busy-Abfrage ersetzt – auch beim Warten während
der LCD-Controller-Initialisierung. Irgendwo habe ich gelesen, dass man
dort das Busy Flag nicht abfragen könne. Bei mir zumindest funktioniert
es ja, aber ist dem immer so, bzw. gibt es irgendeinen Grund, dort feste
Wartezeiten einzuhalten?
Johannes F. schrieb:> gibt es irgendeinen Grund, dort feste> Wartezeiten einzuhalten?
Hi,
Power on reset macht der Displaycontroller so oder so.
Aber die Bedingung ist, dass die Anstiegszeit der angelegten
Betriebsspannung (hier 5V) innerhalb einer nicht zu langen Zeitspanne
stattfindet.
Deswegen sollte kein großer Elko direkt am Display angeschlossen sein.
[Ab etwa 2200 µF funktioniert bei mir im Test der Power-on-Self-Reset
nicht mehr sauber.]
Daraus folgt, dass innerhalb dieser Self-Reset-Spanne der Controller
selber seine Befehlsausführung und Zeit, die er dafür braucht, bestimmt.
Das ist mit jener Formulierung nämlich gemeint, dass in der Zeit keine
Busyflag-Abfrage wirkt, ob man die nun softwaremäßig vorgesehen hat oder
nicht. Die "Firmware" hat höhere Priorität. Und die angegebenen Waits
sind eben Vorgabe, an der man sich orientieren sollte.
BTW: Die Unterschiede der sehr ähnlichen Controller KSxxx und so weiter
beziehen sich im wesentlichen eben auf diese Zeiten.
Dann sollte beachtet werden, dass die praktische Situation so ist,
dass µC und Display meistens von derselben 5V-Spannungsquelle gespeist
werden.
Der µC ist eher in der Lage Steuerimpulse zu senden, während das Display
noch nicht bereit ist.
Deswegen will man keine Befehle in der Zeit haben. Auch solche nicht,
die eine Busyflag-Abfrage machen.
ciao
gustav
Johannes F. schrieb:> Was mich noch interessieren würde: Ich habe in meiner Version das> Busy-Flag bereits in der Initialisierungsroutine abgefragt, also> sämtliche Delays durch Busy-Abfrage ersetzt – auch beim Warten während> der LCD-Controller-Initialisierung.
Das geht nur dann gut, wenn das LCD immer nur nach einem sauberen
Power-On initialisiert wird.
Aber z.B. eine Resettaste, Brownout oder ein Watchdog kann das Reset
auch inmitten eines LCD-Zugriffs auslösen.
Der LCD-Status ist dann unbekannt und kann 3 verschiedene Zustände
haben:
1. LCD ist im 8-Bit Modus.
2. LCD ist im 4-Bit Modus, 1. Nibble
3. LCD ist im 4-Bit Modus, 2. Nibble
Karl B. schrieb:> Die Abfrage bleibt da hängen, da Busyflag während der Self-Init-Phase> ständig auf "high" steht.
Ja, das ist klar, aber das ist doch dann kein Nachteil gegenüber der
Warteschleifenvariante (ohne BF-Abfrage), bei der der µC ja noch länger
„hängenbleiben“ muss, um die Zeit mit Sicherheitszuschlag abzuwarten
(sofern man keinen Timerinterrupt einsetzt)?
Peter D. schrieb:> Aber z.B. eine Resettaste, Brownout oder ein Watchdog kann das Reset> auch inmitten eines LCD-Zugriffs auslösen.> Der LCD-Status ist dann unbekannt und kann 3 verschiedene Zustände> haben:> 1. LCD ist im 8-Bit Modus.> 2. LCD ist im 4-Bit Modus, 1. Nibble> 3. LCD ist im 4-Bit Modus, 2. Nibble
OK, also könnte es problematisch sein, wenn das LCD z.B. gerade auf das
2. Nibble wartet, und R/W zum Lesen des BF high wird?
Hi,
soweit mir bekannt ist:
Die R/W Umschaltung Port von Eingang auf Ausgang geht schon nicht in der
Init Phase mindestens 10 ms siehe Dabla.
ciao
gustav
Karl B. schrieb:> Die R/W Umschaltung Port von Eingang auf Ausgang geht schon nicht in der> Init Phase mindestens 10 ms siehe Dabla.
Im Datenblatt auf S. 23: „The busy flag (BF) is kept in the busy state
until the initialization ends (BF = 1).“
Also ich interpretiere das so, dass das BF während der Initialisierung
abgefragt werden kann – die Aussage, dass es auf 1 gehalten wird, würde
doch sonst keinen Sinn ergeben?
Bei meinem LCD (vermutlich KS0070B) funktioniert es ja auch. Verzögerung
beim Einschalten ist wahrnehmbar, aber sehr kurz, ohne dass Zeichen
„verschluckt“ werden.