PDA

Archiv verlassen und diese Seite im Standarddesign anzeigen : [gelöst] Variable löscht sich nach Interrupt?



robodriver
06.11.2007, 21:00
Hallo Leute,

ich habe ein Problem in meinem Quellcode.
Zunächst mal mein Code in gekürzter Form:


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

Ddrb = &B00111100
Ddrc = &B00001110
Ddrd = &B10000001
Portb = &B00000000
Portc = &B00000000
Portd = &B00001000

Eingang Alias Pind.3
Code_hoch Alias "0111011110"
Code_rechts Alias "1011101101"
Code_links Alias "0011011110"
Code_runter Alias "1011001101"
Code_enter Alias "0111101101"
Code_frechts Alias "1011011110"
Code_flinks Alias "0011101100"
Error_led Alias Portd.7

Dim Statusbit As Byte
'Bits im Statusbyte:
Faceauf Alias 0
Get_data Alias 1
Menue Alias 2

On Int1 Ir_dataempfang

Enable Int1
Enable Interrupts

Hauptschleife:
Do

Loop

Ir_dataempfang:
'Dieser Teil ist für euch unbedeutend-----
Set Error_led
For A = 0 To 71
Temp(a) = Eingang
Waitus 902
Next A

Code = ""
For A = 49 To 58
Tmp = Temp(a)
Code = Code + Str(tmp)
Next A

'-------------------------------------------

If Code = Code_rechts Then
If Statusbit.menue = 1 Then
Menue_cnt = Menue_cnt + 1
Locate 2 , 1
If Menue_cnt > 4 Then Menue_cnt = 1
If Menue_cnt < 1 Then Menue_cnt = 4

If Menue_cnt = 1 Then Lcd "Fahr alleine rum"
If Menue_cnt = 2 Then Lcd " manuell fahren "
If Menue_cnt = 3 Then Lcd " Raumtemperatur "
If Menue_cnt = 4 Then Lcd " Akku Spannung "
End If
End If

If Code = Code_enter Then
If Statusbit.menue = 0 Then
Statusbit.menue = 1
Cls
Locate 1 , 4
Lcd "Hauptmenõ"
Locate 2 , 1
Lcd "Fahr alleine rum"
Menue_cnt = 1
Else
Cls
Locate 1 , 2
Lcd "Menõ verlassen"
Statusbit.menue = 0
End If
End If

Do
'Warte bis Taste wieder losgelassen wurde
A = A + 1
If A > 125 Then
Goto Losgelassen
End If
If Eingang = 0 Then A = 1
Waitms 1
Loop

Losgelassen:
Reset Error_led
Return


