PDA

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

Gento
22.03.2008, 17:32
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!

Gento
22.03.2008, 18:35
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

Dirk
22.03.2008, 19:57
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

Gento
22.03.2008, 22:54
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?