Archiv verlassen und diese Seite im Standarddesign anzeigen : Anfängerfrage, Taster als Schalter
hardstyleroxx
28.09.2005, 20:30
Hey,
mein myAVR Board ist da und ich finde es bis jetzt echt serh gut, gab noch keine Probleme.
Habe schon ein paar lauflichter und solche spielereien gebastelt und hänge nun bei der Funktion einen Taster als Schalter zu benutzen.
Ich möchte das wenn ich den Taster an Pind.2 drücke das eine Programm läuft und wenn ich den Taster an Pind.3 drücke das andere. Am besten wäre es dann noch das wenn ich beide taster gleichzeitig drücke kein programm mehr läuft.
$regfile = "m8def.dat" ' Prozessortyp ATmega8
$crystal = 3686400 ' Taktrate
Ddrd = &B11100000 ' PD5-PD7 auf Ausgang
Portd = &B00001100 ' alle LEDs off, PullUP von PinD2 & 3 An
Do ' Beginn Mainloop
If Pind.2 = 0 Then ' Wenn Taster 1 gedrückt..
Portd.5 = 1
Waitms 100
Portd.5 = 0
Portd.6 = 1
Waitms 100
Portd.6 = 0
Portd.7 = 1
Waitms 100
Portd.7 = 0
Portd.6 = 1
Waitms 100
Portd.6 = 0
Portd.5 = 1
Waitms 100
Else ' sonst...
Portd.5 = 0
Portd.6 = 0
Portd.7 = 0
End If
If Pind.3 = 0 Then ' wenn Taster 2 gedrückt...
Portd.5 = 1
Portd.7 = 1
Waitms 300
Portd.5 = 0
Portd.7 = 0
Portd.6 = 1
Waitms 300
Portd.6 = 0
Else ' sonst...
Portd.5 = 0
Portd.6 = 0
Portd.7 = 0
End If
Loop ' Ende Mainloop
End ' Programmende
'----------------------------------------------------------
Lagere die zwei unterschiedlichen Routinen in Unterroutinen aus. Also mit sub, gosub usw. Dann wirds übersichtlicher!
hardstyleroxx
28.09.2005, 21:17
Könntest du mir das bitte mal an einem Beispiel erklären? Verstehe das nämlich nicht so ganz und die Bascom hilfe verwirrt mich gerade nur ...
Und wie mache ich das denn nun mit der Taster als Schalter Funktion? Ich muss ja irgentwie den zustand vom taster speichern.
Do
If Pind.2 = 0 Then Gosub Test
Loop
Test:
Portd.5 = 1
Waitms 100
Portd.5 = 0
Portd.6 = 1
Waitms 100
und so weiter
Return
:D
$Crystal usw...
Dim T1 as Bit
Dim T2 as Bit
Do
If Pind.2 = 0 then toggle T1
If Pind.3 = 0 then toggle T2
If T1 = 1 then Gosub Taster1
If T2 = 1 then Gosub Taster2
Loop
Taster1:
'hier das Programm für Taster1
Return
Taster2:
'hier das Program für Taster2
Return
Da in den Unterprogrammen selbst schon Wartezeiten eingebaut sind ist das entprellen der Taster nicht notwendig.
Aber die Unterprograme laufen voll durch. Durch drücken eines Tasters wird das Programm nicht abgebrochen!
Um beide als Reset zu verwenden müsste man die Schaltung etwas umbauen. (Und das Progamm anpassen)
Mit GOSUB wird in ein Unterprogramm gesprungen. Mit RETURN geht es wieder dahin zurück von wo aus gesprungen wurde.
TOGGLE schaltet den Zustand um. 0 wird 1, 1 wird 0.
Das Programm ist so noch nicht perfekt. Es wird immer ein Unterprogramm ausgeführt, bis man zufällig zu der Zeit einen Taster drückt, wenn sie abgefragt werden.
Aber da ich deinen gewünschten Ablauf nicht kenne, kann ich es nicht ändern.
hardstyleroxx
29.09.2005, 18:04
Irgentwie bin ich gerade zu dumm. Sitze hier nun 2 Stunden und bekomme es einfach nicht hin eine LED an und aus zu tooglen mitm Taster.
Wäre sehr nett wenn jemand mal gucken kann was in meinem Code falsch ist oder wie es einfacher geht.
$regfile = M8def.dat
$crystal = 3686400
Ddrd = &B10000000 ' PD7 auf Ausgang
Portd = &B00000100 ' PullUP von PinD2 An
Dim T1 As Bit
Do ' Beginn Mainloop
If Pind.2 = 0 Then ' Wenn Taster1 gedrückt, dann..
Waitms 200 ' 200ms warten
If Pind.2 = 0 Then Toggle T1 ' Wenn taster1 immer noch gedrückt, dann Toogle T1
If T1 = 1 Gosub An ' wenn T1 = 1, gehe zum Unterprogramm An
Else Gosub Aus ' sonst gehe zum Unterprogramm Aus
End If
Loop
An:
Portd.7 = 1
Return
Aus:
Portd.7 = 0
Return
End
Jahn Kohlhas
29.09.2005, 23:04
hast du es schon mal mit dem befehl: DEBOUNCE versucht?
DEBOUNCE
Action
Debounce a port pin connected to a switch.
Syntax
DEBOUNCE Px.y , state , label [ , SUB]
Remarks
Px.y A port pin like PINB.0 , to examine.
State 0 for jumping when PINx.y is low , 1 for jumping when PINx.y is high
Label The label to GOTO when the specified state is detected
SUB The label to GOSUB when the specified state is detected
hardstyleroxx
30.09.2005, 12:55
Ich bekomme das einfach nicht hin ...
Kann mir mal bitte jemand den ganzen Code sagen, damit die LED an Portd.7 angeht wenn ich den Taster an Pind.2 drücke. Wenn ich nochmal drücke soll sie ausgehen.
Danke schonmal.
hardstyleroxx
30.09.2005, 15:16
Habs schon alleine hinbekommen !
Und wir müssen jetzt dumm sterben und werden den fertigen Code nie seh'n :(
Er könnte ja den nächsten helfen, die auch das Problem haben und zufällig mal die Suche benutzt haben. Dann müssen die keinen neuen Beitrag eröffnen.
Ich denke das Hauptproblem in deinem Code war die IF-Abfrage.
Schau dir den Syntax für IF mal in der Hilfe genau an.
Entweder:
IF ... THEN ... ELSE
Else kann auch wegfallen.
Oder:
IF...
THEN...
ELSE ...
END IF
auch hier kann Else entfallen. Das wichtige ist das End If! Unter THEN können auch noch viele weitere Befehle stehen.
IF Pind.1 = 0
THEN A=1
B=X
C="Hallo"
ELSE
Y=0
H="H"
END IF
hardstyleroxx
05.10.2005, 21:33
Sorry hier is der Code:
$regfile = M8def.dat
$crystal = 3638400
Ddrd = &B11100000
Portd = &B00001100
Declare Sub An
Declare Sub Aus
Declare Sub Prg1
Declare Sub Prg2
Dim T1 As Bit
Dim T2 As Bit
Do
Debounce Pind.2 , 0 , An , Sub
Debounce Pind.3 , 0 , Aus , Sub
If T1 = 1 Then
Gosub Prg1
End If
If T2 = 1 Then
Gosub Prg2
End If
Loop
End
An:
Toggle T1
Return
Aus:
Toggle T2
Return
Prg1:
Portd.5 = 1
Waitms 100
Portd.5 = 0
Portd.6 = 1
Waitms 100
Portd.6 = 0
Portd.7 = 1
Waitms 100
Portd.7 = 0
Return
Prg2:
Portd.5 = 1
Waitms 400
Portd.5 = 0
Portd.6 = 1
Waitms 400
Portd.6 = 0
Portd.7 = 1
Waitms 400
Portd.7 = 0
Return
Nun habe ich leider das Problem, dass ich die Programme nicht mehr sauber abschalten kann. Is ja auch logisch, da er das Programm erst ganz abarbeiten möchte bevor er stoppt. Also muss man genau im richtigen moment stoppen. Jemand ne idee wie ich das lösen kann?
Einen externen Interrupt verwenden.
Aber wie ich schon gesagt habe, wenn du von der Programmierung noch nicht soviel Ahnung hast und dir ein fertiger Code mehr helfen würde, muss man den genauen Ablauf des Programms kennen.
hardstyleroxx
05.10.2005, 22:53
Der Code ist mein komplettes programm, es geht halt bei mir immoment nur darum die Grundfunktionen kennenzulernen (LED an LED aus, taster usw.)
Die Funktion vom geposteten Code:
Portd.5 & Portd.6 sind LEDs
Pind.2 & Pind.3 sind Taster
Prg1: Leds blinken abwechselnd "Schnell"
Prg2: Leds blinken abwechselnd "Langsam"
Wenn ich Taster1 drücke soll prg1 laufen bis ich den selber Taster nochmal drücke. Das selbe gillt für Taster2 (Blos das dann halt prg2 läuft). Wenn nun prg1 läuft und ich Taster2 drücke soll prg1 aufhören und prg2 anfangen und umgekehrt.
Dann musst du INT0 und INT1 verwenden. Den Syntax findest du in der Hilfe zum Thema Interrupt.
Ein INT unterbricht das laufende Programm und führt das Programm in der SUB zun INT aus.
In deinem Fall könnte da das togglen stehen.
Ich glaube du hast mich etwas falsch verstanden. Als ich davon sprach das man den genauen Ablauf des Programmes kennen müsste, meinte ich damit, den Funktionsablauf. Was soll wann pasieren.
Es bringt ja nicht viel, einen fertigen Code zu sehen, der offentsichtlich Fehler beinhaltet und man frage wo der Fehler ist.
Die, die den Fehler suchen sollen, müssen ja ganz genau wissen, was eigentlich passieren sollte.
Und ganz genau heisst auch wirklich ganz genau. Dazu gehört dann ggf. welche Funktionen oder Taster Vorrang haben sollen und vieles mehr.
hardstyleroxx
06.10.2005, 20:42
Es muss aber doch noch eine andere Lösung geben um ein laufendes "programm" zu unterbrechen als int0 und int1. Was ist denn wenn ich z.B an 8 eingängen Taster habe und die sollen alle eine unterbrechende Funktion haben?
Das ganze ist kein PC!
Wenn du schreibst waitms 300, dann wartet er auch wirklich 300ms und schaut nicht nebenbei was andere Schalter noch so machen. Der läuft sein Programm Schritt für Schritt von oben bis unten ab und verzeigt auf Anweisung ab und zu mal.
Und selbst der PC (außer Intel's HT im Ansatz) macht das so! Da haben die Steckkarten auch alle einen Interrupt der dann weiteres anfordert.
Bei 8 Tastern könnte man alle Taster zusätzlich mit Dioden von einander entkoppelt auf einen INT legen. Und in der SUB des INT wird dann abgefragt, welcher Taster tatsächlich gedrückt wurde.
Sonst geht es nur, wenn die Taster dauerhaft abgefragt werden. Aber dann ist keine Zeit mehr da um das restliche Programm auszuführen.
Es geht nunmal nur mit Interrupts das Programm zu verlassen.
Aber wenn du sagst, "es muss", musst du ja auch wissen wie :P
hardstyleroxx
07.10.2005, 11:41
ok ich geb mich geschlagen, dann muss ich halt anfangen mit interrupts zu arbeiten.
Klaus_0168
10.10.2005, 14:35
Hi hardstyleroxx,
sorry, aber hier Interrupts zu verwenden ist eine Verschwendung.
Die Funktion die Du haben willst ist die eines RS-Flip-Flop's.
ACHTUNG - In den folgenden Zeilen fehlen mit Sicherheit Semikola u.s.w. es sollte jedoch klar sein, was gemeint ist. 'Merker' ist eine Bitvariable, mit der der Schalterzustand zwischengespeichert wird. Unter Subroutine sind die Zeilen abgelegt, die Du beim Einschalten abarbeiten willst.
If Pind 1.0 = 1 then 'Wenn der Einschalttaster betätigt wird Merker setzen
Merker = 1
If Pind 1.1 = 1 then 'Wenn der Ausschalttaster betätigt wird Merker löschen
Merker = 0
If merker 0 1 then 'Wenn Merker gesetzt ist in Subroutine verzweigen
gosub Subroutine
: Subroutine
hier steht der Code für die Subroutine
End Of Programm
Grüße Klaus
If Pind 1.0 = 1
Diese Zeile wird doch aber nur dann abgearbeitet, wenn das Programm grade an dieser Stelle ist.
Wenn das Programm an der Stelle ist wo ein anderer Pin abgefragt wird, wird der erste(zitierte) nicht erkannt.
Somit ist es doch nicht möglich, das eine blinken zu unterbrechen und sofort zum nächsten zu wechseln.
Ich lass mich auch gerne belehren. Bin heute morgen früh aufgestanden und grade erst nach Hause gekommen. Mag sein das ich estwas unkonzentriert gelesen habe.
Klaus_0168
11.10.2005, 00:20
Hi Marco78,
Ich sehe gerade, das ich zwei Zeilen vergessen habe.
Richtig wäre :
: Anfang 'Anfang der Endlosschleife
If Pind 1.0 = 1 then 'Wenn der Einschalttaster betätigt wird -> Merker setzen
Merker = 1
If Pind 1.1 = 1 then 'Wenn der Ausschalttaster betätigt wird -> Merker löschen
Merker = 0
If merker = 1 then 'Wenn Merker gesetzt ist -> in Subroutine verzweigen
gosub Subroutine
Goto Anfang 'Rücksprung zum Anfang
: Subroutine
hier steht der Code für die Subroutine
End Of Programm
Sinn und Zweck des Ganzen ist folgender.
Zwischen ':Anfang' und 'Goto Anfang' ist der Programmcode, der die Abfrage der Taster vornimmt. In diesem Fall ist es eine Endlosschleife, die sehr schnell abgearbeitet wird, bis ...
... die Bitvariable 'Merker' gesetzt ist. Wenn der Merker gesetzt ist wird in die Subroutine verzweigt. In der Subroutine muss jetzt gewährleistet werden, daß diese so schnell wie möglich abgearbeitet wird. Das ist zwingend notwendig, damit die Taster so oft wie möglich abgefragt werden können. Waitbefehle sollten so klein wie möglich gewählt werden. Die Kombination eines kurzen Waitbefehles mit einem Zähler führt zu einem langen Wartezeitraum. Mit dem 'Select Case' - Befehl kann der Zählerstand und damit die abgelaufene Zeit in der Subroutine verwendet werden. Das hat jetzt aber nichts mehr mit dem Tasterproblem zu tun.
Grüße Klaus
Powered by vBulletin® Version 4.2.5 Copyright ©2024 Adduco Digital e.K. und vBulletin Solutions, Inc. Alle Rechte vorbehalten.