Hi, ja wieder Einer der..... ;P Pople nun schon seit >10h an meiner LCD_Lib rum, ich will nich mehr.... 100x überprüft, gesucht, geändert, kein(en wirklichen) Fehler gefunden o. ich bin Betriebsblind. Der Pic18F25k22 ist auf ein BrakeoutBoart (ink. 1x100nF) gelötet, Steckbrett. Stromversorgung OK, Protokoll OK(?), alle Timings ausgemessen OK, Letzer Prüfung RiseTime FALED! Ja kruzefix, kann ja wohl nich sein. Hat ja im Normalfall auch (scheinbar) keiner. Obiges OsziBild zeigt einen belasteten Port, ~25ns. Ohne geht die RiseTime auf ~20ns runter. Pic Dabla sagt bei 5V Typ., 15ns Max. 32ns. Was ja dann eigentlich des öfteren Probleme geben sollte, is ja nu nich außergewöhnlich langsam??? A-Karte gezogen? Das Display zeigt auch unterschiedliches Verhalten, Balken weg, Cursor ja/nein, irgendwo einzelne Zeichen,... Zeigt aber nie das an was es soll. Wie was nu! Kann es wirklich daran liegen? Oder doch "Betriebsblind" und wenn nich, auf gut Glück nen neuen auflöten? (Der Trigger sitzt vor Enable o. vor der Bussy-Prüfung.)
:
Bearbeitet durch User
Teo D. schrieb: > Wie was nu! Kann es wirklich daran liegen? Nö. Die Hauptfehlerursache (zu 99,99%) ist eine fehlerhafte Initsequenz. Das original HD44780 Datenblatt ist da leider etwas unpräzise. Kein Zugriff darf ohne Wartezeit direkt auf den vorherigen folgen. Insbesondere im 4Bit-Mode ist ein sauberes Init essentiell.
Wo ich gerade D0,D1,D2,D3 in deinem LA-Plot sehe. Nutzt der 4-bit Mode vom HD44780 nicht D4 bis D7?
Hi, kenne das Problem zur Genüge. Bin schon seit 2008 mit dem Thema LCD-Initialisierung befasst. Was @Peda sagt, ist absolut essenziell. Das eine Missverständnis bei der Doku ist: Die Befehlsliste ist nicht die Reihenfolge, mit der das LCD initialisiert werden muss. (Die Befehlsliste listet nach aufsteigendem Bit-Wert.) Und: Busy-Flag-Abfrage kann in der ersten Phase des Init nicht laufen. Dann: Der Power on self reset initialisiert das LCD von alleine, schaltet aber die Anzeige ab. Dann muss "softwaremäßig" noch einmal initialisiert werden. Der POSR braucht eine innerhalb eines definierten Zeitintervalls ansteigende Versorgungsspannung. Ist ein "dicker" Elko direkt an den Versorgungsspannungsanschlüssen des LCD, kann es in bestimmten Fällen vorkommen, dass der POSR nicht oder nicht richtig ausgeführt wird. Dann gibt es im Vierbitmodus schon kleine Missverständnisse. Der Befehlssatz am Anfang 3 mal hex 30 (oder je nach Lib hex 03) impliziert, dass die untersten vier Ports auf GND und somit logisch "Null" stehen. So ist das sowohl beim Achtbitmodus wie Vierbitmodus am Anfang egal, ob nun die unteren vier Ports schon fest auf GND verdrahtet sind oder nicht. Aber das LCD kann im Vierbit-Modus nur D4 bis D7 lesen. Wurde oben schon gesagt. Dann ist der HD44780-Controller so konfiguriert, dass er zuerst das obere Nibble des 8-Bit Datenbytes verlangt. Das wird beim "Swappen" oft missverstanden. Dann kommen aber auf jeden Fall irgendwelche Characters z.b. ein Sigma. Und noch etwas Prosa dazu: Beitrag "Re: Atiny2313 4313 LCD Displaytech 204B/ DCF77" sorry für ATMEL AVRs, PICS sind für mich "böhmische Dörfer". Die Initialisierungssequenzen sind aber sicher leicht portierbar. ciao gustav
Teo D. schrieb: > Wie was nu! Kann es wirklich daran liegen? Da schließe ich mal den anderen an und sage nein. Ein LCD-Testprojekt für den 25K22 kannst du hier finden: http://picforum.ric323.com/viewtopic.php?f=40&t=210 (Zum Testen des Displays, Vergleichen der Initialisierung...) ((ist ein bisschen speziell, weil die Pins für die Daten frei wählbar sein sollten))
:
Bearbeitet durch User
Bernd S. schrieb: > Wo ich gerade D0,D1,D2,D3 in deinem LA-Plot sehe. Nutzt der 4-bit Mode > vom HD44780 nicht D4 bis D7? Das passt schon, ist nur mit D0-D3 gedankenlos benannt worden, Karl B. schrieb: > Das eine Missverständnis bei der Doku ist: > ... Nö, kein Missverständnis. Is ja auch nich mein erstes, wenn auch in C. Peter D. schrieb: > Kein > Zugriff darf ohne Wartezeit direkt auf den vorherigen folgen. > Insbesondere im 4Bit-Mode ist ein sauberes Init essentiell. Wie geschrieben, alle geprüft und iO. Nur die Übertragung des zweiten (unteren) Nibble ist unklar im Dabla. Hatte da aber auch schon erfolglos die Wartezeit variiert. Volker S. schrieb: > Da schließe ich mal den anderen an und sage nein. Hab ich befürchtet, nur warum seh ich den Fehler nich. Volker S. schrieb: > Ein LCD-Testprojekt für den 25K22 kannst du hier finden: > http://picforum.ric323.com/viewtopic.php?f=40&t=210 > > (Zum Testen des Displays, Vergleichen der Initialisierung...) > ((ist ein bisschen speziell, weil die Pins für die Daten frei wählbar > sein sollten)) THY
Ich dachte zwar das der LA-Plot besser zu lesen ist, als sich durch mein C zu wühlen. Aber hier mal den relevanten Code.
1 | #include "mcc_generated_files/mcc.h" |
2 | #include "HD44780.h" |
3 | |
4 | void LCD_Init(void) { |
5 | TRIGGER // <---------- T R I G G E R |
6 | LCD_PORT_LAT = 0x03; |
7 | __delay_ms(17); |
8 | TRIGGER // <---------- T R I G G E R |
9 | LCD_ENABLE; |
10 | __delay_us(4500); |
11 | TRIGGER // <---------- T R I G G E R |
12 | LCD_ENABLE; // LCD_PORT_LAT = 0x03; |
13 | __delay_us(110); |
14 | TRIGGER // <---------- T R I G G E R |
15 | LCD_ENABLE; // LCD_PORT_LAT = 0x03; |
16 | // Bussy Flag is avidable
|
17 | LCD_PORT_LAT = 0x02; |
18 | TRIGGER // <---------- T R I G G E R |
19 | TRIGGER // <---------- T R I G G E R |
20 | LCD_Bussy(); |
21 | LCD_ENABLE; |
22 | LCD_Write(LCD_FUNKTION_SET, INSTRUCTION); |
23 | LCD_Write(LCD_DISPLAY_OFF, INSTRUCTION); |
24 | LCD_Write(LCD_DISPLAY_CLEAR, INSTRUCTION); |
25 | LCD_Write(LCD_ENTRY_MODE_SET, INSTRUCTION); |
26 | LCD_Write(LCD_FUNKTION_SET, INSTRUCTION); |
27 | }
|
28 | |
29 | void LCD_Write(unsigned char data, unsigned char RS) { |
30 | LCD_RS_LAT = RS; |
31 | LCD_PORT_LAT = (LCD_PORT_LAT & 0xf0) | (data >> 4); |
32 | TRIGGER // <---------- T R I G G E R |
33 | LCD_Bussy(); |
34 | LCD_ENABLE; |
35 | LCD_PORT_LAT = (LCD_PORT_LAT & 0xf0) | (data & 0x0f); |
36 | __delay_us(1); |
37 | LCD_ENABLE; |
38 | }
|
39 | |
40 | void LCD_Bussy(void) { |
41 | unsigned char dummy; |
42 | dummy = LCD_RS_LAT; |
43 | LCD_RS_SetLow(); |
44 | // __delay_us(1); // tAS
|
45 | LCD_READ_MODE; // ersetzt Delay tAS |
46 | LCD_ENABLE; |
47 | while (LCD_BUSSY_PORT) { |
48 | __delay_us(1); |
49 | LCD_ENABLE; |
50 | }
|
51 | LCD_RS_LAT = dummy; |
52 | LCD_WRITE_MODE; |
53 | }
|
54 | //------------------------------------------------
|
55 | #include "mcc_generated_files/mcc.h" |
56 | #include "HD44780.h" |
57 | |
58 | void main(void) { |
59 | // Initialize the device
|
60 | |
61 | SYSTEM_Initialize(); |
62 | LCD_Init(); |
63 | LCD_Write(LCD_DISPLAY_ON, INSTRUCTION); |
64 | LCD_Write('A', DATA_MODE); |
65 | LCD_Write('H', DATA_MODE); |
66 | LCD_Write( 0x38, DATA_MODE); |
67 | |
68 | while (1) { |
69 | |
70 | LED_TEST_LAT = ~LED_TEST_LAT; |
71 | __delay_ms(500); |
72 | |
73 | }
|
74 | }
|
Hier noch die Macros. Rest egal, es werden definitiv keine falschen Pins angesteuert.
1 | #define LCD_ENABLE {LCD_Enable_SetHigh(); __delay_us(1);LCD_Enable_SetLow();}// delay=tDDR
|
2 | //#define LCD_READ_MODE {LCD_PORT_TRIS |= 0x0f; LCD_RW_SetHigh();}
|
3 | #define LCD_READ_MODE {LCD_D0_SetDigitalInput();LCD_D1_SetDigitalInput(); \
|
4 | LCD_D2_SetDigitalInput();LCD_D3_SetDigitalInput(); LCD_RW_SetHigh();}
|
5 | //#define LCD_WRITE_MODE {LCD_PORT_TRIS &= 0xf0; LCD_RW_SetLow();}
|
6 | #define LCD_WRITE_MODE {LCD_D0_SetDigitalOutput();LCD_D1_SetDigitalOutput(); \
|
7 | LCD_D2_SetDigitalOutput();LCD_D3_SetDigitalOutput(); LCD_RW_SetLow();}
|
8 | |
9 | #define TRIGGER {TEST_Trigger_SetHigh(); TEST_Trigger_SetLow();}
|
Eine kleine Erfahrung meinerseits, ohne das Datenblatt des LCD genauer betrachtet zu haben. -Nach dem Reset/powerup dauert es ueblicherweise sehr lange bevor man ueberhaupt zugreifen darf. Das kann in die Hunderten von ms gehen. -dann kommt das Reset Command, und wieder dauert es sehr lange bis man weitermachen darf. -die Adresse der zweiten Zeile beginnt bei 0x40 -Ready ist nicht noetig, ich verwende einen festen timerinterrupt und schreibe meinen Buffer periodisch in den Display. -Dann muss die Kontrastspannung im richtigen Bereich liegen.
Zwölf M. schrieb: > -Nach dem Reset/powerup dauert es ueblicherweise > sehr lange bevor man ueberhaupt zugreifen darf. > Das kann in die Hunderten von ms gehen. Da werden wohl die 17ms dafür da sein. Ich benutze 15ms und das funktioniert "bisher" mit allen Displays. Zwölf M. schrieb: > -dann kommt das Reset Command, und wieder dauert > es sehr lange bis man weitermachen darf. 4500us bei Teo, 5ms bei mir. Bin mir aber wegen den TRIGGER und LCD_ENABLE nicht 100% sicher, wie oft das RESET bei Teo dann geschrieben wird. Bei mir sieht das so aus:
1 | void LCD_Init(void) |
2 | {
|
3 | LCD_RW = 0; LCD_RW_DIR = 0; |
4 | LCD_RS = 0; LCD_RS_DIR = 0; |
5 | LCD_E = 0; LCD_E_DIR = 0; |
6 | |
7 | LCD_PINS_DIGITAL(); |
8 | LCD_DIR_OUT(); |
9 | |
10 | LCD_busy_cnt = 1; // busy_flag time out counter |
11 | |
12 | LCD_DELAY_5MS();LCD_DELAY_5MS();LCD_DELAY_5MS(); // wait for 15ms |
13 | // display reset procedure
|
14 | LCD_Write_Nibble(LCD_RESET); LCD_DELAY_5MS(); |
15 | LCD_Write_Nibble(LCD_RESET); LCD_DELAY_5MS(); |
16 | LCD_Write_Nibble(LCD_RESET); LCD_DELAY_5MS(); |
17 | |
18 | LCD_Write_Nibble(FOUR_BIT); while(LCD_Busy()){;} // wait |
19 | |
20 | LCD_Command(FOUR_BIT_TWO_LINE); |
21 | |
22 | LCD_Command(DISPLAY_CTRL + DISPLAY_ON);// + BLINK_ON); |
23 | LCD_Command(ENTRY_MODE + CURSOR_INC + DSHIFT_OFF); |
24 | LCD_Clear(); |
25 | LCD_Home(); |
26 | }
|
Zwölf M. schrieb: > Eine kleine Erfahrung meinerseits, ohne das Datenblatt des LCD genauer > betrachtet zu haben. Na dann danke für die guten Tips. ;) Ja alles schon mal gemacht und funst. Gefällt mir aber nicht! Zwölf M. schrieb: > -die Adresse der zweiten Zeile beginnt bei 0x40 ??? Vielen Dank für die Anfänger-Tips. ABER eigentlich hoffe ich das sich das mal einer ernsthaft ansieht. Sicher irgend ein DUMMER Fehler wirds schon sein, nur ICH erkenne ihn nicht. Teo D. schrieb: > Karl B. schrieb: >> Das eine Missverständnis bei der Doku ist: >> ... > > Nö, kein Missverständnis. Das ist leider nur die Hoffnung eines Unwissenden Selbstzweiflers....
Teo D. schrieb: > ABER eigentlich hoffe ich das sich das mal einer ernsthaft ansieht. Also das was du da mit TRIGGER machst, ist mir z.B. ein Rätsel.
Ich hab hier mal einen einfachen und zuverlässigen Code gepostet: http://www.avrfreaks.net/forum/tutc-lcd-tutorial-1001
Volker S. schrieb: > Da werden wohl die 17ms dafür da sein. > Ich benutze 15ms und das funktioniert "bisher" mit allen Displays. Ob 15ms oder 1h sollte egal sein. Hatte da auch erst 15ms, dann aber zur Sicherheit verlängert. Volker S. schrieb: > 4500us bei Teo, 5ms bei mir. Bin mir aber wegen den TRIGGER und > LCD_ENABLE nicht 100% sicher, wie oft das RESET bei Teo dann geschrieben > wird. Dito. Enable rüttelt nur am Enable-Pin, mit 1µs Pause. #define LCD_ENABLE {LCD_Enable_SetHigh();__delay_us(1);LCD_Enable_SetLow();}// delay=tDDR Der TRIGGER ist nur zur besseren Orientierung im LA-Plot eingefügt. Rüttelt auch nur an einem Pin. Tut nichts am LCD, verlängert nur etwas das Timing. #define TRIGGER {TEST_Trigger_SetHigh(); TEST_Trigger_SetLow();}
Teo D. schrieb: > Der TRIGGER ist nur zur besseren Orientierung im LA-Plot eingefügt. Habe ich inzwischen auch schon vermutet. Am Anfang dachte ich, das wäre das selbe wie ENABLE nur ohne delay.
Ja, der Hinweis viel da wohl etwas knapp aus. :) Teo D. schrieb: > (Der Trigger sitzt vor Enable o. vor der Bussy-Prüfung.) Soll heißen, solange keine Bussy-Prüfung möglich, sitzt er vor dem Enable, dann vor der Bussy-Prüfung.
:
Bearbeitet durch User
Dein LCD_Küsschen ist falsch. Es müssen beim Busy-Test immer 2 Nibble gelesen werden, sonst bist Du aus dem Takt. Das BF ist im ersten Nibble (Seite 22, Figure 9 4-Bit Transfer Example). Und mitten drin im LCD_WRITE geht schonmal gar nicht, sondern nur danach. Der Busy-Test geht frühestens auf den ersten Befehl nach dem Setzen des 4Bit-Mode. D.h. bis einschließlich des 4Bit-Kommandos darf nur mit Delay gearbeitet werden.
Ich glaub der peda hat in beiden Punkten Recht ;-) (Ist bei mir auch so)
:
Bearbeitet durch User
Peter D. schrieb: > Nö. > Die Hauptfehlerursache (zu 99,99%) ist eine fehlerhafte Initsequenz. > Das original HD44780 Datenblatt ist da leider etwas unpräzise. Kein > Zugriff darf ohne Wartezeit direkt auf den vorherigen folgen. > Insbesondere im 4Bit-Mode ist ein sauberes Init essentiell. nö, auf Seite 45 ist es eindeutig beschrieben !!
die anderen Wartezeiten stehen bei der "Befehlsübersicht". Damit ist ein exaktes Timing kein Problem. Bleibt nur die Frage ob der Controller auf dem Display auch original ist...
Peter D. schrieb: > Dein LCD_Küsschen ist falsch. Es müssen beim Busy-Test immer 2 Nibble > gelesen werden, sonst bist Du aus dem Takt. Ich denk auch das war der Fehler. Völlig aus den Augen verloren, das mit dem Synchron bzw. immer Paarweise auslesen/schreiben der Nibble. Erklärt auch das unterschiedliche verhalten, je nach dem wann er dann halt aus dem Tritt kommt. War mir da nie sicher (hab das anfänglich so gemacht, im laufe der Fehlersuche/Tests...) und sah ES Antwortet ja. Das dies eventuell nur die halbe Wahrheit ist.... Ojeh, was für ne Dummheit. (Wenns das aber doch nich bringt, geht was kaputt!) DANKE! PS: Kann erst Heut Abend weiter testen... PPS: Stephan schrieb: > die anderen Wartezeiten stehen bei der "Befehlsübersicht". > Damit ist ein exaktes Timing kein Problem. > Bleibt nur die Frage ob der Controller auf dem Display auch original > ist... Hab das Original Dabla vom Modul. War einer der ersten Prüfungen.
Stephan schrieb: > nö, auf Seite 45 ist es eindeutig beschrieben !! Falsches Bild, da: "Figure 23 8-Bit Interface" Und genau das ist die Stelle, die viele falsch verstehen: "BF can be checked after the following instructions." Soll heißen, erst nach den nächsten! In dem Bild fehlt also ein weiteres "Wait for more than 100 μs" vor dem letzten Block.
Peter D. schrieb: > Soll heißen, erst nach den nächsten! > In dem Bild fehlt also ein weiteres "Wait for more than 100 μs" vor dem > letzten Block. Ty. Sieht im Dabla schon merkwürdig aus, nach dem ersten Bussy-Test nur ein Nibble zu übertragen. Hielt aber die Lücke für eindeutig. :( Dann werd ich mal IMMER paarweise rütteln und den ersten Bussy-Test durch ein Delay >100µs ersetzen.
Ich habs doch gewusst. Das kann ja wohl nich angehen! Wie DÄMLICH muss man eigentlich sein, um zu glauben das nach dem ersten auslesen des Bussy, durch auslesen des OBERN Nibble, der nächste Lesebefehl WIDER das OBERE Nibble liefert? Ich mach den Scheiß einfach viel zu selten, völlig eingerostet der Denkapparat. Nochmals VIELEN DANK, für den Tritt in den Ars..! :D
Peter D. schrieb: > Und genau das ist die Stelle, die viele falsch verstehen: > "BF can be checked after the following instructions." > Soll heißen, erst nach den nächsten! > In dem Bild fehlt also ein weiteres "Wait for more than 100 μs" vor dem > letzten Block. Uuups, hab ich so auch noch nicht gelesen. Also es funktioniert zwar seit 20 Jahren ohne, aber vielleicht nur Glück? Scheint auch nicht bei allen "kompatiblen" so zu sein. Im Datenblatt von einem ST7036 gibt es keinen solchen Hinweis.
Hi, RS auf GND und R/W getoggelt? hmmm bei mir ist's genau andersherum. PB7 PB6 PB5 PB4 PB3 PB2 PB1 PB0 R/Wquer=GND ; D7 D6 D5 D4 LED n/c ENA RS ciao gustav
Teo D. schrieb: > Wie DÄMLICH muss man eigentlich sein, um zu glauben das nach dem ersten > auslesen des Bussy, Wenn ich mich richtig erinnere, bin ich darauf vor vielen Jahren auch mal reingefallen, als ich meine Bibliothek von Assembler auf C umgestellt habe und dachte: "Wozu lese ich das eigentlich noch mal, das brauch ich ja gar nicht" Hat natürlich gleich aufgehört zu funktionieren ;-)
Volker S. schrieb: > Uuups, hab ich so auch noch nicht gelesen. > Also es funktioniert zwar seit 20 Jahren ohne, aber vielleicht nur > Glück? Das Bussy auszulesen ist ja auch nich wirklich der Bringer. Nur mit Delays hat man das Problem ja nicht und auch nur in der Init und da werden die meisten erstmal durchwegs Delays nutzen!? Deswegen hat ja bei mir mit Assembler ja immer funktioniert.
Volker S. schrieb: > "Wozu lese ich das eigentlich noch mal, das brauch ich ja gar nicht" > Hat natürlich gleich aufgehört zu funktionieren ;-) Ich denke wenn der erste Enable ein Ready liefert, kann darauf ein Schreibbefehl folgen. Nur wenn der Bussy gesetzt ist, MUSS natürlich erstmal noch das untere Nibble ausgelesen werden, bevor man wieder das obere inkl. Bussy erhält.
Teo D. schrieb: > Deswegen hat ja bei mir mit Assembler ja immer funktioniert. Auch meine Assembler Bibliothek hat schon das Busy abgefragt (und freie Wahl bei den Datenpins).
Hi, Bildchen dazu. Die Kanallegende zeigt RS, wo ich R/WQuer vermute. R/WQuer für die Busyflag-Abfrage. (Die kommt zu früh.) Nach jedem Befehl einen Enable Impuls. Beim Vierbit-Modus dann pro Byte zweimal. Oder besser, pro Nibble jedesmal einen. (Das ist in der Doku im Timingdiagramm auch ein wenig missverständlich formuliert. SEite 22, Figure 9) "...The busy flag must be checked (one instruction) after the 4-bit data has been transferred twice. Two more 4-bit operations then transfer the busy flag and address counter data..." (Muss noch ein anderes Datenblatt heraussuchen, da ist es etwas deutlicher beschrieben, was damit gemeint ist.) ciao gustav
:
Bearbeitet durch User
Funst! :D So das war ja wieder mal wat. (Hab natürlich erst mal nach links geshiftet, natürlich erstmal aufgeregt...:) Peter D. schrieb: > Und genau das ist die Stelle, die viele falsch verstehen: > "BF can be checked after the following instructions." > Soll heißen, erst nach den nächsten! > In dem Bild fehlt also ein weiteres "Wait for more than 100 μs" vor dem > letzten Block. Hab das nu MIT Bussy-Prüfung an dieser Stelle am laufen. Das Dabla scheint da keines Wegs missverständlich zu sein. Antwortzeit ~32ms. Das mit dem IMMER paarigen auslesen des Bussy-Flags ist auch nicht nötig. Das umschalten der Register, resetet das wie erwartet. Vielen Dank nochmals an ALLE! Habt mich da wirklich aus ner Endlosschleife gerettet, das hätte noch Tage dauern können. PS: Wenn's nich so umständlich und unelegant geschrieben wäre, würde ich die Init ja mal posten. So aber nur unter Waffenandrohung. :)
Teo D. schrieb: > Das mit dem IMMER paarigen auslesen des Bussy-Flags ist auch nicht > nötig. > Das umschalten der Register, resetet das wie erwartet. Meinst du damit RS umschalten? Ist es nicht einfacher nochmal einen Enablepuls drauf zu hauen?
Teo D. schrieb: > Das mit dem IMMER paarigen auslesen des Bussy-Flags ist auch nicht > nötig. > Das umschalten der Register, resetet das wie erwartet. Bei manchem Clone mag das gehen, bei einem original HD44780 aber nicht. Setzt man immer nur den gleichen LCD-Typ ein, ist das kein Problem. Will man aber universell bleiben, sollte man auf diese minimale Codeeinsparung besser verzichten. Man liest hier oft Fragen, warum eine LCD-Lib bei anderen LCDs plötzlich nicht mehr funktioniert. Es wird dann gerne mal auf den Händler geschimpft, warum der defekte LCDs liefert. Dabei sitzt das Problem vor dem PC. Ich benutze allerdings immer nur 6 IO-Pins zum LCD, d.h. RW liegt fest auf GND. Oder 3 IO-Pins und einen 74HC164.
Peter D. schrieb: > ch benutze allerdings immer nur 6 IO-Pins zum LCD, d.h. RW liegt fest > auf GND. Oder 3 IO-Pins und einen 74HC164. wie ich auch. Ich schreibe immer nur. In einer Schleife im Int.das Display liegt 1:1 im RAM und ich muss mich nur um den RAM kümmern. der Rest läuft allein.
Stephan schrieb: > wie ich auch. Ich schreibe immer nur. In einer Schleife im Int.das > Display liegt 1:1 im RAM und ich muss mich nur um den RAM kümmern. der > Rest läuft allein. Das ist schon gut, aber in der Lehre ein wenig zu viel des Guten ;-) Wenn jemand der mit Mikrocontrollern gerade angefangen hat zu arbeiten und das erste mal ein LCD benutzen soll, dazu vorher erst mal das Abbild im RAM anlegen soll und den Timer, der dann immer zeichenweise für die Auffrischung sorgt...
Teo D. schrieb: > Das mit dem IMMER paarigen auslesen des Bussy-Flags ist auch nicht > nötig. Ok, wenn es bei Dir klappt. Gratulation. OT/(Google Übersetzer liefert mir bei "bussy" nichts nur bei "busy"=beschäftigt. Das nur ganz nebenbei. Hätte ja auch etwas sein können, was ich noch nicht kenne. Bei den "neudeutschen" Begriffen muss man höllisch aufpassen.)/OT Das "Ich-bin-noch-beschäftigt-Signal" macht, wenn man die Forenbeiträge durchliest, garnicht so selten Probleme. Dazu möchte ich etwas weiter ausholen: Die HD44780-Schnittstelle lehnte sich zu Entwicklerzeiten an die damals üblichen Centronics-Drucker-Parallelschnittstellen an. Dazu unterschied man zwei Gruppen von Signalen: "Reine" Daten- und die Datenfluss-Kontroll-Bits. Für letztere benutzt ein Drucker "Acknowledge" (Input) und "Busy"(Output). Also beim HD44780-Standard "Enable"(Input) und "Busy"(Output). Da man aber Portbits einsparen wollte, kam man auf die Idee, durch Umkonfigurieren des Ports das Busy-Signal softwaremäßig auszulesen. Der Vorteil, dass das Display dadurch schneller würde, ist für die meisten Anwendungszwecke derart gering, dass er oft gar nicht ausgenutzt wird. (Hätten die HD44780-Standard-Entwickler geahnt, dass das so ist, hätten sie doch lieber hardwaremäßig ein Portbit mehr spendiert, könnte ich mir gut vorstellen.) Wieso? Das ist für mich der größte Knackpunkt, man muss die Ports bidirektional ausführen und softwaremäßig im Programm zwischen "Eingang" und "Ausgang" umkonfigurieren. Ich brauche dazu das R/WQuer-Portbit zusätzlich, im anderen Falle kann ich es einfach auf GND legen, brauche kein MCU-Portbit zu opfern. Das Programm wird dadurch auch umfangreicher. Ob das den Zeitgewinn rechtfertigt, weiß ich nicht. Der unbestrittene Vorteil: Der Displaycontroller bestimmt den Datenfluss selbst und ist nicht auf externe, ungenauere Zeitschleifen im Programm angewiesen. Diese sind aber bei der Initialisierung so oder so notwendig. Meine Standard-Portbelegung ist: PB7 PB6 PB5 PB4 PB3 PB2 PB1 PB0 R/Wquer=GND D7 D6 D5 D4 LED n/c ENA RS (Damit kann ich sogar mit einem Terminalprogrämmchen via PC im Vierbit-Modus über den UART mit 9k6-8N1 direkt auf das Display schreiben. Ohne dass ich den Eindruck gewinne, dass Zeichen verschluckt würden. So schnell ist die Anzeige.) ciao gustav
:
Bearbeitet durch User
Karl B. schrieb: > OT/(Google Übersetzer liefert mir bei "bussy" nichts nur bei > "busy"=beschäftigt. Das nur ganz nebenbei. Hätte ja auch etwas sein > können, was ich noch nicht kenne. Bei den "neudeutschen" Begriffen muss > man höllisch aufpassen.)/OT OT/ Ja ich bin ein Trottel. Danke für die Belehrungen, ich bin wirklich ein Ahnungsloser, kann ja garnicht anders sein, kann ja nich mal richtig schreiben und bilde mir ein, ich könne einen µC Programmieren. Ein naiver Trottel halt.. /OT Karl B. schrieb: > (Das ist in der Doku im Timingdiagramm auch ein wenig missverständlich > formuliert. SEite 22, Figure 9) Dafür hübsch gezeichnet. Wenn man Enable hoch zieht steht (meist) wenige ns (lieber 500ns warten)das BF an. Lesen muss (sollte) man logischerweise wenn Enable Hi ist. Auch wenn die Daten noch nach der fallenden Flanke von Enable noch anstehen, sicher is das nich. Das scheinen viele so zu machen, rütteln->lesen, kann natürlich schnell zu Timing Probleme kommen. Beim Schreiben is es ja egal wenn die Daten schon vorher anliegen und gerüttelt wird. Karl B. schrieb: > Der Vorteil, dass das Display dadurch schneller würde, ist für die > meisten Anwendungszwecke derart gering, dass er oft gar nicht ausgenutzt > wird. Teo D. schrieb: > Das Bussy auszulesen ist ja auch nich wirklich der Bringer. Tja, is halt nur Spielzeug, will ich haben, selber gemacht. Bei mir kommt außer Pommes auch kein TK Misst auf den Tisch. Volker S. schrieb: > Meinst du damit RS umschalten? > Ist es nicht einfacher nochmal einen Enablepuls drauf zu hauen? Ja,da sollte RW stehen. Einfacher, nein. BF lesen -> schreiben. Warum da noch irgend wo rumrütteln.
Teo D. schrieb: > Einfacher, nein. BF lesen -> schreiben. Warum da noch irgend wo > rumrütteln. Na ja, wenn das Busy-Flag "Busy" zeigt, dann ließt man ja normalerweise wieder und wieder, ohne vorher zu schreiben. (Also ich mach das so) Beim nächsten Lesen, will ich ja wieder das BF (bit7) und nicht bit3.
:
Bearbeitet durch User
Teo D. schrieb: > Teo D. schrieb: >> Das Bussy auszulesen ist ja auch nich wirklich der Bringer. > > Tja, is halt nur Spielzeug, will ich haben, selber gemacht. > Bei mir kommt außer Pommes auch kein TK Misst auf den Tisch. Grundsätzlich jeder nach seinem Gusto. Das Busy-Flag ist schon ne nette Sache, damit kann man ganz gut die Unterschiede von Display zu Display auffangen. Sofern die Möglichkeit besteht (bi-direktionale Anbindung des LCD-Datenbus) sollte man es schon nutzen. Wenn nicht muss man halt die Timings mächtig aufweiten um allen möglicherweise verwendeten LCDs (bei den möglichen Einsatztemperaturen) gerecht zu werden. (Insbesondere da die Lebensdauer der LCD Hintergrundbeleuchtung bei den transmissiven Ausführungen erfahrungsgemäß stark schwankt... und für einen Euro wird man wohl eher das Display tauschen anstatt da dran rumzumachen) Gruß Dominik
Peter D. schrieb: > Ich benutze allerdings immer nur 6 IO-Pins zum LCD, d.h. RW liegt fest > auf GND. Oder 3 IO-Pins und einen 74HC164. Dito, wollt das aber halt mal machen. Dito, so habe ich mein allererstes LCD auf einem 16f84 programmiert. Schien mir als Übung sonst zu einfach und viel zu viele Pins. :) Das Busy-Flag lesen heißt ja auch dieses zu beherrschen. Nur fällt mir nich wirklich was zu ein. Die Cursor Adresse auslesen, könnte manchen Situationen praktisch sein? Peter D. schrieb: > Bei manchem Clone mag das gehen, bei einem original HD44780 aber nicht. Angeblich arbeite ich mit einem Original? Funst aber auch mit einem L1652. Das Dabla unterscheidet sich in diesem Punkt auch nicht. Ich denke bei so vielen Derivaten ist einfach Erfahrung nötig. Volker S. schrieb: > Na ja, wenn das Busy-Flag "Busy" zeigt, dann ließt man ja normalerweise > wieder und wieder, ohne vorher zu schreiben. (Also ich mach das so) > > Beim nächsten Lesen, will ich ja wieder das BF (bit7) und nicht bit3. Ja klar! Warum meinst du ist dieser verfik.... Thread entstanden? :D Natürlich muss man vor dem ZWEITEN auslesen des BFs, erstmal das untere Nibble beseitigen. Das war echt peinlich Man. Nur wenn das BF nicht gesetzt ist, muss man auch nicht das untere Nibble lesen. Es folgt ja ein Schreibbefehl, der den Nibble-Counter resetten (sollte er zumindest).
Teo D. schrieb: > Nur wenn das BF nicht gesetzt ist, muss man auch nicht das untere Nibble > lesen. Es folgt ja ein Schreibbefehl, der den Nibble-Counter resetten > (sollte er zumindest). Ah ok, die Unterscheidung wäre mir dann schon zu viel, bzw. habe ich gar nicht darüber nachgedacht...
Volker S. schrieb: > Ah ok, die Unterscheidung wäre mir dann schon zu viel, > bzw. habe ich gar nicht darüber nachgedacht... Ditio :D Muss ja auch nich sein, einfach den Stiefel durchziehen, vereinfacht das auch. :) Spart bei mir auch nur ~5µs. War da ja grad am popeln und wollte wissen ob ich das Dabla richtig interpretiere. Man sollte immer etwas mehr wissen als man braucht, um nicht in scheinbar unlösbare Situationen zu geraten. Und hier ist eh nur der Weg das Ziel....
Teo D. schrieb: > Die Cursor Adresse auslesen, könnte manchen > Situationen praktisch sein? Naja, die meisten LCD mit dem Hitachi sind ja so klein, das man da nicht gross durcheinander kommt. Wenn man dann doch mal ein 4*40 hat, dann kann man sich das vermutlich leichter mit 2 Variablen im MC merken, als das Zeug zurück aus dem langsamen Display zu lesen. Bei den DOGM132 mit SPI mache ich das immer so, das sind aber auch reine Grafik LCD.
:
Bearbeitet durch User
Teo D. schrieb: > War da ja grad am popeln und wollte wissen ob ich das Dabla richtig > interpretiere. > Man sollte immer etwas mehr wissen als man braucht, um nicht in > scheinbar unlösbare Situationen zu geraten. > Und hier ist eh nur der Weg das Ziel.... Kenn ich.
Matthias S. schrieb: > Wenn man dann doch mal ein 4*40 hat, dann kann man sich das vermutlich > leichter mit 2 Variablen im MC merken, als das Zeug zurück aus dem > langsamen Display zu lesen. Das teil stammt halt aus Zeiten, in denen Ram noch rar war. :) Und hör auf mir meine super tolle Erkenntnis, wie ich das Ding auslese, madig zu machen! Das hat viele Stunden und noch mehr Selbstzweifel gekostet. :D (letzteres scheinbar berechtigt:()
Teo D. schrieb: > Das teil stammt halt aus Zeiten, in denen Ram noch rar war. :) Naja, ehrlich gesagt, selbst beim 8048 wäre noch genügend RAM für X und Y dagewesen und bei meinem Favoriten 8051 damals wars ein Klacks. Selbst das Busy Flag wurde von mir ignoriert, weils einfach schneller ging, wenn man einfach die Timings aus dem Datenblatt beachtete und schrieb, so schnell es erlaubt war. Teo D. schrieb: > Und hör auf mir meine super tolle Erkenntnis, wie ich das Ding auslese, > madig zu machen! Mir tut es ja auch leid um die Zeit, die du da reingesteckt hast, aber das hier ist nun mal keine Sonntagsschule, sondern die MC.net Folterkammer, die immer noch Salz reinstreut, wo es weh tut :-P
:
Bearbeitet durch User
Matthias S. schrieb: > Mir tut es ja auch leid um die Zeit, die du da reingesteckt hast, aber > das hier ist nun mal keine Sonntagsschule, sondern die MC.net > Folterkammer, die immer noch Salz reinstreut, wo es weh tut :-P Warum tut Dir das leid tuts ja noch nich mal mir. ;) Ne was nur immer wieder ärgerlich ist, das ich immer an so simplen Dingen hänge, wie ein blinder Fleck, den ich einfach nicht sehen will. Und das geht garnich, selbst wenn ich mich in aller Öffentlichkeit, einer solchen Demütigung aussetzen muss. > das hier ist nun mal keine Sonntagsschule, sondern die MC.net > Folterkammer, die immer noch Salz reinstreut, wo es weh tut :-P Jo, da braucht man nich meckern, wenn man mal selber was abbekommt. ;P skorpionx schrieb: > Teo D. schrieb: >> ? > > Das funktioniert... Meins auch! Zu spät gepostet!?
Hi, wollte es auch einmal probieren: Also: Portbit freimachen für R/Wquer Die Routine Busyflagabfrage direkt hinter die Routine Zeichenausgabe an LCD, bzw. Befehl an LCD. Busyflagabfrage: Erst Port zum Eingang konfigurieren Enable high Daten auslesen (oberes Nibble mit B7) Enable low ein paar nops zur Stabilisierung des Ports Enable high Enable low ohne Daten auszulesen (unteres Nibble einfach ignorieren) Sprung in Schleife, so lange B7 gesetzt ist. (oder mit "rol" B7 in Carry schieben und Carry abfragen, was im Endeffekt auf dasselbe herauskäme) Und Port wieder zumn Ausgang machen etc. So sieht der code dann aus: busyflag: push temp ldi temp, 0x0F out ddrb, temp out daten, temp cbi daten, rs sbi daten, rw ; busyflag1: sbi daten, ena nop nop nop nop nop in temp, daten nop nop cbi daten, ena nop nop nop nop nop sbi daten, ena nop nop nop nop cbi daten, ena nop nop sbrc temp, 7 rjmp busyflag1 nop nop nop ldi temp, 0xFF out ddrb, temp cbi daten, rw nop nop sbi daten, rs pop temp ret Wieso die ganzen nops? Weil ich meine, dass die Umschalterei von Ausgang zu Eingang etc. Reflexionen auf dem Draht produziert. Also auch das Übersprechen der Steuerbits (ohne Busabschluss). Eben die Verdrahtung! ("Nur" 20 cm) Also, es wird mir zumindest das erste Zeichen verschluckt. (Siehe Bildchen) Habe jetzt das Label Busyflag wieder durch die passende Warteschleife ersetzt, und es läuft wieder so wie ich das gewöhnt bin. ciao gustav P.S.: Da ich der Meinung bin, dass das Enable-Bit ein Transition state Bit ist, also der Wechsel von High nach Low hier das Entscheidende ist, habe ich auch die Routine 'mal entsprechend ausprobiert, es geht dann noch schlechter. Es ist dann - zumindest in diesem Zusammenhang - also doch ein "Current State" Bit. (Steht aber nirgends in der Doku.)
:
Bearbeitet durch User
Edit: Hi, nur zur Vervollständigung: es muss so richtig heißen: wait3: ;Verzoegerungsschleife 3 push xl push xh push temp ;Register sichern auf Stapel push temp1 ;Sicherung von Temporaerregistern in temp1, SREG ;und Statusregister auf Stapel push temp1 ;bei Interrupts notwendig ldi xl, low(zeit1) ;laedt Zaehlregisterpaar mit ldi xh, high(zeit1) ;oben deklariertem Wert "Zeit1" ;ldi zl, low(zeit1) ;laedt Zaehlregisterpaar mit *falsches Register!* ;ldi zh, high(zeit1) ;oben deklariertem Wert "Zeit1" rjmp repeatx Aber ändert nichts am Problem. ciao gustav
Karl B. schrieb: > also der Wechsel von High nach Low hier das Entscheidende ist, Genau so ist das, sieht man auch im Zeitdiagramm. Daten werden mit der fallenden Flanke übernommen, ausgegeben bei der steigenden. Karl B. schrieb: > cbi daten, ena > nop > nop > sbrc temp, 7 > rjmp busyflag1 Wie lang dauert ein nop?... tADD nicht eingehalten? tADD = Die Zeit die der Adrescounter zum weit erzählen braucht, nachdem das Busy-Flag auf Low geht (~5-10µs). PS: Deine Prosa und Bild bring ich grad nicht in Einklang!? Der Rest iat leider auch nich viel klarer.
:
Bearbeitet durch User
Teo D. schrieb: > Daten werden mit der fallenden Flanke übernommen, ausgegeben bei der > steigenden. Hi @Th, genau das ist mein Denkfehler. (Ich steh' soo kurz davor, das zu lösen...das ist immer soo blamabel.) Danke nochmals für den Tip mit dem Adresscounter. Dann hatte ich noch nen dicken Bug drin, wie gesagt, das Doppelregister bei der einen Zeitschleife falsch. Die wird bei der Init Routine glücklicherweise nicht am Anfang gebraucht. Ich merkte das daran, dass die Hintergrundbeleuchtung am Ende nicht blinkt. Also musste das irgendwo hängen geblieben sein. Bei der Zeitschleife. Und nicht etwa bei der Busy-Flag-Abfrage. Teo D. schrieb: > Deine Prosa und Bild bring ich grad nicht in Einklang!? Das "T" fehlt im Bild. Der Erste Buchstabe des Tabellen-Strings wurde "geschlabbert". Teo D. schrieb: > Der Rest iat leider auch nich viel klarer. Die Sache mit den "unsauberen" Impulsen auf dem Port. Müsste echt noch einmal mit dem Oszi dran, und mir die Sache anschauen. Ursachen: Irgendwelche Kontaktfehler, am selben Port Ausgänge und Eingänge die sich vielleicht gegenseitig verkoppeln. Weiß nicht. Die Flachbandleitung ist mit ca. 20 cm vielleicht schon zu lang. (Stichwort Busabschluss.) ciao gustav
Karl B. schrieb: > Die Flachbandleitung ist mit ca. 20 cm vielleicht schon zu lang. > (Stichwort Busabschluss.) Kann da nur was ohne BF Abfrage zu sagen sagen. Da gibst kaum Probleme. Steckbrett, Display, ~40cm Flachband, 2. Display, keine Problem. Wenn du da rumspielst, gib bitte laut wie's mit BF aussieht. Dann muss ich vielleicht irgend wann, mein Oszi nicht bemühen. :)
Teo D. schrieb: > Wenn du da rumspielst, gib bitte laut wie's mit BF aussieht. Hi, das ist mir jetzt noch aufgefallen: Es kann nur an der Verdrahtung liegen, bzw. an der MCU-Portbeschaltung. Beim Flashen kommt bei gestecktem Portstecker: "An Error has occured." Ziehe ich den Portstecker, ist die Fehlermeldung weg und es wird wie gewohnt geflasht. Dann hab' noch einen Tip gelesen: Man kann das Watchdog-Timout in die BF-Abfrage einbauen. Damit ist sichergestellt, dass das Programm nicht in der BF-Routine hängenbleibt. Zumindest resettet sich die MCU dann und durchläuft die Initialisierung erneut. Dazu ist aber zu beachten, dass aufgrund Bestehenbleibens der Versorgungsspannung der POSR vom LCD nicht durchlaufen wird. Mit Portreset und dreimal hex 30 bzw. 03 und Warteschleifen fängt es dann wieder an. Aber das war ja schon klar. ciao gustav
Hi, da ich den Port in Verdacht hatte, schaute einmal eine alternative Initialisierungsroutine an. (Die fand ich in der Literatur.) Teo D. schrieb: > Ne was nur immer wieder ärgerlich ist, das ich immer an so simplen > Dingen hänge... Und interessant, obwohl es im Buch vor Programmbeispielen nur so wimmelt, finde ich kein einziges für eine Busyflagabfrage. Da stehen wir also gar nicht einmal so "dumm" da. Scheint so, als ob sich sogar ein renommierter Fachbuchautor um diese Sache herummogelt. Noch ein Fallstrick: Der durch Port-Bit-Setzen auf "Eins" gesetzte "rs" wird durch die nachfolgenden Ausgabe wieder mit der "Null" des ausmaskierten "oberen" Ports-Nibbles überschrieben, so dass das Display ständig im Befehls-Modus steht. Das bedeutet, dass im Charakter-Übergabemodus dass Rs-Impuls-Setzen hinter der Datenausgabe aber vor dem Enable-Impuls stehen muss. Und da könnte es mit dem Timing evtl. eng werden. Daher wurde in die Enableimpuls-Routine vorher und hinterher noch "nop" gesetzt. Die Code-Schnipsel sind im Anhang. (Und man braucht kein zweites "swap"... entgegen der Feststellung im Buch.) ciao gustav
Karl B. schrieb: > Noch ein Fallstrick: > Der durch Port-Bit-Setzen auf "Eins" gesetzte "rs" wird durch die > nachfolgenden Ausgabe wieder mit der "Null" des ausmaskierten "oberen" > Ports-Nibbles überschrieben, so dass das Display ständig im > Befehls-Modus steht. Daher habe ich meine LCD-Lib so geschrieben, daß sie nur Bitbefehle benutzt. Viele MCs können einzelne Bits atomar setzen, d.h. ohne Seitenefekte auf andere Bits des selben Ports.
Freut mich wenns nu bei dir klappt. :) Karl B. schrieb: > Da stehen wir also gar nicht einmal so "dumm" da. Wir vielleicht nicht, aber der, der vergessen hat das zweite Nibble auszulesen, lacht Heut noch über sich. :D
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.