PDA

Archiv verlassen und diese Seite im Standarddesign anzeigen : LCD Ausgabe macht uC langsam?



Brantiko
25.03.2009, 23:35
Hallo!
Wenn ich einfache Sachen über mein LCD ausgebe wird der uC extrem lahm!



$regfile = "m8def.dat"
$crystal = 8000000

Config Portb.0 = Output

Config Lcd = 16 * 1
Config Lcdpin = Pin , Db4 = Portc.0 , Db5 = Portc.1 , Db6 = Portc.2 , Db7 = Portc.3 , E = Portd.5 , Rs = Portd.4
Config Lcdbus = 4
Cursor Off
Cls
Do
Toggle Portb.0
Locate 1 , 1 : Lcd "1,22929"
Loop
End


Die LED toggelt gerade mal mit 50Hz! Ohne die Ausgabe an das Display sind es 670kHz.

Hat Jemand ne Ahnung wieso die Ausgabe den uC so langsam macht?
uC im Eimer? Oder gibt das Display irgendwas zurück?
Mit 50Hz kann mn ja nicht mehr viel anfangen :-(


Gruss

Alex[/code]

Gento
26.03.2009, 00:06
Das ist bekannt ,damit das LCD nicht vom Speed überfahren wird.

Wenn Du den Quarz viel langsamer angiebst wird schneller.

Testen was geht und bei den Baud berücksichtigen.

Gento

Brantiko
26.03.2009, 00:14
Baudrate spielt dabei eine Rolle?

veit
26.03.2009, 03:27
in einer loop schleife aufs display draufdonnern ist auch nicht sonderlich geschickt ... wie schnell willst du denn da änderungen wahrnehmen?

ein display braucht seine zeit und meldet wenn es nicht bereit ist "busy" zurück

hatte das mal versehentlich in einem c-code, da hat das display dann nur noch wirres zeug angezeigt

Klingon77
26.03.2009, 10:07
hi,

Dein Display hat dann auch eine Darstellungs-Frequenz von 50 Hz.

Das muß sicherlich nicht sein.
Für eine einfache Anzeige reicht ein kleines Unterprogramm welches man z.B: regelmäßig über Interrupt oder unregelmäßig bei Bedarf anspringt um das Display mit den neuen Daten zu füttern.

Dann verbleibt Dir mehr Rechenzeit für andere Aufgaben.

liebe Grüße,

Klingon77

Brantiko
26.03.2009, 13:58
Moin,
Wenn ich die Ausgabe in eine 100Hz Timerroutine packe, ändert sich nichts am Problem. Ist evlt das Display im eimer bzw gibt es etwas zurück?

Gruss
Alex

jeffrey
26.03.2009, 16:02
Moin,
Wenn ich die Ausgabe in eine 100Hz Timerroutine packe, ändert sich nichts am Problem. Ist evlt das Display im eimer bzw gibt es etwas zurück?

Gruss
Alex
hoi,
nee, vermutlich ist gar nix kaputt, sondern das display einfach zu lang beschäftigt, und dann wird halt gewartet, bis es nicht mehr busy ist, und das dauert.
mfg jeffrey

Brantiko
26.03.2009, 16:12
Okay, aber wie kann ich in ein Zeitkritisches Porgramm ein Display implementieren ohne dass alles aus dem Ruder läuft?

Gruss

Alex

python_rocks
26.03.2009, 18:10
Okay, aber wie kann ich in ein Zeitkritisches Porgramm ein Display implementieren ohne dass alles aus dem Ruder läuft?
Hallo Alex!

Indem du alles Zeitunkritische in die Mainloop verlagerst und alles was zeitkritisch ist in Timer-Interrupthandler (Interrupt Service Routine, ISR).

Das LCD muss auf jeden Fall in der Mainloop angesteuert werden. So langsame Befehle haben in einer ISR nichts **absolut gar nichts** in einer ISR zu suchen.

Tausche deine Programmlogik um. Lasse die LEDs in einer ISR blinken und die LCD-Ansteuerung kommt in die Mainloop.

Achte darauf, dass die ISR nicht lange dauert. Alles was länger dauern kann, muss in die Mainloop.

mfg
Gerold
:-)

Dirk
26.03.2009, 18:18
Hallo Alex,

... wie kann ich in ein Zeitkritisches Porgramm ein Display implementieren ohne dass alles aus dem Ruder läuft?
Da die LCD langsam sind, muss man sich in der Programmlogik überlegen, was man anzeigen will.
Beispiel: Wenn das Display eine Uhr darstellt, wird es nur dann neu beschrieben, wenn sich die Sekunde ändert.
Genauso must du definieren, was dargestellt werden soll. Evtl. kann man auch nur einzelne Zahlen oder Zeichen aktualisieren und nicht das ganze LED neu beschreiben.

Gruß Dirk

wkrug
26.03.2009, 18:59
Achte darauf, dass die ISR nicht lange dauert. Alles was länger dauern kann, muss in die Mainloop.
Das würd ich absolut unterschreiben.
Will man aber trotzdem längerdauernde Funktionen regelmässig aufrufen, kann man in einem Interrupt ein Flag setzen ( Bit Variable ), das von der Hauptroutine abgefragt wird.
Wurde die zugehörige Routine in der Hauptroutine abgearbeitet wird dieses Flag wieder gelöscht.

guenter1604
26.03.2009, 20:08
Hallo Brantiko,

