PDA

Archiv verlassen und diese Seite im Standarddesign anzeigen : Unterprogramm durch Interrupt auslösen



YaNnIk
07.01.2010, 15:19
Hi Leute..

Also es geht (wieder) um eine Beleuchtungsteuerung..

Und zwar soll folgendes passieren :

1. An Int0 liegt das Signal eines PWM empfängers an.
2. Sobald das signal an Int0 wechselt wird die ISR "Messen" ausgelöst. Diese startet Timer0 und sobald das signal wieder wechselt wird der Timer gestoppt. So habe ich dann einen Wert zwischen 62,5 und 125..

Bis hierhin schonmal den Code :


$regfile = "m644def.dat"
$crystal = 16000000

Config Porta = Output
Config Portc = Output
Config Portd.2 = Input

Dim Reading As Bit
Dim Empf_wert As Byte

Reading = 0

Config Timer0 = Timer , Prescale = 256
Enable Timer0
Stop Timer0
On Timer0 Error

Config Int0 = Change
On Int0 Messen
Enable Interrupts
Enable Int0



Do

Loop

End


Messen:

If Reading = 0 Then
Start Timer0
Reading = 1
Else
Stop Timer0
Empf_wert = Timer0
Timer0 = 0
Reading = 0
End If
Return

Error:

Stop Timer0
Return

So, nun will ich in der ISR "Messen" zwei verschiedene "Sprünge auswählen"

Undzwar geht es um folgendes : Wenn der Wert < 95 ist soll ein Programm ablaufen und wenn der wert > 95 ist soll ein ANDERES programm ablaufen..

Also ich will im Prinzip durch den im Interrrupt ermittelten Wert zwei unterschiedliche Programme starten.. Das erste Programm soll einfach sein, das alle LEDs auf High gesetzt werden und das zweite soll ein Lauflicht werden..

Da kommt aber noch ein Problem hinzu.. Undzwar wird das Signal am Empfänger ja mehrere mal in der Sekunde gesendet und jedes mal die ISR "Messen" ausgelöst.. Das Problem ist das nur, das wenn der Wert > 95 ist, würde das Lauftlicht-Programm jedes mal neu starten.. Das soll aber nciht passieren, es soll an der Stelle weiterlaufen wo es aufgehört hat..

Leider weiß ich noch nicht so ganz wie ich das realisieren soll..

Hoffentlich könnt ihr mir helfen..

Danke im Vorraus ;-)


Mfg Yannik

PicNick
07.01.2010, 16:11
In der ISR machst du eigentlich garnix ausser "empf_wert" ändern.
Damit steuerst du, welches Programm in der Hauptschleife läuft


DO
if empf-wert > 95 then
gosub next_lauflicht_step
else
gosub Led_alle_high
endif
LOOP

YaNnIk
07.01.2010, 16:23
Ahh, Danke, den Befehl Gosub kannte ich vorher garnicht :D

Aber dann halt noch die Frage : Wird wärend der Subroutine auch das Hauptprogramm ausgeführt???
Weil das Lauflicht wird mit Wait befehlen arbeiten und es dauert ein bisschen bis es durch ist..

Bei dem von dir beschriebenen Code würde erst die ganze Subroutine durchlaufen und dann würde erst wieder überprüft werden, welche Subroutine gestartet wird, oder??

Was ich braucht ist im Prinzip so : Wenn ich den Schalter am Sender umlege und sich damit der Empf_wert ändert, soll sofort die jeweilige Subroutine gestartet werden und nicht erst gewartet werden, bis die Schleife wieder im Hauptprogramm ist..

Geht das, oder soll ich diese Kurze Zeit in kauf nehmen???

(Problematisch wird halt noch, weil neben dem lauflicht auch noch andere empfänger Kanäle ausgewertet werden sollen und andere sachen geschaltet werden sollen.. ich weiß halt nicht ob das dann zu lange dauern würde..)


was ich mir so vorstelle (keine ahnung ob es sowas gibt) ist im prinzip ein interrupt..

Also angenommen der emp_wert steht momentan auf 70.. Nun will ich sozusagen einen interupt auslösen wenn der wert 65 oder 75 erricht und in diesem interrupt dann von der aktuellen subroutine zurück in die hauptschleife verweist, in der dann ausgewählt welche subroutine gestartet wird...


Puh, das ist schwierig zu erklären xD Also sobalt sich der Empf_wert um +5 oder -5 ändert, möchte ich einen interrupt auslösen, der sich vorrangig vor alle anderen schlaifen und subroutinen stellt.. gibt es sowas???


Edit : muss ich die Subroutinen vorher irgendwie definieren, oder kann ich die so verwenden??

PicNick
07.01.2010, 16:44
Wenn der µC mehrere Dinge tun soll, ist irgendeine Schleife mit "WAIT" auf jeden Fall pfui.
Dazu kann man (z.B.) eine weiteren timer beschäftigen, der vor "wait" gestartet wird und sagt, wann es wieder weitergeht.
However, wenn mehrere Dinge unabhängig laufen sollen und sich aber gegenseitig unterbrechen können, wird es trickreicher.

YaNnIk
07.01.2010, 16:54
Ich glaube das mit dem Timer lasse ich lieber. .Bei so vielen sachen wir mit das zu komliziert...

Nachher stehe ich da, nix funktioniert und ich hab nur frust.. Wäre ja blöde...


Trotzdem danke für deine Hilfe ;-)

021aet04
07.01.2010, 17:35
@YaNnIk
Du hast recht mit dem Frust. Anfangen würde ich mit z.B. wait. Danach würde ich mich z.B. mit Timer beschäftigen und das Programm immer weiterentwickeln bis es perfekt läuft.

MfG Hannes

peterfido
07.01.2010, 18:47
Eine Möglichkeit, welche ich zu meinen Anfängen mal genutzt habe( Prinzip...):


Dim Modus as byte
dim pause as integer
config portb=output '8leds an port b
leds alias portb

do
if modus = 1 then gosub prog1
if modus = 2 then gosub prog2
loop
end

prog1:

set leds 'alle leds an
for pause=1 to 500 '0,5 Sekunden leuchten lassen
waitms 1
if modus <> 1 then goto ende1
next pause
reset leds
for pause=1 to 500 '0,5 Sekunden dunkel lassen
waitms 1
if modus <> 1 then goto ende1
next pause
goto prog1
ende1:
return

prog2:

leds=1 '1. led an
wdh2:
for pause=1 to 500 '0,5 pause
waitms 1
if modus <> 2 then goto ende2
next pause
rotate leds,left 'lauflicht...
goto wdh2
ende2:
return

Messen:

If Reading = 0 Then
Start Timer0
Reading = 1
Else
Stop Timer0
Empf_wert = Timer0
Timer0 = 0
Reading = 0
if empf_wert>95 then
modus=1
else
modus=2
endif
End If
Return


alles aus dem Kopf und ungetestet. Evtl kleine Fehler dann selbst beheben...

"Heute" nutze ich meist einen Timer, welcher alle 10 ms (je nach Bedarf)die Variable Tickcount hochsetzt, beim PC bei der gettickcount API abgeschaut