Guten Tag an alle erstmal! Ich versuche ein LC-Display mit C-Programmiersprache zu initialisieren, jedoch klappt es nur bis "Display löschen" und zeigt dann leider keine Zeichen an sondern nur einen völlig leeren, beleuchteten Display. Meine Quellen sind ein getestes und funktionierendes .asm-Programm eines "Vorgängers" und diese Internetseite: http://www.stefan-buchgeher.info/elektronik/lcd/lcd_kap5.html#Kap5 Ich habe eigentlich das asm.-Programm wortwörtlich übersetzt, aber die Ausgabe funktioniert nicht. Ich programmiere mit MPLAB IDE v8.88 einen PIC16f887, PORTB dient als 8-Bit-Datenausgabe. Anbei mein C-Programm in txt.-Datei. Vielen Dank schonmal im Voraus für eure Mühe.
> Anbei mein C-Programm in txt.-Datei.
Warum?
Häng einfach deine C-Datei als Anhang an, so wie sie ist. Dann greift
hier im Forum auch das Syntax Coloring.
Hallo, Ich habe gerade deinen Code überflogen und habe dazu ein paar Fragen: 1) Du hast eine Routine, die das LCD initialisiert. Warum wird nach der Initialisierung eine For-Schleife aufgerufen, in der das Display gelöscht wird und dann in jede Zeile ein Zeichen geschrieben wird? Würde ich entfernen) 2) Sollte die Initialisierung erfolgreich sein, wird der µC nichts mehr tun, da dieser dann keine Arbeit mehr hat. Ist das von Dir so gewollt, oder sollen noch Zeichen später eingefügt werden? ("while(1)") 3) Versuche einmal, dass dein LCD initialisiert wird und dann erst (z.B. in der Hauptschleife) Zeichen an das Display übergeben werden (kann auch per Tastendruck o.ä. geschehen) 4) Sind die Zugriffszeiten für das Display OK? (Es kann sein, dass deine Zugriffe zu schnell sind? [je nach Taktquelle]) 5) Du hast zwar im Post die verwendeten Komponenten angegeben, wie hast Du dieses aber dem Compiler (HTC,CCS,XC8?) mitgeteilt? (Einstellung im Projekt? Mir scheint, dass hier noch etwas im Programm fehlt)
@technik_freak Zur for-Schleife: Ich hatte davor eine while(1) Schleife und habe dann meine for-Schleife reingeschrieben um zu sehen ob der Pic sich eventuell vorher irgendwo verabscheidet,aber das ist nicht der Fall. ( Ich habe nach der For-schleife eine Led kurz aufleuchten lassen zum überprüfen.) Die for-schleife wandle ich dann wieder um :) Meine Zugriffszeiten habe ich eigentlich recht großzügig gestaltet und beim compilieren mit Knudsen CC5x stand "build succeeded" ohne Warnings o.Ä. Meine Konfiguration ist: XT_OSC WDT disabled PWRTE disabled LVP off BOREN out MCLR bei RE3 Ich habe nicht per pragma-Direktiven sondern unter Settings die Bits eingestellt. Dann mach ich mich mal daran deine Vorschläge umzusetzen^^
So habe mein Programm überarbeitet aber es haut noch nicht hin :( Hier das neue Programm im richtigen Format ;) Edit: ich habe in "delay500ys()" das "g" mit "m" ausgebessert und dann hat noch nichtmal das Display löschen wie ursprünglich geklappt. Das verwirrt mich zwar etwas aber sieht wohl danach aus, dass ich die Warteschleifen nochmal überprüfen muss.
Dir ist hoffentlich schon klar, dass dir jeder besser Wald- und Wiesen- Nasenpopel-Compiler das hier
1 | void delay100ms(unsigned char e) |
2 | {
|
3 | for(y=e; y!=0; y--) |
4 | {for(x=50;x!=0; x--) |
5 | {for(z=248;z!=0; z--) |
6 | {}}}
|
7 | }
|
rausschmeissen wird? Verbrutzelt nur Zeit ohne etwas zu tun tun. Daher weg damit. Dasss es dir gerade auf dieses 'verbrutzelt nur Zeit' ankommt, das kann der Compiler nicht wissen und in seinem Übereifer, für dich aus dem Programmtext die maximale Geschwindigkeit rauszuholen, optimiert er dir das glatt komplett weg. Hat denn dein Compiler keine vorgefertigten Delay-Funktionen?
Karl Heinz Buchegger schrieb: > Dir ist hoffentlich schon klar, dass dir jeder besser Wald- und Wiesen- > Nasenpopel-Compiler das hier >
1 | > void delay100ms(unsigned char e) |
2 | > { |
3 | > for(y=e; y!=0; y--) |
4 | > {for(x=50;x!=0; x--) |
5 | > {for(z=248;z!=0; z--) |
6 | > {}}} |
7 | > } |
8 | >
|
> rausschmeissen wird? > Verbrutzelt nur Zeit ohne etwas zu tun tun. Daher weg damit. > > Dasss es dir gerade auf dieses 'verbrutzelt nur Zeit' ankommt, das kann > der Compiler nicht wissen und in seinem Übereifer, für dich aus dem > Programmtext die maximale Geschwindigkeit rauszuholen, optimiert er dir > das glatt komplett weg. > > Hat denn dein Compiler keine vorgefertigten Delay-Funktionen? In dem Dateiordner zu den Header-Dateien verschiedenster PICs war auch ein Delay-Programm dabei aber da ich den Aufbau nicht verstanden habe, habe ich selber welche programmiert. Zudem habe ich den Watchdogtimer deaktiviert. Dann habe ich an meinem Port einfach 8 LEDs angeschlossen und es funktionierte, darum bin ich dabei geblieben. Ich werds aber mal ausprobieren.
Hallo, Neben den Tipp von K.H.B kommt noch einer von Mir: Wandle deine LCD-Routinen soweit ab, dass du die Information, der mit Save übergeben wird, als Funktionsparameter einfügst. dieses spart Prorgammzeilen und ist übersichtlicher, da diese gleich beim Aufruf übergeben werden. (Falls später zwischen der Wertübergabe an Save und der LCD-Routine noch andere Dinge hineingequetscht werden, kann es zu Fehlern kommen) Andere Frage, werden wirklich so viele Variablen benötigt?
Sebastian H. schrieb: > Hallo, > > Neben den Tipp von K.H.B kommt noch einer von Mir: > > Wandle deine LCD-Routinen soweit ab, dass du die Information, der mit > Save übergeben wird, als Funktionsparameter einfügst. dieses spart > Prorgammzeilen und ist übersichtlicher, da diese gleich beim Aufruf > übergeben werden. (Falls später zwischen der Wertübergabe an Save und > der LCD-Routine noch andere Dinge hineingequetscht werden, kann es zu > Fehlern kommen) > > Andere Frage, werden wirklich so viele Variablen benötigt? Ok, habe ich gemacht. Nein, ich hatte davor eine 7-Segment-Anzeige angesteuert und vergessen die Variablen herauszulöschen. Ich habe es auch mal mit den vorgefertigten Delay-Programmen versucht aber da hat mein Compiler(Knudsen CC5x) gestreikt; die Datei wurde wahrscheinlich mal verändert oder so. Daraufhin habe ich meine Zeitprogramme nochmals überprüft mit LED-Ausgaben. Und je länger mein Zeitprogramm desto langsamer haben sie geblinkt.
Roland E. schrieb: > Ok, habe ich gemacht. Gut. Denn diese Zuweisungen an save vor einem Funtkionsaufruf sind ja wirklich eine Zumutung.
1 | void LCD_Ausgabe( unsigned char wert ) |
2 | {
|
3 | LCD_busy(); |
4 | |
5 | RW_aus; |
6 | nop(); |
7 | RS_an; |
8 | |
9 | PORTB = wert; |
10 | |
11 | enable_an; |
12 | nop(); |
13 | enable_aus; |
14 | nop(); |
15 | }
|
die nop da drinnen. Die würde ich alle mal durch längere Wartezeiten ersetzen. Und dann ... > Daraufhin habe ich meine Zeitprogramme nochmals überprüft mit > LED-Ausgaben. Und je länger mein Zeitprogramm desto langsamer haben sie > geblinkt. ... häng nochmal deine 8 LED an. Denn: du darfst ein LCD nicht zu schnell ansteuern. Du darfst es aber so langsam ansteuern wie du willst. D.h. du kannst alle Wartezeiten so lange machen, wie du möchtest und wie du an den 8 LED ablesen kannst, ob die Reihenfolge der Signale an den einzelnen Leitungen stimmt. Einzig die Busy Funktion ... die würde ich erst mal durch eine generelle Wartezeit ersetzen. Die längste mögliche Aktion (LCD löschen) dauert so um die 30ms. D.h. wenn deine Busy Funktion einfach mal 1 Sekunde wartet, dann ist das LCD mit Sicherheit nicht mehr busy. Und dann kannst du die LED auch parallel zum LCD anhängen um zu sehen, was das LCD genau bekommt und wie es darauf reagiert.
Vielen Dank erstmal für die bisherige Hilfe :D Also ich habe die 8 LEDs drangehängt und habe herausgefunden, dass sich mein LC-Display mit der "2 Zeilen 5x7 Darstellung"-Anweisung in Zeile 98 abschaltet und danach gar nicht mehr reagiert. Der PIC läuft das komplette Programm ganz normal ab, d.h. er hängt sich nirgendwo auf. Anbei das aktuelle C-Programm. Edit: Bevor sich das LCD abschaltet sieht man in der ersten Zeile des Displays einen schwarzen Balken.
Roland E. schrieb: > Edit: > Bevor sich das LCD abschaltet sieht man in der ersten Zeile des Displays > einen schwarzen Balken. Moment. Diese 'Abschaltung' ist dein Hinweis, dass das LCD gerade initialisiert wird/wurde. Das ist völlig normal. Ein derartiges LCD zeigt nach dem Anlegen der Versorungsspannung IMMER einen schwarzen Balken an. Der ist nützlich um a) zu sehen, dass das LCD prinzipiell erst mal funktioniert b) den Kontrast zumindest provisorisch so einzustellen, dass man dann auch die ersten Zeichen auf dem LCD sehen können wird. Mit den ersten Initialisierungen schaltet das LCD dann den Balken weg und nimmt den normalen Betrieb auf.
In deiner < void init(void) > werden die Ports wohl auf Output geschaltet, ich sehe aber keine Umschaltung von ANALOG (was Default ist) auf DIGITAL. Und beim 887 sind PORTA und PORTB mit Analogfunktionen belegt.
Und du bist dir sicher, dass die Zeitschleifen nicht 'wegoptimiert' werden?
OK, habe zu spät gesehen das die BUSY-Funktion nicht verwendet wird, also ist die Analog/Digital Umschaltung nicht (unbedingt) nötig...
Hallo, 1) Du hast im Kopf deiner Datei, Definierungen angegeben. Im laufenden Programm werden diese aber nicht verwendet. Es wäre angebracht, als Definierung nicht zu schreiben "PORTB=0bxxxxxxxx", sondern einfach nur den Wert. Diese Definierung wird dann als Parameter deiner gewünschten Funktion übergeben (Nehmen wir an, du rufst z.B. den Löschbefehl im späteren Programm 50x auf. Jetzt fällt dir/jmd. anderem auf, dass der Wert falsch ist => Du änderst in einer Zeile den Wert, welcher für die anderen 49 gleich ist oder suchst im Programm nach allen 50 [50 ist spontan gewählt, kann aber vorkommen]) 2) Erstelle für die Initialisierung des Displays eine weitere Funktion (void LCD_SoftReset(void)), welche die EN-Leitung für den Soft-Reset ansteuert (sieht optisch auch besser aus) 3) (wahrscheinlich dein Fehler) Du initialisierst dein Display mit 8-Bit, dann wird die weitere Konfiguration (2-Zeilen, 5x7 oder 5x10) mitgeteilt. DANN wird dein Display ausgeschaltet (?). => Ich habe in diesem Beitrag(http://www.mikrocontroller.net/articles/AVR-GCC-Tutorial/LCD-Ansteuerung) mir eben die initialisierungroutine angeschaut (zwar im 4-Bit Modus) und dort wird nach der Einstellung des Modus und des Displaytyps, weitere Funktionen eingestellt, bevor das Display gelöscht wird und die ersten Zeichen eingefügt werden. Entferne die LCD-Aus/Ein Befehle und probiere es erneut.
Hi >Also ich habe die 8 LEDs drangehängt und habe herausgefunden, dass sich >mein LC-Display mit der "2 Zeilen 5x7 Darstellung"-Anweisung in Zeile 98 >abschaltet und danach gar nicht mehr reagiert. Kein Wunder, du veralberst dein Display. Beim 8-Bit-Interface reichen drei Befehle zur Initialisierung: Function Set: 0b00111000 Display On/Off: 0b00001110 Entry Mode Set: 0b00000110 MfG Spess
spess53 schrieb: > Hi > >>Also ich habe die 8 LEDs drangehängt und habe herausgefunden, dass sich >>mein LC-Display mit der "2 Zeilen 5x7 Darstellung"-Anweisung in Zeile 98 >>abschaltet und danach gar nicht mehr reagiert. > > Kein Wunder, du veralberst dein Display. Beim 8-Bit-Interface reichen > drei Befehle zur Initialisierung: > > Function Set: 0b00111000 > Display On/Off: 0b00001110 > Entry Mode Set: 0b00000110 > > MfG Spess Das hat mir einen Schritt weitergeholfen, jetzt sehe ich am Display unter LCD-Anzeige immerhin den Cursor im ganz linken oberen und unteren Feld blinken. Aber leider immernoch keine Zeichen bzw. Buchstaben. @technik-freak: Mein Display wird nicht wirklich ausgeschlatet (habe ich mich leider undeutlich ausgedrückt). Der schwarze Balken in der ersten Zeile verschwand im alten Programm nach der "2 Zeilen 5x7 Darstellung"-Anweisung. Der Display blieb aber weiter beleuchtet, hatte nur keinerlei Zeichen oder Symbole ausgegeben. Ich programmiere mit MPLab von MIcrochip und da hatte ich bei früheren Programmen das Problem, dass komischerweise bei manchen Direktiven oder Befehlen von AVR mir Fehler angezeigt werden. Aber ich lese es mir mal durch und schaue ob ich etwas übernehmen kann. @ralg: Ja, ich habe das öfters mit den 8 LEDs überprüft und die improvisierten Zeitprogramme haben ihren Zweck erfüllt. Nichtsdestotrotz werde ich vorm nächsten Projekt das etwas professioneller handhaben^^
Hi >Das hat mir einen Schritt weitergeholfen, jetzt sehe ich am Display >unter LCD-Anzeige immerhin den Cursor im ganz linken oberen und unteren >Feld blinken. Hast du ein Datenblatt von deinem Display, oder wenigstens eine´Bezeichnung? Wie sieht dein Programm jetzt aus? Zweimal Cursor ist mir noch nicht untergekommen. Möglicherweise muß es als einzeiliges Display initialisiert werden. Also Function Set: 0b00110000 >Aber leider immernoch keine Zeichen bzw. Buchstaben. Wenn der Cursor blinkt ist das Display initialisiert. Also müßte die Zeichenausgabe auch funktionieren. MfG Spess
Hallo, Es kann sein, dass die Schritte "LCD gibt Zeichen aus" und "LCD wird gelöscht" mit 50ms etwas schnell sind (naja, sind zwar 20Hz und m.W. kann das menschliche Auge ab ca. 25 Hz keine einzelnen Schritte mehr erkennen (siehe Filme, diese laufen mit 25 Bildern/Sekunde). Da das Display anscheinend richtig initialisiert wurde (Cursorblinken ist vorhanden), probiere folgende Änderung deiner While(1)-Schleife:
1 | while(1) //Ist die Schleife der Main |
2 | {
|
3 | LCD_Ausgabe('T'); |
4 | LCD_Ausgabe('e'); |
5 | LCD_Ausgabe('s'); |
6 | LCD_Ausgabe('t'); |
7 | while(Button_LCD_Reset != 1); //Der Pin Button_LCD_Reset muss als digitaler Eingang initialisiert werden und der nächste Schritt erfolgt erst, wenn die While-Bedingung "False" ist |
8 | |
9 | LCD_Befehl(0x01); //LCD wird gelöscht |
10 | while(Button_LCD_Reset != 0); //Hier wird verhindert, dass erneut das LCD beschrieben wird, so lange der Pin den Zustand 1 besitzt. |
11 | }
|
Edit: Noch etwas => Meines Wissens nach, wird durch
1 | #define LCD_8bitinterface PORTB=0b00110000; //8bitinterface
|
die Ersatzbezeichnung "LCD_8bitinterface" mit deinem PORTB=xyz definiert und gleich abgeschlossen (;) Im weiteren Programm rufst du "LCD_8bitinterface" erneut auf und schließt diese auch mit ; ab. Gibt der Compiler diesbezüglich eine Warnmeldung heraus? Falls Ja, entferne in der Definierung das ; (Ich hatte zu Beginn dieses auch gemacht und hatte am Ende probleme mit dem Programm, bis dieses erkannt wurde.
Spess53 schrieb: > Hi > >>Das hat mir einen Schritt weitergeholfen, jetzt sehe ich am Display >>unter LCD-Anzeige immerhin den Cursor im ganz linken oberen und unteren >>Feld blinken. > > Hast du ein Datenblatt von deinem Display, oder wenigstens > eine´Bezeichnung? > > Wie sieht dein Programm jetzt aus? > > Zweimal Cursor ist mir noch nicht untergekommen. Möglicherweise muß es > als einzeiliges Display initialisiert werden. Also > > Function Set: 0b00110000 > >>Aber leider immernoch keine Zeichen bzw. Buchstaben. > > Wenn der Cursor blinkt ist das Display initialisiert. Also müßte die > Zeichenausgabe auch funktionieren. > > MfG Spess Die Anleitung habe ich schon vergeblich gesucht. Unterm Display steht "16265SSBHD" und google spuckt folgendes aus: http://pdf1.alldatasheet.com/datasheet-pdf/view/165398/VARITRONIX/MDL-16265.html http://octopart.com/datasheet/mdls-16265-ss-lv-g-varitronix-547617-138126 http://www.cumbriadesigns.co.uk/Datasheets/MDLS16265-04.pdf Allerdings habe ich auf meinem Übungsboard noch einen BL-Anschlusspin am LCD-Control, der in den Datenblättern nicht vorkommt?! Ich beziehe mich im Folgenden auf mein hier angehängtes Programm. Zum Thema Cursorblinken muss ich mich korrigieren: Er blinkt nicht sondern ist fest (Ich hatte letztes Mal eine kurze Wartezeit und darum habe ich es versehentlich als Blinken wahrgenommen). Beim Befehl "Display löschen" (Z.28) befindet sich der Cursor in der ersten Zeile ganz links. Beim Befehl "Ausgabe A" (Z.32) befindet der Cursor in der zweiten Zeile im zweiten Käschten von links. Beim Befehl "Ausgabe B" (Z.36) befindet sich der Cursor in der zweiten Zeile im dritten Kästchen von links. Und beim Befehl "Ausgabe H" (Z.40) befindet sich der Cursor in der zweiten Zeile ziemlich in der Mitte. Dann beginnt es erneut. @tech_freak: Ich habe die Warteschleife vorsorglich auf 1,5s gesetzt aber daran lags leider nicht. Mein Compiler zeigt mir keinerlei warning an, egal ob mit oder ohne Semikolon bei der Definierung. Ich habe das Semikolon aber trotzdem vorsorglich mal gelöscht. Das mit dem "while(Button_LCD_Reset != 1)" verstehe ich nicht ganz. Bin noch C-Neuling^^ Ich mache ja auch eine LCD-busy-Abfrage. Frägt das dann was anderes ab ?
Hi >Beim Befehl "Display löschen" (Z.28) befindet sich der Cursor in der >ersten Zeile ganz links. >Beim Befehl "Ausgabe A" (Z.32) befindet der Cursor in der zweiten Zeile >im zweiten Käschten von links. >Beim Befehl "Ausgabe B" (Z.36) befindet sich der Cursor in der zweiten >Zeile im dritten Kästchen von links. >Und beim Befehl "Ausgabe H" (Z.40) befindet sich der Cursor in der >zweiten Zeile ziemlich in der Mitte. Sieht fast so aus, als würde das wie ein 'Set DDRAM Adress'-Befehl interpretiert. Die Positionen passen irgendwie zu den unteren Bits der ASCII-Codes von A, B und H (0x41, 0x42 und 0x48). Überprüfe mal deine RS-Leitung. MfG Spess
Also ein einziges Mal konnte ich jetzt in der ersten Zeile immerhin schon "AABBHH[komisches Zeichen]AABBHH[komisches Zeichen]..." sehen. Meine Leitungen und das Display habe ich mit einem PIC, auf dem das alte .asm-Programm zum LCD ist, überprüft und es hat alles reibungslos funktioniert. Irgendein kleines Detail fehlt im Programm anscheinend noch :/
Ich habe jetzt exakt das gleiche Programm auf einen PIC16F84A geflasht und der LCD gibt mir im Gegensatz zum PIC16F887 Buchstaben aus. Jetzt bin ich otal verwirrt :@
Roland E. schrieb: > Das mit dem "while(Button_LCD_Reset != 1)" verstehe ich nicht ganz Hallo, eigentlich meinte Ich folgendes: Du hast deine "Main-Schleife". Als erstes wird in dieser "Test" auf das Display ausgegeben. Dann kommt die Abfrage eines Pins ("Button_LCD_Reset", dieser ist ein einfacher Taster mit PullDown, der an einem Pin des Controllers angeschlossen ist und als digitaler Eingang (auch das ANSEL Register muss auf digitalIO eingestellt werden)initialisiert wird). Ist der Taster nicht betätigt, so ist die Bedingung in while(Button_LCD_Reset != 1) Wahr und die Schleife wird ausgeführt. Da aber nach dem while(Button_LCD_Reset != 1) ein Semikolon steht, wird das als leere Schleife interpretiert (man hätte auch {} schreiben können) und macht erst einmal nichts mehr. Jetzt wird der Taster betätigt, die Bedingung ist Falsch und die Schleife wird verlassen. Jetzt wird dem LCD mitgeteilt, dass alles vom Display gelöscht wird. Nach diesem Löschbefehl steht aber eine weitere While-Schleife, dessen Bedingung ist aber zur vorherigen invertiert.Erst, wenn der Taster wieder losgelassen wird, ist auch diese Schleife fertig und das Display wird wieder mit Test beschrieben. Eine andere Sache bzgl. deinem LCD-Busy: Du fragst in deinem Programm den Pin B7 ab, dieser ist aber als Ausgang initialisiert worden. Du musst für die Abfrage von B7, besagten als Einang definieren, auslesen und wieder als Ausgang umdefinieren. Du würdest sonst den aktuellen Zustand des PIC-Pins lesen und nicht den Zustand des LCD. Im schlimmsten Fall kann es sein, dein LCD gibt ein 1-Signal aus, der PIC hat aber den Pin (als Ausgang) auf 0 gelegt => LCD kann einen Knacks abbekommen haben (Es gibt Komponenten, die nach so einem Fehler für die Tonne waren, andere haben interne Schutzmaßnahmen [Keine Ahnung, wie es bei deinem Display aussieht])
Juhu! Es klappt :D Zur Lösung: void init(void) { ANSEL = 0; ANSELH = 0; } Ich habe die ANSEL und ANSELH vergessen, somit waren PORTA und PORTB analog. Außerdem in meiner Busy-Schleife den TRISB als Eingang definiert. Vielen Dank für eure Mühe. Anbei ist mein funktionierendes Programm.
Wenn du alles gelesen hättest was hier gepostet wurde, dann hättest du dir 24 nervenaufreibende Stunden erspart....
Chris B. schrieb: > Wenn du alles gelesen hättest was hier gepostet wurde, dann hättest du > dir 24 nervenaufreibende Stunden erspart.... Oh ich sehs grad, ist leider untergegangen :( Naja immerhin habe ich einiges dazugelernt ^^
>Naja immerhin habe ich einiges dazugelernt ^^
Thumbs up!
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.