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
:
Bearbeitet durch User
Johannes F. schrieb: > Die Datei „lcd-routines.asm“ vom Ende des AVR-Tutorial: LCD habe ich > (hoffentlich) verbessert Welche genau, diese https://www.mikrocontroller.net/wikifiles/9/96/Lcd-routines.asm ? Die enthält zu Beginn auch
1 | ;sendet ein Datenbyte an das LCD |
2 | lcd_data: |
3 | |
4 | ; sendet einen Befehl an das LCD |
5 | lcd_command: |
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: > eine Menge Spaß dabei haben! Mit ner Dampflok sicher. Mit Assembler dagegen hat man nur Spaß wenn man Masochist ist...
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.
> ... verbessert und ... erweitert > Delay-Routinen anpassen muss Dann wäre dies doch sicher auch ein lohnender Punkt, nicht wahr?
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
:
Bearbeitet durch User
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
Karl B. schrieb: > Hi, > gib 'mal den Link an, wo das zugehörige asm-File zu sehen ist. > Sonst reden wir womöglich aneinander vorbei. https://www.mikrocontroller.net/wikifiles/9/96/Lcd-routines.asm Zusätzlich im Anhang, falls die verlinkte Datei im Tutorial geändert wurde/wird.
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.
:
Bearbeitet durch User
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
:
Bearbeitet durch User
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
:
Bearbeitet durch User
Hi, Die Abfrage bleibt da hängen, da Busyflag während der Self-Init-Phase ständig auf "high" steht. ciao gustav
:
Bearbeitet durch User
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.
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.