Hallo, Ich versuche mit einem Attiny2313, ein Pollin-LCD TC1602A im 4-Bit-Modus anzusprechen. Direkt mal vorneweg: Ich sehe Text ! Verwendet habe ich (nach zig eigenen Tests) den SourceCode aus dem GCC-Tutorial. Angepaßt auf meine Pins (Port B). Mein Problem liegt nun darin, das bestimmte Zeichen nicht richtig angezeigt werden, allerdings in seltsamen Konstellationen. Das hier ist mein Hauptprogramm int main(void) { // Initialisierung des LCD int z=1,s=0,c=0; lcd_init(); // Teil 1 lcd_data(0x30); lcd_data('0'); lcd_string("0@P0@P0@P0@P"); _delay_ms(1000); lcd_clear(); // Teil 2 while(1) { if (s==16) { s=0; z++; if (z==3) z=1; lcd_setcursor(s,z); } lcd_data(c); _delay_ms(500); c++; s++; } return 0; } Die Ausgabe nach dem ersten Teil sieht absolut sauber aus. Es erscheinen genau die Zeichen auf dem Display. Jetzt das Problem: Die Ausgabe im zweiten Teil produziert bei jedem Zeichen, das im unteren Nibble eine 0 hat ein falsches Zeichen. Mittlerweile habe ich auch raus, was schief läuft: 0x30 - 0xf3 (Befehl - Anzeige) 0x40 - 0xf4 0x50 - 0xf5 usw. D.h. in den Fällen wo das untere Nibble 0 ist, sendet der Controller das entsprechend falsche Zeichen. Sieht für mich so aus, als ob in dem Fall das Verschieben der Nibbles nicht hinhaut. Ich verstehe nur nicht WARUM ? Das ausgeben von Hex 30 vor der Schleife funktioniert, in der Schleife nicht mehr. Ich dachte an Optimierungen und habe es mit allen Einstellungen probiert. Bei allen das gleiche Ergebnis. Der attiny läuft mit 8 MHz, Fuses sind korrekt, Nutze AVR Studio mit Atmel MKII. Bin für Tips dankbar.
Hi
>lcd_data(c);
Welchen Datentyp erwartet denn 'lcd_data'? Mit Sicherheit kein 'int'.
MfG Spess
Hm, wie wär es mit der itoa-Funktion? Außerdem hast du bei if(z==3) eine Klammer vergessen.
L. J. schrieb: > Außerdem hast du bei if(z==3) eine Klammer vergessen. Ups ja, die Klammer ist beim kopieren da rausgerutscht, sorry. > Welchen Datentyp erwartet denn 'lcd_data'? Mit Sicherheit kein 'int'. Ist definiert als UINT8_T Die Funktion und die Übergabe funktionieren ja generell bei fast allen Zeichen.. Wenn ich jetzt den String in der Schleife unten ausgebe, produziert der auch Müll bei allen Zeichen die auf 0x?0 enden. Dieses "Rundschreiben" aller Zeichen hatte ich zum Debuggen eingebaut. Aufgefallen ist es, als ich in einer Schleife wechselweise zwei Strings ausgeben wollte.
L. J. schrieb: > Hm..was hast du denn jetzt genau geändert? Meinst du im letzten Beitrag ? Da hab ich nur die Zeile eingefügt mit dem Bezug zu deinem Eintrag und itoa ;)
Beschränk dich doch erstmal auf gängige druckbare Zeichen (ASCII
0x20..0x7F). Könnte ja gut sein, dass andere Zeichen als Steuerzeichen
interpretiert werden.
> lcd_data(c);
Für Variable "c" den Wertebereich einschränken.
Andreas Peters schrieb: > Verwendet habe ich (nach zig eigenen Tests) den SourceCode aus dem > GCC-Tutorial. Angepaßt auf meine Pins (Port B). Dann zeige ihn auch (komplettes compilierbares Programm als Dateianhang). Wie soll man denn sonst den Fehler finden? Peter
> Dann zeige ihn auch (komplettes compilierbares Programm als > Dateianhang). Hängt jetzt hier dran > Beschränk dich doch erstmal auf gängige druckbare Zeichen (ASCII > 0x20..0x7F). Könnte ja gut sein, dass andere Zeichen als > Steuerzeichen interpretiert werden. Damit habe ich ja angefangen. Ich hatte einen String mit großem 'P' und raus kam ein kleines 'ü', alle anderen Buchstaben waren in Ordnung. Dann habe ich die Schleife eingebaut und festgestellt, das bei jedem Buchstaben, der in Hex auf 0 endet dieses Verschiebeproblem auftritt. 0 = 0x30 -> 0xf3 wird ausgegeben @ = 0x40 -> 0xf4 wird ausgegeben P = 0x50 -> 0xf5 wird ausgegeben.
Andreas Peters schrieb: > Hängt jetzt hier dran Naja, die verwendete LCdD-Lib wird wohl hoffentlich fehlerfrei sein. Was wahrscheinlich viel interessanter wäre, ist dein Code PS: verscuhs mal mit Peter Fleurys lcd lib. Die funktioniert auf jeden Fall.
Vlad Tepesch schrieb: > Naja, die verwendete LCdD-Lib wird wohl hoffentlich fehlerfrei sein. Das hatte ich gehofft :) > Was wahrscheinlich viel interessanter wäre, ist dein Code Der ist wenig spektakulär, siehe oben. > PS: verscuhs mal mit Peter Fleurys lcd lib. Die funktioniert auf jeden > Fall. Das probiere ich heute abend mal aus.
Die hier aus dem Forum funktioniert aber auch. Ich benutze die auch immer. Ich glaub es liegt eher an seinem Code.
L. J. schrieb: > Die hier aus dem Forum funktioniert aber auch. Ich benutze die auch > immer. Ich glaub es liegt eher an seinem Code. Davon würde ich generell auch ausgehen. Blöd ist nur, das die gleiche Routine für alle möglichen Zeichen funktioniert, nur keine mit Low-Nibble == 0 wenn der Aufruf aus einer Schleife kommt. Darum hatte ich vermutet, das es irgendwas mit Optimierungen & Compiler zu tun hat.
Naja, da ich mir nicht sicher bin, was du in deinem Code geändert hast und was nicht, gehe ich von dem obigen aus. Im zweiten Teil treten die Probleme auf? So wie ich das sehe versuchst du den Wert der Variablen c auszugeben oder? Und danach inkrementierst du c. Und das ausgeben von c funktioniert dann nicht oder wie?
Schränk dich mal den Laufbereich von c ein, bzw. vereinfache dein Testprogramm weiter.
Du gibst Steuerzeichen aus. Versuche es mal mit c='0' statt c=0 in der ersten Zeile. Und dann vielleicht ein delay zwischen dem Setzen des cursors und der Ausgabe.
Probier doch mal, ob das funktioniert: char c=5; lcd_data(c); Da müsstest du ja dann eigentlich die 5 sehen.
L. J. schrieb: > Probier doch mal, ob das funktioniert: > > char c=5; > lcd_data(c); > > Da müsstest du ja dann eigentlich die 5 sehen. Das bezweifle ich doch stark. Gruß, Frank
L. J. schrieb: > char c=5; > lcd_data(c); > Da müsstest du ja dann eigentlich die 5 sehen. ? Ne, das ist ja 0x05 -> Steuerzeichen. Das Zeichen '5' wäre 0x35. Stört euch mal nicht an der Schleife mit dem c. Damit bin ich nur auf die Schliche gekommen, welche Zeichen alle nicht funktionieren. Die gleiche Routine (lcd_data) klappt ja, wenn sie außerhalb der while Schleife aufgerufen wurde. Vorher hatte ich da mal stehen: while (1) { lcd_string("Peters"); } und auf dem Display stand: "üeters" Ich probiere heute Abend mal die andere lib aus.
L. J. schrieb: > Wow dann müsste da aber oft üeters stehen^^. (Die Schleife war jetzt nur sinngemäß wiedergegeben, da ich den Code gerade nicht kopieren kann). Alternativ wird ein '@' durch Omega-Zeichen ersetzt und die 0 durch ein Durchschnittssymbol.
Andreas Peters schrieb: > Stört euch mal nicht an der Schleife mit dem c. Damit bin ich nur auf > die Schliche gekommen, welche Zeichen alle nicht funktionieren. > Die gleiche Routine (lcd_data) klappt ja, wenn sie außerhalb der while > Schleife aufgerufen wurde. Hä? Ich denke, die Schleife ist wichtiger Bestandteil des Fehlers? wenn du lcd_data( 'P' ); machst, funktioniert alles, wenn du while( 1 ) lcd_data( 'P' ); machst, kriegst du 'ü' Oder wie, oder was? Ich tippe da auch erst mal auf ein Timingproblem. Das sich der Compiler da verhaut ... so recht glaub ich da nicht daran.
Frank M. schrieb: > Das bezweifle ich doch stark. Oh jetzt habe ich selber den Fehler gemacht. Es sollte char c='5' heißen. Sorry.
Karl heinz Buchegger schrieb: > lcd_data( 'P' ); > machst, funktioniert alles, > wenn du > while( 1 ) > lcd_data( 'P' ); > machst, kriegst du 'ü' > Oder wie, oder was? Genau das ist es. Und die Regelmäßigkeit betrifft alle Zeichen, die in Hex 0x20, 0x30, 0x40, 0x50 sind. Diese kommen als 0xf2, 0xf3, 0xf4, 0xf5 auf dem Display an. > Ich tippe da auch erst mal auf ein Timingproblem. Das sich der Compiler > da verhaut ... so recht glaub ich da nicht daran. Es werden ja immer die gleiche Routinen durchlaufen...:(
Andreas Peters schrieb: > Karl heinz Buchegger schrieb: >> lcd_data( 'P' ); >> machst, funktioniert alles, >> wenn du >> while( 1 ) >> lcd_data( 'P' ); >> machst, kriegst du 'ü' >> Oder wie, oder was? > Genau das ist es. Und die Regelmäßigkeit betrifft alle Zeichen, die in > Hex 0x20, 0x30, 0x40, 0x50 sind. Diese kommen als 0xf2, 0xf3, 0xf4, 0xf5 > auf dem Display an. > >> Ich tippe da auch erst mal auf ein Timingproblem. Das sich der Compiler >> da verhaut ... so recht glaub ich da nicht daran. > Es werden ja immer die gleiche Routinen durchlaufen...:( OK , Test
1 | #include "lcd_routines.h" |
2 | |
3 | int main(void) |
4 | {
|
5 | lcd_init(); |
6 | |
7 | lcd_data( 'P' ); |
8 | lcd_data( 'P' ); |
9 | lcd_data( 'P' ); |
10 | |
11 | _delay_ms( 1000 ); |
12 | lcd_clear(); |
13 | |
14 | while( 1 ) |
15 | {
|
16 | lcd_data( 'P' ); |
17 | _delay_ms(500); |
18 | }
|
19 | |
20 | return 0; |
21 | }
|
welche dieser 'P' werden als 'ü' ausgegeben.
Karl heinz Buchegger schrieb: > welche dieser 'P' werden als 'ü' ausgegeben. Na, das ist doch in genau das, was in meinem Eingangspost ganz oben steht. Die ersten P's tauchen sauber auf, die dann erscheinenden P's werden als ü's ausgegeben. Ich hatte das mit "0@P" ausprobiert. Werde heute Abend den Sourcecode exakt so einmal eingeben und austesten.
Andreas Peters schrieb: > Werde heute Abend den Sourcecode exakt so einmal eingeben und austesten. Ich bitte darum. In deinem Code taucht nämlich auch noch SetCursor etc auf. Ausserdem ist ein Aufruf von lcd_string nicht unbedingt mit einem mehrfach hintereinander erfolgtem Aufruf von lcd_data zu vergleichen. c ist bei dir int, etc. Da gibt es schon ein paar Unterschiede, die sich zb auswirken wenn du lcd_routines.h nicht inkludiert hast. (Hast du doch, oder? -> immer kompletten Source Code posten!)
Karl heinz Buchegger schrieb: > Da gibt es schon ein paar Unterschiede, die sich zb auswirken wenn du > lcd_routines.h nicht inkludiert hast. (Hast du doch, oder? -> immer > kompletten Source Code posten! Ja, habe ich, ich hatte dann irgendwann die kompletten Beispiele aus dem Tutorial übernommen. Beim stöbern gerade habe ich widersprüchliche Aussagen zu DB0-DB3 gefunden -> Offen lassen oder grounden ?
Hi
>Offen lassen oder grounden ?
Die Pins haben interne Pullups.
MfG Spess
Andreas Peters schrieb: > Karl heinz Buchegger schrieb: >> welche dieser 'P' werden als 'ü' ausgegeben. > Na, das ist doch in genau das, was in meinem Eingangspost ganz oben > steht. Die ersten P's tauchen sauber auf, die dann erscheinenden P's > werden als ü's ausgegeben. Ich hatte das mit "0@P" ausprobiert. In meinen Augen sieht das auch, wie schon erwähnt nach einem Timing-Problem aus. Ich hatte solche Probleme auch schon, aber da wars weil ich Speed-halber an den Delay-Zeiten rumgebastelt habe. Ich würde so vorgehen: 1) Überprüfe ob für die Delay-Funktion die Quarzfrequenz stimmt 2) erhöhe mal sämtliche delays im Header-File (z.B doppelt so gross). was hat das anschliessend für ein Effekt?
spess53 schrieb: > Die Pins haben interne Pullups. Hmm, d.h. bei der Übertragung des High-Nibbles liegt dann z.B. für 0x40 ('@') 0b11110100 = 0xf4 an, würde man dabei kurz im 8-Bit Modus lesen. Aber das das Display dabei hin- und herschaltet kann eigentlich nicht sein, oder ?
Hi >Hmm, d.h. bei der Übertragung des High-Nibbles liegt dann z.B. für 0x40 >('@') 0b11110100 = 0xf4 an, Nein. Wenn schon dann $4F. Deine Datenleitungen liegen an D4...D7. MfG Spess
Ist das ein HD44780(-kompatibler) Chip? Falls ja dann könntest Du Timing-Probleme recht einfach bestätigen (und beheben) indem Du das busy-Flag zurückliest. Winzigster Hardwareaufwand und wenig Softwareaufwand. Die Details dazu stehen im Datenblatt.
Ich würde vorallem mal prüfen das die Ports korrekt auf Ausgang konfiguriert sind.
Patrick B. schrieb: > In meinen Augen sieht das auch, wie schon erwähnt nach einem > Timing-Problem aus. Da hatte ich auch schonmal vermutet. > 1) Überprüfe ob für die Delay-Funktion die Quarzfrequenz stimmt Ich nutze den internen Oszillator. Den hatte ich per Fuse schonmal auf 1 MHz und auf 8 MHz gesetzt, in beiden Varianten das gleiche. Die Frequenz habe ich grob geprüft, durch die Verzögerung in der Ausgabe (500ms), die passte. > 2) erhöhe mal sämtliche delays im Header-File (z.B doppelt so gross). Hatte ich ebenfalls schonmal gemacht, brachte keine Besserung, wieder zurückgebaut. Allerdings habe ich gestern Nacht an soviele Stellen geschraubt, das ich nicht ausschließen will, irgendwas verschlimmbessert zu haben.
Hilfreich wäre jetzt der komplette Source Code, sonst raten wir nur rum.
L. J. schrieb: > Hilfreich wäre jetzt der komplette Source Code, sonst raten wir nur rum. Ich mache heute abend 3 Sachen: 1. Komplett neues Projekt anlegen, alle 3 Files aus dem Tutorial neu kopieren und einfügen 2. Hauptprogramm anpassen an den String den ich will -> gucken. 3. Lib von Fleury ausprobieren.
Andreas Peters schrieb: > 3. Lib von Fleury ausprobieren. Die Fleury Lib benötigt eine Beschaltung des R/W Pins vom LCD. Nicht dass du da dann lang rumsuchst.
Karl heinz Buchegger schrieb: > Die Fleury Lib benötigt eine Beschaltung des R/W Pins vom LCD. Nicht > dass du da dann lang rumsuchst. Nene, das ist schnell gemacht ;)
Andreas Peters schrieb: > Nene, das ist schnell gemacht ;) Naja, bei einem KS0066U (der ist (fast) "kompatibel") handelt man sich beim Auswerten des Busy-Flags neue Probleme ein: Beitrag "LCD-Kontroller KS0066U, HD44780, Timing bei Busy-wait" http://www.sprut.de/electronic/lcd/index.htm#ks0066u Beitrag "Re: LCD (HD44780) timing extrem träge" Ich selbst benutze das Busy-Flag schon lange nicht mehr, macht nur Ärger. Gruß, Frank
So, es wird irgendwie immer seltsamer. Neues Projekt angelegt für 2313. Alle 3 Beispieldateien aus dem Tutorial 1:1 kopiert. Anpassungen für CPU & Ports gemacht, sonst NICHTS. Laut Anweisungen sollte erscheinen: "Test " "Hello World! " Erschienen ist: "Test " "HelloRWoWld! " Ich habe daraufhin das Display gewechselt. Vorher weiße/blau, jetzt blau schwarz, auch T1602A. Ausgabe: "Test " "Hello*Wo*ld! " (Die beiden * sind dabei 2 chinesische Hyroglyphen.) Zum Testaufbau: Pollin Eval Board 2.01, IDE-Flachbandkabel, Add On Board V1.0, alle Jumper runter, Drahtbrücken zwischen PortB und LCD, Display gesteckt auf der Platine, programmiert über AVR MKII original mittels ISP Anschluss, 8MHz intern per RC und extern per crystal. Zu guter letzt Programm wie folgt abgeändert: int main(void) { lcd_init(); lcd_data( 'r' ); lcd_data( 'r' ); lcd_data( 'r' ); lcd_data( 'r' ); lcd_string("Hello World!"); while(1) { } return 0; } Erwartet: "rrrrHello World!" erhalten: "rrrrHello*Wo*ld! * = Hieroglyphen. Ich probier jetzt mal die Fleury Lib aus... kopfschüttel
Versuchs mal so:
1 | ////////////////////////////////////////////////////////////////////////////////
|
2 | // Erzeugt einen Enable-Puls
|
3 | static void lcd_enable( void ) |
4 | {
|
5 | LCD_PORT |= (1<<LCD_EN); // Enable auf 1 setzen |
6 | _delay_us( LCD_ENABLE_US ); // kurze Pause |
7 | LCD_PORT &= ~(1<<LCD_EN); // Enable auf 0 setzen |
8 | _delay_us( LCD_ENABLE_US ); // kurze Pause |
9 | }
|
Andreas Peters schrieb: > Brachte keine Besserung. Probiere gerade nochwas aus. Ich glaube, ich habe das Rätsel gelöst. Problem ist: Sobald ein Zeichen ausgegeben wird, das im Low-Nibble ein 0x?F hat, wird beim nächsten Zeichen das Low-Nibble als High-Nibble verwendet.
1 | #include <avr/io.h> |
2 | #include "lcd-routines.h" |
3 | #include <util/delay.h> |
4 | |
5 | int main(void) |
6 | {
|
7 | lcd_init(); |
8 | |
9 | // Text in einzelnen Zeichen ausgeben
|
10 | // Vermutung -> Wenn das letzte Zeichen auf Hex 0x?f endete,
|
11 | // Wird das Nächste Zeichen aus Low Nibble alt und HighNibble Neu Falsch gebildet
|
12 | lcd_data( 0x48 );// H |
13 | lcd_data( 0x65 );// e |
14 | lcd_data( 0x6c );// l |
15 | lcd_data( 0x6c );// l |
16 | lcd_data( 0x6f );// o |
17 | lcd_data( 0x48 );// H (Hier wird Omega angezeigt 0xf4 |
18 | lcd_data( 0x6f );// o |
19 | lcd_data( 0x50 );// P (Hier wird ein kleines ü angezeigt (0xf5 |
20 | lcd_data( 0x50 );// P Dieses P ist einwandfrei |
21 | lcd_data( 0x3f );// ? (endet auch auf f) |
22 | lcd_data( 0x40); // @ |
23 | // Soll: HelloHoPP?@
|
24 | // Ist: Hello*oüP?* // * = Omega
|
25 | // Falsch ^ ^ ^
|
26 | while(1) |
27 | {
|
28 | }
|
29 | |
30 | return 0; |
31 | }
|
Habe das Display dann von Port B auf Port D umgedrahtet auf dem Evaluationsboard. Und schon werden alle Zeichen einwandfrei sauber angezeigt. Ich habe den MC auf der Eval-Platine mit dem Atmel ISP und Buchsenleiste programmiert. Das Evaluationsboard hat aber noch einen serielle ISP aus diskreten Bauteilen. Der hängt fest an den Leitungen. Ich vermute jetzt das die Bauteile da Streß machen und irgendwie ein Enable-Signal verschleifen, woraufhin das neu reingeschobene Nibble nicht übernommen wird.
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.