Forum: Mikrocontroller und Digitale Elektronik AVR-Tutorial: LCD - Erweiterung lcd-routines.asm - Bitte um Feedback


von Johannes F. (emitterfolger)


Angehängte Dateien:

Lesenswert?

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

von Ralph S. (jjflash)


Lesenswert?

... warum "verändert / verbessert" man etwas, wenn man keine Möglichkeit 
hat, seine Änderungen zu testen und veröffentlicht dieses dann auch noch 
ungetestet?

von asm-hater (Gast)


Lesenswert?

Blöde Idee!

von S. Landolt (Gast)


Lesenswert?

> ... 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 ...

von Karl B. (gustav)


Lesenswert?

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
von Alexander S. (alesi)


Lesenswert?

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.

von Johannes F. (emitterfolger)


Lesenswert?

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?

von Johannes F. (emitterfolger)


Lesenswert?

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.

: Bearbeitet durch User
von S. Landolt (Gast)


Lesenswert?

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.

von Peter D. (peda)


Lesenswert?

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).

von S. Landolt (Gast)


Lesenswert?

> 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!

von Dieter (Gast)


Lesenswert?

S. Landolt schrieb:
> eine Menge Spaß dabei haben!

Mit ner Dampflok sicher. Mit Assembler dagegen hat man nur Spaß wenn man 
Masochist ist...

von Johannes F. (emitterfolger)


Lesenswert?

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).

: Bearbeitet durch User
von Johannes F. (emitterfolger)


Lesenswert?

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?

von Thomas H. (Firma: CIA) (apostel13)


Lesenswert?

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.

von S. Landolt (Gast)


Lesenswert?

> ... verbessert und ... erweitert
> Delay-Routinen anpassen muss

Dann wäre dies doch sicher auch ein lohnender Punkt, nicht wahr?

von Stefan F. (Gast)


Lesenswert?

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.

von Peter D. (peda)


Lesenswert?

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.

von Thomas F. (igel)


Lesenswert?

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.

von Karl B. (gustav)


Angehängte Dateien:

Lesenswert?

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

von Wilhelm M. (wimalopaan)


Lesenswert?

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.

von DerEinzigeBernd (Gast)


Lesenswert?

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?

von Karl B. (gustav)


Lesenswert?

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
von Johannes F. (emitterfolger)


Lesenswert?

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“?

von Karl B. (gustav)


Angehängte Dateien:

Lesenswert?

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

von Johannes F. (emitterfolger)


Angehängte Dateien:

Lesenswert?

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.

von Karl B. (gustav)


Angehängte Dateien:

Lesenswert?

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

von Johannes F. (emitterfolger)


Lesenswert?

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.

: Bearbeitet durch User
von Karl B. (gustav)


Angehängte Dateien:

Lesenswert?

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
von Johannes F. (emitterfolger)


Lesenswert?

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.

von Karl B. (gustav)


Angehängte Dateien:

Lesenswert?

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

von c-hater (Gast)


Lesenswert?

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...

von Johannes F. (emitterfolger)


Lesenswert?

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?

von Karl B. (gustav)


Lesenswert?

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
von Peter D. (peda)


Lesenswert?

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
von Karl B. (gustav)


Angehängte Dateien:

Lesenswert?

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
von Johannes F. (emitterfolger)


Lesenswert?

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?

von Karl B. (gustav)


Lesenswert?

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

von Johannes F. (emitterfolger)


Lesenswert?

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
Noch kein Account? Hier anmelden.