PDA

Archiv verlassen und diese Seite im Standarddesign anzeigen : Anfängerfrage: Schalterabfrage in Subroutine



derrabe
18.01.2015, 15:11
Hallo miteinander,
ich bin noch recht neu in der Bascom/Microcontroller Materie und habe gerade folgende Idee auf nem Evaluationsboard versucht zu realisieren:
Ein Schwimmschalter soll den Füllstand eines Gefäßes, dass ständig neu volläuft regeln und dazu ggf eine Tauchpumpe ein und auschalten. Um zu verhindern, dass der Schalter ständig ein und auschaltet will ich mit dem Microcontroller ne ein und auschalteverzögerung realisieren.

Mein Code sah nun so aus: Der Schalter muss 4 Sekunden aktiviert sein, bevor das Programm in die Subroutine Pumpen springt. Dort wird dann der Port für die Pumpe (aktuell noch ne LED auf dem Evaluationsboard) eingeschaltet. In dieser Routine soll der Port abgefragt werden, wenn dieser für 4 Sekunden aus ist soll die Subroutine verlassen werden und das ganze Spie von vorne beginnen.

Jedoch klappt das nicht so wie ichs mir vorstellt, da das Programm zwar in die Routine Pumpen springt, aber die LED dann dauerhaft anbleibt. Woran liegt das?

Im folgenden mein Code:


$regfile "m88def.dat"
$crystal = 8000000
$baud = 19200

Led Alias Portb.6
Config Led = Output
Led = 0

Sw1 Alias Pind.2
Config Sw1 = Input
Portd.2 = 1

Reset Led
Main:
Do

If Sw1 = 0 Then

Waitms 4000
If Sw1 = 0 Then

Gosub Pumpen

End If
End If

Loop
End


Pumpen:
Set Led
If Sw1 = 1 Then
Waitms 4000
If Sw1 = 1 Then
Reset Led
Gosub Main
End If
End If
Return

Über Feedbacks würde ich mich sehr freuen

Searcher
18.01.2015, 19:09
Hallo,
ich habe in dem zitierten Code mal etwas hinzugefügt und markiert. Das Grüne würde ich der Übersicht halber mit aufnehmen, da sonst die Bascom IDE Einstellungen gültig sind, die man nicht immer gegenwärtig hat.

Bei dem roten Gosub liegt ziemlich sicher ein Problem vor. Das Programm verläßt dort das Unterprogramm ohne den Stackpointer richtig zu bedienen, sondern legt eine weitere Rücksprungadresse auf den Stack statt sich die richtige zurückzuholen. Es muß mit Return zurückgesprungen werden! In der "Main" kann das Programm nur wieder zu einem neuen Gosub aber nicht auf ein Return treffen und der Stack wird vermutlich irgendwann überlaufen:cry:. Ob da sonst noch Fehler sind hab ich jetzt nicht weiter überprüft:(.





$regfile "m88def.dat"
$crystal = 8000000
$swstack = 32
$hwstack = 32
$framesize = 32
$baud = 19200
.
.
Main:
Do
If Sw1 = 0 Then
Waitms 4000
If Sw1 = 0 Then
Gosub Pumpen
End If
End If
Loop
End

Pumpen:
Set Led
If Sw1 = 1 Then
Waitms 4000
If Sw1 = 1 Then
Reset Led
Gosub Main
End If
End If
Return



Um die Konstruktion ;) zu umgehen könnte man den SW1 in der Main Loop auf beide Zustände prüfen und dann in jeweils ein Unterprogramm springen. zB:


Do
If Sw1 = 0 And Led = Aus Then Gosub Pumpe_an 'Aus ist eine Konstante mit Wert 0
If Sw1 = 1 And Led = An Then Gosub Pumpe_aus 'Ein ist eine Konstante mit Wert 1
Loop


In den jeweiligen Unterprogrammen kann man dann die 4 Sekunden warten, nochmal SW1 abfragen, eventuell schalten und dann ordnungsgemäß mit Return zurück zum Hauptprogramm.

Eine von vielen Möglichkeiten mit und ohne Timer. So ein waitms hält ja das Programm immer an ...

Gruß
Searcher

dolivo
08.02.2015, 11:12
Wenn sw1=0 ist geht es zum UP Pumpen. Die Led wird eingeschaltet und, da sw1=0 ist geht es sofort wieder zurück. Man muss hier einfügen "bitwait sw1, set".
An dem "gosub main" störe ich mich, da das ja kein UP ist. Es ist überflüssig. Nach dem return geht es ja sowieso zurück.
Ich hoffe, meine Nachricht kommt nicht zu spät.
dolivo

i_make_it
09.02.2015, 07:22
Wenn man nicht den Controller mit warten auslasten will, könnte man SW1 an einen Interrupteingang anschließen und da dann einen Timer starten. Der Timerinterrupt startet dann das eigentliche pumpen. Damit hat man dann "freie" Prozessorzeit, mit der man noch andere dinge ausführen lassen kann (z.B. ein zweiter Speicher mit Pumpe).