PDA

Archiv verlassen und diese Seite im Standarddesign anzeigen : "schleife" unterbrechen



Che Guevara
30.08.2008, 17:53
servus leude,

ich will für ein etwas größeres projekt einige einzelteile davon fertigstellen.
mein jetztiges problem ist es, dass ich eine schleife mit einem tastendruck unterbrechen möchte.



for i = 1 to 100
for n = 0 to 7
portc.n = 0
waitms 100
portc.n = 1
next n
next i


diese schleife läuft im normalfall 100 mal durch, bis das programm etwas anderes macht. das soll auch so sein.
nur habe ich in dem programm die tastenabfrage vom rn-control. jetzt möchte ich, dass bei taste 3 dieser obige code durchläuft.
sollte jedoch bevor i = 100 eine andere taste gedrückt worden sein, soll dieser code sofort verlassen werden und es soll die aktion von taste x (dem tastendruck, der diesen code unterbrochen hat) ausgeführt werden.

ich hoffe, mein gefassel ist so halbwegs verständlich und ihr könnt mir helfen.
danke für eure bemühungen.

gruß
chris

for_ro
30.08.2008, 18:23
Hi,
ich geh' mal davon aus, dass der obige code nicht in einer ISR ausgeführt wird, denn dann ist er nicht unterbrechbar.
Es gibt zwei Möglichkeiten, wie du auf Tastendrücke reagieren kannst. Entweder du fragst dauernd die Pins ab oder du hast die taster an einem externen Interrupt Eingang (z.B. Pin Change) angeschlossen.
Wenn du selber abfragst und es nur eine Taste oder mehrere Tasten an einem Port sind, dann würde ich nach dem Wait eine If Abfrage einbauen. Etwa so:


Config Porta = Input
Config Portc = Output
Config Portd = Output
Dim I As Byte , N As Byte , Taste As Byte , Tasten_flag As Byte
If Taste = 1 Then
For I = 1 To 100
For N = 0 To 7
portc.n = 0
Waitms 100
portc.n = 1
If Pina > 0 Then
Tasten_flag = 1
Exit For
End If
Next N
If Tasten_flag = 1 Then
Exit For
End If
Next I
Elseif Taste = 2 Then
For I = 1 To 100
For N = 0 To 7
Portd.n = 0
Waitms 100
Portd.n = 1
If Pina > 0 Then
Tasten_flag = 1
Exit For
End If
Next N
If Tasten_flag = 1 Then
Exit For
End If
Next I
End If
Tasten_flag = 0
Taste = Pina

Bei der Taste 1 habe ich jetzt einfach mal PortC eingeschaltet, bei Taste 2 PortD.
Wenn mehrere tasten gleichzeitig gedrückt sein können, musst die Tastendrücke erst einmal zwischenspeichern.
Löst der Druck einen externen Interrupt aus, dann wird das tasten_flag in der ISR gesetzt und anstelle des "If PINA > 0 Then" abgefragt.

Klaro?

Gruß

Rolf

Che Guevara
30.08.2008, 21:42
hallo rolf,

danke für deine antwort!

allerdings funktioniert das so nicht :-(
ich habe hier mal meinen code, vielleicht kannst du dir das ja mal ansehen?!?!
währe nett von dir!
das gilt natürlich für alle ;-)



$regfile = "m32def.dat"
$crystal = 16000000
$baud = 9600
$hwstack = 32
$swstack = 10
$framesize = 40

Declare Function Tastenabfrage() As Byte
Declare Sub Batteriespannung()

Config Lcd = 20 * 4
Config Lcdpin = Pin , Db4 = Portc.0 , Db5 = Portc.1 , Db6 = Portc.2 , Db7 = Portc.3 , E = Portc.4 , Rs = Portc.5
Config Lcdbus = 4
Config Adc = Single , Prescaler = Auto
Config Pina.7 = Input
Porta.7 = 1

Config Timer1 = Timer , Prescale = 1024
Enable Timer1
Enable Interrupts
Timer1 = 49910
On Timer1 Isr_von_timer1

Config Timer0 = Counter , Edge = Falling
Enable Timer0
Timer0 = 255
On Timer0 Isr_von_timer0

Dim A As Integer
Dim Taste As Byte
Dim Volt As Single
Dim Secu As Single
Dim Minu As Single
Dim Hour As Single
Dim X As Single
Dim Tasten_flag As Byte
Dim F As Single
Dim T As Single
Dim Freq As Single
Dim N As Long

Const Ref = 5 / 1023

A = 1
X = 1
Secu = 00
Minu = 00
Hour = 00
T = 0
Tasten_flag = 0
F = 0

Cls
Locate 1 , 4
Lcd "Daten-Terminal "
Locate 2 , 1
Lcd "Zeit = "
Locate 2 , 8
Lcd Hour ; Minu ; Secu

Do

Taste = Tastenabfrage()
If Taste <> 0 Then

