Archiv verlassen und diese Seite im Standarddesign anzeigen : LCD flackert bei Verwendung von Gosub Anweisungen! Warum?
elcapitano
22.03.2008, 17:24
Hallo zusammen,
ich bin recht neu beim Thema Microcontrollerprogrammierung und bastle hier gerade zwecks Wissensaufbau etwas herum.
Ich möchte mir ein Menü per LCD Display bauen - ansich funktioniert die Ansteuerung auch wirklich gut.
Mein Problem ist, dass - immer wenn ich irgendwo im Programm einen Sprung mit Gosub oder Goto einfüge - mein Display anfängt zu flackern. Programmiere ich mit anderen Anweisungen und umgehe Sprünge (z.B. einer While Schleife) dann steht der Text auf dem Display absolut ruhig.
Woran kann das liegen?
Das Ganze läuft derzeit mit 16Mhz Quarz auf einem STK500 mit einem Atmega16...
Ich hab hier mal meinen Code:
$regfile = "m16def.dat"
$crystal = 16000000
'**** Konstanten ****
Const Fw_rev = "0.9"
'**** LCD Initialisieren ****
Config Lcd = 16 * 2
Config Lcdpin = Pin , Db4 = Porta.3 , Db5 = Porta.5 , Db6 = Porta.7 , Db7 = Porta.2 , E = Porta.0 , Rs = Porta.1
'**** Variablendeklaration ****
'**** Ports etc. Parametrieren ****
Config Portd.0 = Input
Config Portd.1 = Input
Config Portd.2 = Input
Config Portd.3 = Input
Config Pind.0 = Input
Config Pind.1 = Input
Config Pind.2 = Input
Config Pind.3 = Input
'**** Sprungverteiler
Cls
Cursor Off
Upperline
Lcd " *** Test1 *** "
Lowerline
Lcd "Lrn Prg Tst Fw?" ' das soll quasi in der unteren Zeite angezeigt werden um darunterliegende Taster als Softkeys zu verwenden
Debounce Pind.0 , 0 , Pr , Sub
Pr:
Lowerline
Lcd "test1"
Return
End
Schon mal vielen Dank!!!
Grüße
ElCapitano
Da fehlt im Hauptteil:
Do
Loop
lg gento
elcapitano
22.03.2008, 17:36
Stimmt...hatte ich zu Testzwecken rausgemacht und verwundert festgestellt dass es trotzdem läuft...
Nur warum?
Das Problem ist mit Do ... Loop genauso vorhanden!
Muß blinken wenn Du immer Cls aufrufst.
Bitte mal den Code mit Do Loop
Gento
elcapitano
22.03.2008, 19:04
Nee...am Cls liegts leider nicht. Das hatte ich auch zuerst vermutet und daher hab ich es dann auch aus der Schleife rausgenommen und nur am Programmanfang einmal ausgeführt und testweise später nochmal ganz rausgenommen.
Hier noch mal mein Code:
$regfile = "m16def.dat"
$crystal = 16000000
'**** Konstanten ****
Const Fw_rev = "0.9"
'**** LCD Initialisieren ****
Config Lcd = 16 * 2
Config Lcdpin = Pin , Db4 = Porta.3 , Db5 = Porta.5 , Db6 = Porta.7 , Db7 = Porta.2 , E = Porta.0 , Rs = Porta.1
'**** Variablendeklaration ****
'**** Ports etc. Parametrieren ****
Config Portd.0 = Input
Config Portd.1 = Input
Config Portd.2 = Input
Config Portd.3 = Input
Config Pind.0 = Input
Config Pind.1 = Input
Config Pind.2 = Input
Config Pind.3 = Input
'**** Sprungverteiler
Cls
Do
Cursor Off
Upperline
Lcd " *** Test1 *** "
Lowerline
Lcd "Lrn Prg Tst Fw?" ' das soll quasi in der unteren Zeite angezeigt werden um darunterliegende Taster als Softkeys zu verwenden
Debounce Pind.0 , 0 , Pr , Sub
Pr:
Lowerline
Lcd "test1"
Return
Loop
End
Hallo elcapitano,
du darfst ein Unterprogramm (Pr:) nicht in die Hauptschleife einfügen.
Unterprogramme gehören hinter das End.
Gruß Dirk
linux_80
22.03.2008, 20:00
Das Unterprogramm sollte nicht in der Hauptschleife liegen, sonst wird das da auch nochmal mit ausgeführt. Und ein Return wenn nix zu returnen da ist, landet irgendwo im Nirvana/ Reset.
Also das Loop oberhalb einbauen.
elcapitano
22.03.2008, 22:27
Hmmm...also irgendwie stimmt hier was nicht...
...ich hab jetzt den Code so wie anbei angehängt. Jetzt flackert zwar nichts mehr aber das Programm funktioniert auch nicht.
Ich hab mir zum Debuggen mal zwei LEDs angehängt (PB.0 und PB.1)...
Folgendes Verhalten tritt auf:
Nach dem Einschalten erscheint auf dem LCD wie erwartet
*** Test 1 ***
Lrn Prg Tst Fw?
Soweit so gut! Nun würde ich erwarten, dass beim Drücken des Tasters, der an PD.0 hängt in der unteren Zeile Test1 ausgegeben wird und durch das Cls der Rest vom LCD gelöscht wird. Das passiert aber nicht. Daher hab ich mir mal die LEDs im Programm gesetzt, da ich gedacht hab, das Programm würde nicht zu Pr: spingen - tut es aber. Nach Druck auf den Taster geht zunächste die LED PB.0 aus, dann nach 2 Sek. auch PB.1. Nur die LCD Anweisungen werden anscheinend nicht ausgeführt!
Nur warum???
$regfile = "m16def.dat"
$crystal = 16000000
'**** Konstanten ****
Const Fw_rev = "0.9"
'**** LCD Initialisieren ****
Dim ___lcdno As Bit
Config Lcd = 16 * 2
Config Lcdpin = Pin , Db4 = Porta.3 , Db5 = Porta.5 , Db6 = Porta.7 , Db7 = Porta.2 , E = Porta.0 , Rs = Porta.1
'**** Variablendeklaration ****
'**** Ports etc. Parametrieren ****
Config Portd.0 = Input
Config Portd.1 = Input
Config Portd.2 = Input
Config Portd.3 = Input
Config Pind.0 = Input
Config Pind.1 = Input
Config Pind.2 = Input
Config Pind.3 = Input
Config Portb.0 = Output
Config Portb.1 = Output
'**** Sprungverteiler
Cls
Do
Cursor Off
Upperline
Lcd " *** Test 1 *** "
Lowerline
Lcd "Lrn Prg Tst Fw?"
Debounce Pind.0 , 0 , Pr
Loop
End
Pr:
Cls
Lowerline
Lcd "test1"
Portb.0 = 1
Waitms 2000
Portb.1 = 1
:-s
Irgendwie ist Dein Code nur Schw_eiße
Initlcd vergessen.
Return nach Gosub.
Statt Lowerlin würde ich Locate 1,1 schreiben
So ist der Code nur Schrott.
Bascom hat zig Beispiele anbei.
Versuche Dich dort mal durchzulesen.
lg
Gento
digitali
22.03.2008, 22:58
Setz erstmal das "Cursor off" vor der do-loop. Man muss dem Display dieses nur einmal zur Laufzeit mitteilen - und nicht permanent. Und anstatt Lowerline und Upperline wuerde ich fest definierte Cursorpositionen anspringen. Also z.B. mit Locate 1,1, oder Locate 2,1 usw.
Und wo ist das "Return" in Deiner Sr-Sub? Und wenn man schon mit Sub's arbeitet, wuerde ich dem Atmel obligatorisch auch etwas hwstack, swstack und framesize spendieren. Schau mal ins Bascom-Beispiel fuer "Debounce".
Und wo wir schon mal grad dabei sind: ein "Config Debounce" gibt's bei Dir auch nicht. :)
Mit freundlichen Gruessen
Digitali
elcapitano
23.03.2008, 00:07
Ok, danke!
"Curser off" ist klar
Ich glaub Lowerline und und Upperline statt "locate x,y" sollten deckungsgleich sein. Jedenfalls sind die beiden erstgenannten Befehle in der Hilfe explizit aufgeführt. Ich hab's mal getetstet und alles durch locate Befehle ersetzt - leider gleiches Ergebnis.
Initlcd braucht man IMHO nicht - die Hilfe sagt dazu folgendes:
The LCD display is initialized automatic at start up when LCD statements are used by your code.
If fore some reason you would like to initialize it again you can use the INITLCD statement.
hwstack, swstack und framesize hatte ich bei den Compileroptionen eingetragen - greift dann ja hoffentlich auch. Sicherheitshalber hab ich es jetzt nochmal in den Code übernommen.
Config Debounce brauch ich doch auch nur, wenn ich nicht die 25ms Standardzeit haben will, oder?
Mein Code sieht jetzt so aus: (Die LED-aufrufe sind zu debugzwecken)
$regfile = "m16def.dat"
$crystal = 16000000
$hwstack = 32
$swstack = 10
$framesize = 40
'**** Konstanten ****
Const Fw_rev = "0.9"
'**** LCD Initialisieren ****
Dim ___lcdno As Bit
Config Lcd = 16 * 2
Config Lcdpin = Pin , Db4 = Porta.3 , Db5 = Porta.5 , Db6 = Porta.7 , Db7 = Porta.2 , E = Porta.0 , Rs = Porta.1
'**** Variablendeklaration ****
Config Debounce = 30
'**** Ports etc. Parametrieren ****
Config Portd.0 = Input
Config Portd.1 = Input
Config Portd.2 = Input
Config Portd.3 = Input
Config Pind.0 = Input
Config Pind.1 = Input
Config Pind.2 = Input
Config Pind.3 = Input
Config Portb.0 = Output
Config Portb.1 = Output
Config Portb.2 = Output
'**** Sprungverteiler
Initlcd
Cls
Cursor Off
Do
Locate 1 , 1
Lcd " *** Test 1 *** "
Locate 2 , 1
Lcd "Lrn Prg Tst Fw?"
Debounce Pind.0 , 0 , Pr , Sub
Portb.2 = 1
Loop
End
Pr:
Cls
Locate 2 , 1
Lcd "test1"
Portb.0 = 1
Wait 1
Portb.1 = 1
Return
Leider gleiches Ergebnis - funktioniert nicht. Die LEDs zeigen mir, dass er zum Label springt.
Wie ist denn das? Der Code wird doch sequenziell abgearbeitet, oder? Eigentich sollte doch der Code zwischen Do ... Loop erst weiter ausgeführt werden wenn mit return aus dem Sub zurückgesprungen wird, oder?
Wenn das nämlich nicht so wäre, dann würde ja u.U. schon wieder der alte Texte ins Display geschieben...
linux_80
23.03.2008, 01:59
Hi,
Das Programm funktioniert auf jeden Fall, würd ich sagen.
Nach drücken des Tasters kommt für 1 Sekunde "test1", danach gehts wieder von vorne los.
Hab das auf dem RN-Mega8 laufen, darum hab nur die Ports ändern müssen fürs LCD, und für den Eingang PD0 den internen Pullup aktiviert, weil ich aussen keinen dran hab.
Wie schaut das bei Dir aus ?
Evtl. könnte man das noch optimieren, indem man den Text in der Hauptschleife nicht dauernd an das LCD sendet, wenn kein Taster gedrückt wurde, das hat aber jetzt nix mit dem Problem zu tun.
elcapitano
23.03.2008, 12:36
Danke linux_80 für deine Mühe.
Bei mir funktioniert es leider nicht so. Nach dem Anschalten kommt der Text in der Hauptschleife (also die zwei Zeilen), nach einem Tastendruck bleibt er aber einfach stehen (während die LEDs schon reagieren - gesprungen wird also)
Keine Ahnung warum das so ist! Läuft das LCD auf dem RN-Mega8 auch im 4-Bit Pin Mode oder evtl. anders?
Grüße
ElCapitano
elcapitano
23.03.2008, 14:24
Also ich hab jetzt alles probiert,
* Initialisiere das LCD nach dem Sprung noch mal neu,
* schreibe mehrfach den gleichen Text nacheinander
Alles bringt nichts - sobald er zu Pr: gesprungen ist fürt er zwar alle anderen IO Operationen aus (LEDs an PB.0 und PB.1 machen was sie sollen) aber ins LCD wird nichts mehr geschrieben...
Pr:
Initlcd
Waitms 500
For Var = 1 To 20 Step 1
Locate 2 , 1
Lcd "test1"
Portb.0 = 1
Wait 1
Portb.1 = 1
Wait 3
Portb.1 = 0
Portb.0 = 0
Next
Return
Nachtrag:
Also irgendwas mach debounbce anders als ein normaler gosub Aufruf!
Mach ich es nämlich so:
Do
Locate 1 , 1
Lcd " *** Test125 *** "
Locate 2 , 1
Lcd "Lrn Prg Tst Fw?"
If Pind.0 = 0 Then Gosub Pr
Loop
End
Pr:
Cls
Locate 2 , 1
Lcd "test1"
Wait 5
Return
Dann funktiniert es einwandfrei!
Nur dass ich dann die Tasten nicht mehr entprelle...
...gibts Alternativen zu debounce???
linux_80
23.03.2008, 16:02
Bei mir läuft das Debounce wunderbar, welche Bascom-Version hast Du, hier die 1.11.9.1, die gibts auch schon als Demo hab ich gesehen.
Ich hab das letzte Beispiel von Dir verwendet, hab die Ports geändert, fürs RN-M8 muss man noch das RW-Pin per Hand auf 0 legen, danach erst das Initlcd, und schon gings.
Statt Taster hab ich auch nur ein Kabel dran, das ich auf Gnd halte ;-)
Wenn Du selber debouncen willst, musst Du nach dem erkennen des Signals (Taster) eine bestimmte Zeit warten, bleibt der Eingang auf dem Level, kannst du das Sub aufrufen, ändert sich der Wert vorzeitig, beginnt man wieder von vorne und wartet bis der gewünschte Wert wieder auftritt.
elcapitano
23.03.2008, 18:03
Ich hab hier die gleiche Bascom Version - nur als Demo. Vielleicht liegt ja hier der Hund begraben. Außerdem progge ich per AVR Studio - nicht direkt aus Bascom. Aber das sollte ja eigentlich keien Unterschied machen, oder?
Powered by vBulletin® Version 4.2.5 Copyright ©2024 Adduco Digital e.K. und vBulletin Solutions, Inc. Alle Rechte vorbehalten.