Hallo, Ich habe mal eine kleine Frage. Ich schließe ein HD44780 Display per Schieberegister an. Schieberegister läuft an einem Mega16 mit SPI eingeschaltet. Wenn ich nun den SPI Takt auf Fsys/128 stelle bei 16Mhz. dann hätte ich doch quasi 16000000/128=125000 Clocktakt. Bei 8Bits entspräche das 125000/8=15625 Hz Strobetakt. 1/15625Hz = 64uS. Heißt es jetzt, dass wenn das Display 40uS für einen Befehl braucht (Die langen INIT Befehle mal ausgelassen) dass ich hier keine warteschleifen brauch?
Im Prinzip ja. Du musst aber natürlich vor dem Senden der nächsten Daten immer so lange warten, bis die SPI alles ins Schieberegister geschaufelt hat. Insofern brauchst du doch Warteschleifen, bzw. musst auf den entsprechenden Interrupt warten.
"Warteschleifen" braucht man eigentlich garnicht, wenn man es dementsprechend programmiert. Denn Warteschleifen vernichten nur wertvolle Rechenleistung. Sie sollten daher nur bei kurzen zeitkritischen Wartezeiten (im µs-Bereich) angewendet werden. Ich habe ein Display (8 Zeilen, 24 Zeichen) mit einem Timer-Int synchronisiert (Mega8535). Der Timer-Int setzt nur ein Flag, dass die "Wartezeit" abgelaufen ist. Im Hauptprogramm wird dieses Flag abgefragt und dann das nächste Zeichen ausgegeben. Wenn andere Arbeiten anliegen, können auch mal einige "Ausgabetermine" ausfallen, das merkt aber keiner. Da in gewissen Programmsituationen der ganze Bildschirm (192 Zeichen) auf einmal aktualisiert wird, habe ich der Ausgaberoutine einen Ringbuffer von 256 Bytes spendiert (es war noch ausreichend SRAM vorhanden, der Einfachheit des Pointerhandlings im Bereich von $100 bis $1ff). Die LCD_Data-Routine schreibt nun nur in den Ringbuffer (geht wahnsinnig schnell), die Zeichen werden dann so ausgegeben, wie der Controller Zeit dazu findet, bis der Lesepointer den Schreibpointer erreicht hat. Dann wird ein "Jobflag" gelöscht, welches in der LCD_DATA-Routine gesetzt wurde, worauf die Zeichenausgabe eingestellt wird. Auch die Cursor-Positionierung erfolgt über den Ringbuffer. Dazu wurden Steuerzeichen im unteren ASCII-Bereich vereinbart. Jede Positionierung benötigt zwei Bytes im Ringbuffer. Wenn deine SPI-Ausgabe dementsprechend langsam ist, dann kann die Ausgabe des nächsten Zeichens natürlich über den SPI-Interrupt synchronisiert werden. Einen Ringbuffer wirst du aber trotzdem brauchen. ...
Ja, geht super. Habe ich beim ATTiny12 auch gemacht. Die Daten müssen ja nur die 1µs stabil anliegen, während E = 1 ist. Du kannst also ruhig die nächsten Daten reinschieben, während das LCD noch den alten Befehl abarbeitet. Ich habe ein 74HC164 genommen, dann reichen 3 Leitungen zum LCD. Peter
Ok klingt gut. So sieht meine Schaltung aus. Wollte mir eine kleine lib basteln, die man dann immer mal wieder verwenden kann. C-Code habe ich schon, allerdings ist das Display hier sehr eigenwillig. Hat irgndwie ne Macke!
Achso, Du benutzt den 4Bit-Modus, dann hast Du ja jede Menge Wartezeit. Ich habe den 8Bit-Modus benutzt und steuere den E-Pin nach dem Schieben direkt an, das ist von der Software her einfacher: http://www.mikrocontroller.net/forum/read-4-22246.html#new Die Wartezeit (46µs) hatte ich damals noch dringelassen (unnötig). Bei Displays mit 2 E-Pins braucht man dann insgesamt 4 Portpins (CLK, DIN, E1, E2). Peter
Also das WD-C2704M von Pollin (4x27) läuft bei mir im 4-Bit-Mode in ASM sehr stabil. Allerdings direkt angeschlossen, also ohne Schieberegister. Dafür hatte ich mal eine Ansteuerung geschrieben, bei der die Pins frei verteilt werden dürfen, also jeder Pin auf einem anderen Port sein darf. Einschränkung sind die Datenpins, die müssen in einem Nibble eines Ports liegen, oberes oder unteres Nibble kann ausgewählt werden. Dies schafft die Möglichkeit, die für LCD genutzten Pins (des Mega8) so zu verteilen, dass man die Spezialfunktionspins frei halten kann. Ich habe aber bisher noch keine Zeit und Muße gefunden, diese Routinen so abzuändern, dass die Ausgabe über Ringbuffer und Timer-Synchronisation erfolgt. Dort, wo ich das LCD einsetze, werden immer nur wenige Zeichen aktualisiert, da ist Ausgabecache nicht unbedingt erforderlich. ...
<<Achso, Du benutzt den 4Bit-Modus, dann hast Du ja jede Menge Wartezeit. Ich habe den 8Bit-Modus benutzt und steuere den E-Pin nach dem Schieben direkt an, das ist von der Software her einfacher: Hm.Hatte ich mir auch erst gedacht, aber effektiver ist es doch, wenn man die Schiebezeit vom Schieberegister als Waitstate sozusagen benutzt um das LCD nicht zu schnell anzusteuern. Ich muss dann zwar auf den höchsten Teiler beim SPI gehen, aber was solls. Hängt eh nur das eine Schieberegister dranne. PS: Irgndwie habe ich das Gefühl die MOS 4094 (meistens CD4094) von Reichelt sind irgndwie sehr langsam im gegensatz zu dem HC/HCT Typ. Und das obwohl der HC/HCT Typ kaum mehr kostet.
Die CD-Familie ist in der Tat grottenlahm. Aber warum wunderst du dich, steht doch alles im Datenblatt drin!
nene, ist mir ja nachher erst aufgefallen im Datenblatt.. Ist nicht so, als hätte ich das DB nicht gelesen! PS: Kleine Frage zu C. ich hab eine Funktion die einen Parameter erwartet. Nennen wir sie void func(unsigned char param) Ist erstmal egal was diese Funktion macht. Nun habe ich ein Byte (0b00000000) in der Variable unsigned char var = 0b00000000 Wenn ich jetzt folgenden Funktionsaufruf mache func(var & (~(1<<4)) ); Wird dann der Wert in var verändert? Ich schätze nein oder? Es wird doch erst var in ein temporäres Register gelegt, geOR't und dann der Funktion übergeben oder?
Hier wäre mein bis jetziger Code. Falls es jemand interessiert oder vielleicht sogar jemand mal drüberlesen möchte :-). Bin ja noch nicht so der Profi in gcc für AVR.
Ok Danke Daz. Das sieht ja grausam aus. Hier mal besser lesbar. PS: Ist natürlich keine Spur von Ringbuffer etc.. Werde erstmal die ganzen Pausen rausnehmen und probieren mit einem WINTEK von Pollin.
@Simon: Bist du sicher, dass du das Timing korrekt einhältst? Enable sollte meines Erachtens nach erst aktiviert werden, nachdem die Data-Pegel sicher anliegen. Ein gleichzeitiges Anlegen der Data-Pegel und des Enable-Impulses halte ich für zu störanfällig. Ich kann mich da aber auch irren, ich habe noch kein LCD mit Schieberegister angesteuert. Mir wäre es aber zu heikel... ...
Achja... Bist du sicher, dass die Pausen auch ausgeführt werden? Nicht, dass dir die beim Compilieren bzw. Linken wegoptimiert werden... ...
Also ich glaube zumindest dass dies keine Probleme macht. War erst auch zweifelhaft, hat aber wohl zuerst funktioniert. Leider steht im Datenblatt nix ob es Rising Edge oder Falling Edge strobed. Jetzt bin ich unsicher. Die Pausen sind da.
1 | 228 .L26: |
2 | 229 .LM31: |
3 | 230 /* #APP */ |
4 | 231 00ea 0000 nop |
5 | 232 /* #NOAPP */ |
6 | 233 00ec 2196 adiw r28,1 |
7 | 234 00ee 8FEF ldi r24,hi8(-1) |
8 | 235 00f0 CF3F cpi r28,lo8(-1) |
9 | 236 00f2 D807 cpc r29,r24 |
10 | 237 00f4 D1F7 brne .L26 |
Laut Datenblatt zu meinem Displaytech 204A mit HD44780 müssen die Daten mindestens 60 ns vor bis mindestens 10ns nach dem falling edge von E anliegen. Das sicherste wäre somit, die Daten am Schieberegister auszugeben, dann über einen separaten Pin an und wieder auszuschalten und dann erst das Schieberegister zu überschreiben.
Laut HD44780 Datenblatt muß RS vor E = 1 anliegen, dann die Daten mit E = 1 anlegen und dann E = 0 setzen. Dann das nächste Nibble, macht insgesamt 5 * Schieben und Latchen. Ich schiebe einmal 8 Bit, dann setze ich RS auf DIN des Schieberegisters und dann E = 1, nen bischen warten, E = 0, fertig. Peter
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.