So, nun zu meinem Problem:
Das öffnen und schließen des Menüs über die enter-Taste funktioniert einwandfrei.
Nun habe ich aber ein Problem mit der rechts-Taste:
Wenn diese betätigt wird springt er in die Entsprechende If-Schleife. Wenn er bei dem Befehl Menue_cnt = Menue_cnt + 1 ankommt ist diese Variable allerdings IMMER 0 und somit springt er an dieser Stelle immer auf 1. (was auf dem Display dann "Fahr alleine rum" entspricht.

Hoffe irgendjemand versteht was ich meine....

Irgendwie wird die Variable Menue_cnt nach meinen bisherigen Beobachtungen bei jedem Interrpt-Aufruf auf 0 gesetzt (Habe mir die Variable an verschiedenen Stellen auf dem Display mal anzeigen lassen. Nach auslösen der Interrupts über enter ist sie 1 und beim nächsten Interruptaufruf ist sie schon wieder 0). Woran liegt das?
Kann sich das jemand erklären? Was kann man dagegen tun? Oder ist doch noch ein Fehler im Quellcode?

tausend dank schonmal an diejenigen die sich die Mühe machen und versuchen mir zu helfen. Bin für jedne Tipp dankbar.

Gruß Robodriver

PS: Einstellungen:
HW Stack = 64
Soft Stack = 16
Framesize = 32

Dirk
06.11.2007, 21:31
Hallo robodriver,

eine Interruptroutine sollte so kurz wie möglich sein. Das warten auf eine Taste darf auf keinen Fall in einer ISR stattfinden!
Grund: Je nach deiner Timer-Frequenz (kenne ich ja nicht) wird die ISR nicht angesprungen, weil sie ja immer noch läuft. In der ISR solltest du nur z.B. den Eingang abfragen und ein Flag setzen. Das wird dann im Hauptprogramm verarbeitet.

Gruß Dirk

robodriver
06.11.2007, 21:43
Hm, okay.

Dann mal die nächste frage hinterher:
Da kommen noch einige Tasten mehr dazu. Also die Interruptroutine wird schätzungsweise nochmal um das 4 fache größer.

Somit wäre es dann auf jeden Fall notwendig das ganze auszulagern.
Das einlesen des Codes würde ich noch ganz gerne in der Interrupt-Routine machen.
Aber wo soll ich denn am besten die Daten-Auswertung hin schreiben?
Die Hauptschleife wird früher oder später auf jeden Fall noch um einiges voller und sehr umfangreich. evtl. werden es sogar 2 oder 3 Hauptschleifen die je nach Betriebsart durchlaufen werden.
Wie soll ich da dann am günstigsten die Datenauswertung hin schreiben?

Vitis
06.11.2007, 23:30
entweder in eine Subroutine (Sub)
oder in eine Funktion (Function)
Hat ausserdem den Vorteil, das Du an beliebigen
Stellen Deines Programmablaufs dort hin und zurück springen
kannst, also für Deine x Betriebsmodi beispielsweise
nur einmal die Anzeigeroutine proggen musst anstatt
x-mal

robodriver
07.11.2007, 09:00
Hm,
meinst du das so in etwa?:


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

Ddrb = &B00111100
Ddrc = &B00001110
Ddrd = &B10000001
Portb = &B00000000
Portc = &B00000000
Portd = &B00001000

Eingang Alias Pind.3
Code_hoch Alias "0111011110"
Code_rechts Alias "1011101101"
Code_links Alias "0011011110"
Code_runter Alias "1011001101"
Code_enter Alias "0111101101"
Code_frechts Alias "1011011110"
Code_flinks Alias "0011101100"
Error_led Alias Portd.7

Dim Statusbit As Byte
'Bits im Statusbyte:
Faceauf Alias 0
Get_data Alias 1
Menue Alias 2

On Int1 Ir_dataempfang

Enable Int1
Enable Interrupts

Hauptschleife:
Do

Loop

Ir_dataempfang:
'Dieser Teil ist für euch unbedeutend-----
Set Error_led
For A = 0 To 71
Temp(a) = Eingang
Waitus 902
Next A

Code = ""
For A = 49 To 58
Tmp = Temp(a)
Code = Code + Str(tmp)
Next A

'-------------------------------------------

gosub auswertung_code

Do
'Warte bis Taste wieder losgelassen wurde
A = A + 1
If A > 125 Then
Goto Losgelassen
End If
If Eingang = 0 Then A = 1
Waitms 1
Loop

Losgelassen:
Reset Error_led
Return

'Ende Interruptroutine



sub auswertung_code
If Code = Code_rechts Then
If Statusbit.menue = 1 Then
Menue_cnt = Menue_cnt + 1
Locate 2 , 1
If Menue_cnt > 4 Then Menue_cnt = 1
If Menue_cnt < 1 Then Menue_cnt = 4

If Menue_cnt = 1 Then Lcd "Fahr alleine rum"
If Menue_cnt = 2 Then Lcd " manuell fahren "
If Menue_cnt = 3 Then Lcd " Raumtemperatur "
If Menue_cnt = 4 Then Lcd " Akku Spannung "
End If
End If

If Code = Code_enter Then
If Statusbit.menue = 0 Then
Statusbit.menue = 1
Cls
Locate 1 , 4
Lcd "Hauptmenõ"
Locate 2 , 1
Lcd "Fahr alleine rum"
Menue_cnt = 1
Else
Cls
Locate 1 , 2
Lcd "Menõ verlassen"
Statusbit.menue = 0
End If
End If
return
end sub


Dann wird die Auswertung aber doch irgendwie immer noch innerhalb des Interrupts abgearbeitet oder ist das so ein Unterschied weil es im Sub steht?



PS: generall verstehe ich aber immer noch nicht warum die Variable immer wieder auf Null gesetzt wird. Wo kommt der Befehl denn bloß her?
Wenn ein Wert im Speicher einmal drinne steht dann steht er doch drinne. Wer Pfucht denn da dann am Speicher und macht aus der 1 wieder eine 0 ?

robodriver
08.11.2007, 09:04
Hat denn keiner weiter eine Idee?

Bin auch offen für neue komplett andere Source-Vorschläge.

Das ganze ist für meinen Roboter die IR-Fernbedienungs-Fernsteuerung (tolles Wort :) )
Folgende Anforderungen müssen erfüllt werden:
- Sofortige Reaktion auf Tastenereignisse
- Erfassung von "Key Down" --> Reaktion und "Key Up" --> Reaktion
- Entscheidend sind die ersten Bits. Diese verraten welche Taste gedrückt wurde. Was danach kommt ist Datentechnisch egal. Key Up wird erkannt wenn eine bestimmte Zeit (etwa 125ms) keine Daten mehr angekommen sind.

Eine bessere Lösung als alle Auswertungen ins Interrupt zu setzen ist mir noch nicht gekommen.

PS: Ausgewertet werden müssen Später insgesammt 17 Verschiedene Tasten. Auf manche Tasten (hauptsächlich die Pfeiltasten) müssen je nach aktuellen Betrieszustand (Menü oder Auswahllisten oder Manuelle Steuerung) unterschiedliche Aktionen ausgeführt werden.

Komm hier echt nicht mehr weiter :(

Gruß Robodriver

robodriver
14.11.2007, 12:26
Okay, nach seeeeehhhhr langer suche und viel rum probieren bin ich darauf gestoßen, das sich die variable NICHT mehr zurück setzt wenn ich sie eine Zeile weiter oben deklariere.

Dann habe ich mir das ganze mal genauer angesehen und den Fehler festgestellt:



Die Variable Temp ist folgender maßen declariert:
Dim Temp(72)

im code befülle ich den Array wie folgt:

For A = 0 To 71
Temp(a) = Eingang
Waitus 902
Next A



Und da steckt der fehler....
Arrays beginnen bei BASCOM nicht mit 0 sondern immer bei 1...
(Das wusste ich nicht, hab es später erst in der Hilfe gelesen)

Somit wird ein bestimmter Speicherbereich für temp freigehalten. Wenn ich aber auf temp(0) was schreibe, dann wandert dieser Wert eine Variable VOR den freigehaltenen Bereich und überschreibt mir somit jedes mal mein Menue_cnt mit einer 1....

Ärgerlich, aber zum glück gefunden und beseitig :)

Gruß Robodriver