setze in deine Mainloop mal ein wait1.
Dann ist die Hauptschleife richtig langsam. Das heißt aber nicht, daß der ATMega langsam ist.
Lasse jetzt einen Timer alle paar Milisekunden einen Interrupt auslösen. Dort machst du deinen schnellen Code rein. ;-)
Jetzt wird der Interrupcode sehr oft und schnell ausgeführt, der Code in der Mainloop nur wenn gerade nichts anderes zu tun ist. Du siehst, die langsame Mainloop bremst dein Programm nicht aus.

Jetzt zu deinem Displayproblem. So ein Display ist laaaaangsam, alle Änderungen dauern ewig. Das würde theoretisch unser Programm ausbremsen. Da die LCD-Routinen aber in der Mainloop liegen, der schnelle Code aber im Interrupt, wird garnicht auf das Display gewartet, sondern der Interrupt abgehandelt und erst danach wieder nach dem Display geschaut.
Wenn jedoch die Interrupts zu schnell aufeinander folgen, hat der Controller vor lauter Interrupts gar keine Zeit für die Mainloop. Ebenso ist wait1 natürlich auch zu lang. Aber das kriegst du hin.
Ich hoffe ich konnte ein bisschen Klarheit reinbringen.

Günter

TobiasBlome
27.03.2009, 21:38
Ich fasse das mal zusammen:

-Do...Loop mit Hauptprogramm
-LCD-ISR z.b. über Timer&Bit setzen

(Programm nicht getestet, sollte aber funktionieren)


$regfile = "m8def.dat"
$crystal = 8000000

Config Portb.0 = Output

Dim Anzeige as Bit

Config Timer1 = Timer , Prescale = 256
Const Timervorgabe = 36736 'ca 2x / sec
Enable Timer1
Enable Interrupts
On Timer1 Timer_ISR

Config Lcd = 16 * 1
Config Lcdpin = Pin , Db4 = Portc.0 , Db5 = Portc.1 , Db6 = Portc.2 , Db7 = Portc.3 , E = Portd.5 , Rs = Portd.4
Config Lcdbus = 4
Cursor Off
Cls

Do

Toggle Portb.0

if Anzeige = 1 then
Anzeige = 0
goto LCD_ISR
End if

Loop


LCD_ISR:
Locate 1 , 1 : Lcd "1,22929"
Return


Timer_ISR:
Timer1 = 36736
Anzeige = 1
Return


Das LCD aktualisiert 2 mal pro Sekunde - das sollte eigendlich ausreichen...
Wenn du das Signal an deinem Ausgang (Portb.0) mit einem Oszi ansiehst wirst du sehen, dass immer wenn das LCD aktualisiert wird der Ausgang etwas "hängt" das lässt sich nur ändern, wenn du den Ausgang selber über einen Timer laufen lässt(ich weiß ja nicht wie zeitkritisch dein Programm wird).

Tobias

for_ro
27.03.2009, 21:55
Do

Toggle Portb.0

if Anzeige = 1 then
Anzeige = 0
goto LCD_ISR
End if

Loop


LCD_ISR:
Locate 1 , 1 : Lcd "1,22929"
Return

Goto und Return passen nicht zusammen, wenn dann also Gosub LCD_ISR.
Allerdings ist das keine ISR und wenn von sonst nirgendwo dorthin gesprungen wird, dann kannst du den Locate... Befehl ruhig direkt in die Abfrage setzen.

Gruß

Rolf

TobiasBlome
27.03.2009, 22:03
oh ja gosub wollte ich auch eigendlich schreiben....



Allerdings ist das keine ISR...

Wann ist es denn eine ISR?

Wie funktioniert das mit "Locate"? Habe es in der Hilfe nur in Verbindung mit LCD´s gefunden.

Tobias

Jaecko
27.03.2009, 22:15
Ich mach das bei Nur-Text-LCDs und genügend Speicher immer so, dass ich den aktuellen Displayinhalt in eine String-Variable speichere.
Soll was geändert werden, wird der neue Inhalt in eine 2. Variable geschrieben. Am Ende der Main-Loop werden beide verglichen. Sofern unterschiedlich: Neu aufbauen, alten String = neuen String setzen.

Es wird also nur dann was zum LCD geschickt, wenn sich auch was ändert.

for_ro
27.03.2009, 22:19
Eine ISR ist eine Interrupt Service Routine, also ein Stück Code, das ausgeführt wird, wenn ein bestimmter Interrupt aufgetreten ist.
Ich meinte nur, ich würde es nicht LCD_ISR nennen, eben weil es demnach keine ISR ist.
Locate gibt es nur für LCDs. Du setzt damit die Stelle, wo die nächste Ausgabe positioniert wird.
Ich würde die Loop also so schreiben

Do
Toggle Portb.0
if Anzeige = 1 then
Anzeige=0
Locate 1,1 : LCD "1,22929"
End if
Loop

guenter1604
28.03.2009, 10:14
Hallo miteinander,

fast richtig.

Ob das Display jetzt ein bisschen früher oder später aktualisiert wird ist doch eigentlich egal. Darum würde ich dafür KEINEN Interrupt bemühen. Dieser ist für Programmcode gedacht, der SOFORT ausgeführt werden MUSS und nicht unterbrochen werden darf, also timingkritisch ist. Das alles ist das Display nicht. Das setzen von Anzeige=1 würde ich nur da in den Code einbauen, wo auch was im Display geändert werden soll.