Select Case Taste
Case 1
Tasten_flag = 0
Call Batteriespannung
Case 2
Tasten_flag = 0
Writeeeprom Secu , 1
Writeeeprom Minu , 10
Writeeeprom Volt , 20
Case 3
For N = 1 To 100000000
Freq = F / T
Cls
Locate 1 , 1
Lcd "Sekunden = " ; T
Locate 2 , 1
Lcd "Signale = " ; F
Locate 3 , 1
Lcd "==> Frequenz = "
Locate 4 , 1
Lcd Freq ;
If Taste <> 3 Then
Tasten_flag = 1
Exit For
End If
If Tasten_flag = 1 Then
Exit For
End If
Wait 1
Next N
Case 4
Tasten_flag = 0
If Secu = 60 Then
Secu = 00
Minu = Minu + 1
Elseif Minu = 60 Then
Minu = 00
Hour = Hour + 1
End If
Cls
Locate 2 , 1
Lcd "Zeit = "
Locate 2 , 8
Lcd Hour ; Minu ; Secu ;
Waitms 10
Case 5
Tasten_flag = 0
Readeeprom Secu , 1
Readeeprom Volt , 20
Cls
Locate 1 , 4
Lcd " Daten-Terminal "
Locate 2 , 1
Lcd Secu ; " Sekunden "
Locate 3 , 1
Lcd Minu ; " Minuten "
Locate 4 , 1
Lcd Volt ; " Volt "
End Select
End If

Loop

Isr_von_timer1:
Timer1 = 49910
Incr Secu
Incr T
Return

Isr_von_timer0:
Timer0 = 255
Incr F
Return

Function Tastenabfrage() As Byte
Local Ws As Word

Tastenabfrage = 0
Start Adc
Ws = Getadc(7)
If Ws < 500 Then
Select Case Ws
Case 400 To 450
Tastenabfrage = 1
Case 330 To 380
Tastenabfrage = 2
Case 260 To 305
Tastenabfrage = 3
Case 180 To 220
Tastenabfrage = 4
Case 90 To 130
Tastenabfrage = 5
End Select

End If


End Function

Sub Batteriespannung()
Local W As Word
Start Adc
W = Getadc(6)
Volt = W * Ref
Volt = Volt * 5.2941
Cls
Locate 1 , 1
Lcd "Die aktuelle "
Locate 2 , 1
Lcd "Spannung betraegt: "
Locate 3 , 1
Lcd Volt ; " Volt "
Waitms 100
End Sub


im prinzip möchte ich ja nur, dass der code in case 3 bis zu einem tastendruck (der dafür sorgt, dass das prog zu einem anderem case springt) ausgeführt wird und dann soll der andere case-code laufen.

gruß
chris

Dirk
30.08.2008, 21:53
Hallo chris,

wenn du innerhalb der Schleife mit der Variable N keine Tastaturabfrage machst, kann die Variable "Taste" nie einen anderen Wert als 3 annehmen. Der Wert 3 ist ja im "Case 3" Abschnitt immer gleich.

Gruß Dirk

Che Guevara
30.08.2008, 22:32
ok, danke
jetzt funzt's.

jetzt habe ich nur noch eine frage:

ich möchte das display immer aktualisieren, deshalb das cls und wait1 in case 3.
gibt es dafür nicht einen befehl, der mir das macht??
außerdem habe ich das problem bei wait 1, dass ich solange auf die taste drücken muss, bis der teil-code durchgelaufen ist (im extremfall 1 sec)....
wenn ich allerdings waitms 1 oder so schreibe, dann kann man auf dem lcd nichts mehr lesen, da das zu schnell ist.
gibt es dafür auch eine lösung???

gruß
chris

Dirk
31.08.2008, 11:23
Hallo chris,

... dann kann man auf dem lcd nichts mehr lesen, da das zu schnell ist. gibt es dafür auch eine lösung???
Das ist eine grundsätzliche Frage zur Ansteuerung eines LCD.

Die stabilste Anzeige ergibt sich auf einem LCD dann, wenn man immer nur dann (und auch nur 1x) etwas auf das LCD schreibt, wenn sich die Anzeige ändern soll.
Bei einer Uhrenanzeige ist das einfach: Man schreibt nur dann auf das LCD, wenn sich die Sekunde ändert. Dazu speichert man sich in einer Variablen (z.B. Oldsecond) die Sekunde ab, die man beim letzten Mal auf das LCD geschrieben hat. Ist Second noch = Oldsecond, dann wird der Schreibbefehl für das LCD einfach übersprungen.
Ist Second <> Oldsecond, dann wird die Uhrzeit neu auf das LCD geschrieben und Oldsecond = Second gesetzt.

Das alles geht dann völlig ohne Cls. Cls würde ich auch weitgehend vermeiden, weil es ein Flimmern durch das Löschen des ganzen LCDs macht, sondern immer nur die geänderten Infos an die Stelle schreiben, wo sie hinsollen. Alle nicht geänderten Texte ("Daten-Terminal") bleiben immer da stehen und werden nicht überschrieben.

Wenn du das so machst, kannst du Wait-Befehle in deiner Hauptschleife ganz weglassen.

Gruß Dirk