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
voiddelay100ms(unsignedchare)
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
>voiddelay100ms(unsignedchare)
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
voidLCD_Ausgabe(unsignedcharwert)
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.
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
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.htmlhttp://octopart.com/datasheet/mdls-16265-ss-lv-g-varitronix-547617-138126http://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.
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 ^^