PDA

Archiv verlassen und diese Seite im Standarddesign anzeigen : HEX Codierschalter und If-Then-Elseif



128er
17.12.2011, 17:56
Hallo miteinander,
mein Problem schildert sich wiefolgt. Ich habe am PortD.7-D.4 einen Hexadezimalen Codierschalter angeschlossen. Also 1-2-4-8, die C Anschlüssen liegen auf VCC.
Benutze übrigens das RN-Control 1.4. Zur optischen Kontrolle schalte ich die Leds am PortC durch, um den Schalterzustand zu erkennen.

Nur leider passiert rein garnichts. Habs auf vielen Wegen probiert. Nichts hat zum Erfolg geführt.

Liegt es evtl. an der Binärschreibweise wenn ich PortD lesen will? Aber so wie ich das verstehe kommt der obere Nibble doch als erstes. Also würde PortD=&B10000000 eine 1 an PortD.7 bewirken. Das nur zum Verständnis meinerseits. Eigentlich sollte man mit PINX= ... doch auch den ganzen Port abfragen können. Oder ist die If-then-Elseif-Verzweigung Mist?

Nach zwei Tagen ausprobieren und I-Net Recherche find ich keinen Ansatz mehr.

Achso... Schalter ist voll funktionsfähig und gibt die richtigen Zustände an PortD aus

Hier der Code:


$regfile "m32def.dat"
$crystal = 16000000
$framesize = 32
$swstack = 32
$hwstack = 32

Config Portc = Output
Config Portd = Input


Do


If Pind = &B00000000 Then
Portc = &B11111111


Elseif Pind = &B10000000 Then
Portc = &B11111110


Elseif Pind = &B01000000 Then
Portc = &B11111100


Elseif Pind = &B11000000 Then
Portc = &B11111000


Elseif Pind = &B00010000 Then
Portc = &B11110000


Elseif Pind = &B10010000 Then
Portc = &B11100000


Elseif Pind = &B01010000 Then
Portc = &B11000000

End If

Loop

End

Danke für die Mühe


Gruß 128er

for_ro
17.12.2011, 21:13
Ich habe am PortA.7-A.4 einen Hexadezimalen Codierschalter angeschlossen.
Config Portd = Input
Wo sind sie jetzt dran, an A oder an D?



Eigentlich sollte man mit PINX= ... doch auch den ganzen Port abfragen können.
Du kannst schon mit
Elseif Pind = &B10000000 Then
den ganzen Port abfragen, aber dann müssen auch die unbenutzten Pins auf 0 liegen.
Wenn du also nur 4 Schalter dran hast, dann ist so zunächst einmal nicht sicher, dass sie das auch tun.
Wenn du pulldown Widerstände nach Masse an jeden Pin machst, auch an die mit Codierschalter dran, dann sollte die Abfrage funktionieren.

Kampi
18.12.2011, 11:06
Mach das doch lieber mit einer Select-Case Abfrage. Das ist bischen bequemer als die ganzen Ifs :)

128er
18.12.2011, 13:45
Danke for_ro für den Tip. Funktioniert nun einwandfrei.

@Campi
Da hast du wohl recht. Wofür ich das eigentlich nutzen will, ist ein Codeschloss. Im Programm ist ein 4-Stelliger Code hinterlegt. Zum Codierschalter gibt es noch einen Taster zum bestätigen. Also wählt man die erste Codestelle am Codierschalter und bestätigt. Das gleiche für die 3 weiteren Codestellen. Die Wertigkeit der einzelnen stellen soll dann (evtl. addiert?!) verglichen werden mit dem im Programm hinterlegten Code. Wenn Eingabe und Hinterlegter Code übereinstimmen soll irgendwas geschaltet werden. Eine elektromechanische Verriegelung oder sowas.

Habe schon versucht den hier gezeigten Code für die beschriebene Anwendung weiter zu stricken. Aufgrund fehlender Programmiererfahrung ist es aber nicht immer so einfach den passenden Lösungsansatz zu finden. Der Gedanke mit der Select Case Anweisung kam mir beim lesen allerdings auch schon.

Bin aber weiterhin für jede Idee offen.


Gruß 128er

128er
19.12.2011, 17:10
So sieht das Programm nun erstmal aus. Wenns logischer, einfacher, etc. geht dann ruhig meckern :)

$regfile "m32def.dat"
$crystal = 16000000
$framesize = 100
$swstack = 100
$hwstack = 100


Config Portd.7 = Output 'Ports/Pins definieren
Config Portc = Output
Config Porta = Input
Config Pinb.0 = Input


Declare Sub Stelle1 'Subroutinen festlegen
Declare Sub Stelle2
Declare Sub Stelle3
Declare Sub Stelle4
Declare Sub Erfolg


Led1 Alias Portc.7 'Alias
Led2 Alias Portc.6
Led3 Alias Portc.5
Led4 Alias Portc.4
Taster Alias Pinb.0



Do

If Taster = 0 Then 'Erste Stelle anwählen
Gosub Stelle1
Else
Toggle Portc '"Startsequenz"
Waitms 500
Toggle Portc
Waitms 500
End If

Loop

End 'end program


Sub Stelle1
Do
If Pina = 128 And Taster = 0 Then
Gosub Stelle2 'Sprung zur nächsten Stelle wenn Eingabe richtig und bestätigung gedrückt wurde
Else
Toggle Led1
Waitms 500
Toggle Led1
Waitms 500
End If
Loop
End Sub

Sub Stelle2
Do
If Pina = 16 And Taster = 0 Then
Gosub Stelle3 'Sprung zur nächsten Stelle wenn Eingabe richtig und bestätigung gedrückt wurde
Else
Toggle Led2
Waitms 500
Toggle Led2
Waitms 500
End If
Loop
End Sub

Sub Stelle3
Do
If Pina = 64 And Taster = 0 Then
Gosub Stelle4 'Sprung zur nächsten Stelle wenn Eingabe richtig und bestätigung gedrückt wurde
Else
Toggle Led3
Waitms 500
Toggle Led3
Waitms 500
End If
Loop
End Sub

Sub Stelle4
Do
If Pina = 224 And Taster = 0 Then
Gosub Erfolg 'Hier kann der Sprung zum entsperren bzw. freigabe oder wie auch immer geschehen
Else
Toggle Led4
Waitms 500
Toggle Led4
Waitms 500
End If
Loop
End Sub

Sub Erfolg
Sound Portd.7 , 1000 , 500
End Sub


Die Grundlegende Funktion ist schonmal erfüllt. Die If-Then-Elsif Sache zur Schalterabfrage hat sich als suboptimal herausgestellt. Als das Programm in den Subroutinen werkelte war die Abfrage aus der Hauptschleife wohl nicht verfügbar. Bei der angesprochenen Select-Case Methode ist bei mir noch kein Licht aufgegangen wie das richtig funktioniert.
Manipulationssicher ist das ganze auch noch nicht. Hält man den Taster gedrückt und dreht wild am Codierschalter, springt er natürlich von Stelle zu Stelle. Außerdem wäre dann auch noch ein Zähler notwendig, der die falschen Eingaben festhält und nach Eingabe X alles sperrt.


Gruß 128er

for_ro
19.12.2011, 19:06
Hallo 128er,
die Logik deines ersten Codes ist so:
If Bedingung1 then
...
Elseif Bedingung2 then
...
Elseif Bedingung3 then
...
Elseif Bedingung4 then
...
Elseif Bedingung5 then
...
Elseif Bedingung6 then
...
Elseif Bedingung7 then
...
End If

Das zweite sieht so aus:

If Bedingung1 then
if Bedingung2 then

If Bedingung3 then

If Bedingung 4 then
Else
...
End If


Else
...
End If

Else
...
End If
Else
...
End If

Du erkennst sicherlich den Unterschied. Im zweiten Fall kommt er nur weiter zur nächsten Stelle, wenn die Bedingung stimmt.
Beides scheint für deine Überprüfung nicht ganz geeignet zu sein.
Wenn du willst, dass der Taster zwischendurch auch wieder losgelassen wird, bevor es mit der Erkennung der nächsten Stelle weitergeht, dann kannst du das über ein Bitwait erreichen. Da der Taster in Ruhestellung eine 1 gibt, wäre das dann
Biwait Taster, Set
Dann bleibt die Ausführung solange stehen, bis der Taster losgelassen wird. Danach käme dann ein kurzes Wait, um ein Prellen zu übergehen und dann die nächste Abfrage. Oder du benutzt gleich den Debounce Befehl.
Mit Bitwait sähe das dann so aus:

Bitwait Taster, Set 'Taster losgelassen
Waitms 20 'Prellen abwarten
Bitwait Taster, Reset 'Taster gedrückt
Stelle1 = PinA

Waitms 20
Bitwait Taster, Set 'Taster losgelassen
Waitms 20
Bitwait Taster, Reset 'Taster gedrückt
Stelle2 = PinA

Waitms 20
Bitwait Taster, Set 'Taster losgelassen
Waitms 20
Bitwait Taster, Reset 'Taster gedrückt
Stelle3 = PinA

Waitms 20
Bitwait Taster, Set 'Taster losgelassen
Waitms 20
Bitwait Taster, Reset 'Taster gedrückt
Stelle4 = PinA

Hältst du den Taster gedrückt passiert gar nichts. Drückst du den Taster immer wieder, wird jeweils immer wieder der Wert am Codierschalter übernommen, auch wenn der sich nicht geändert hat.
Nach 4-maligem Drücken werden die 4 Stellen mit der Vorgabe verglichen. Wenn falsch, geht es wieder von vorne los.

Vielleicht hilft dir das ja weiter.

128er
20.12.2011, 22:58
Die Bitwait-Abfrage wie du sie gepostet hast funktioniert von der Sache her sehr gut. Wie könnte ich denn parallel zum Bitwait noch die Leds für die Stellen blinken lassen? Ich habe versucht es folgendermaßen zu lösen


Do

Do
Toggle Led1
Waitms 500
Toggle Led1
Waitms 500
Loop Until Taster = 0


Bitwait Taster, Set 'Taster losgelassen
Waitms 20
Bitwait Taster, Reset 'Taster gedrückt
Stelle1 = Pina

Do
Toggle Led2
Waitms 500
Toggle Led2
Waitms 500
Loop Until Taster = 0



Bitwait Taster, Set 'Taster losgelassen
Waitms 20
Bitwait Taster, Reset 'Taster gedrückt
Stelle2 = PinA

Do
Toggle Led3
Waitms 500
Toggle Led3
Waitms 500
Loop Until Taster = 0


Bitwait Taster, Set 'Taster losgelassen
Waitms 20
Bitwait Taster, Reset 'Taster gedrückt
Stelle3 = Pina


Do
Toggle Led4
Waitms 500
Toggle Led4
Waitms 500
Loop Until Taster = 0


Bitwait Taster, Set 'Taster losgelassen
Waitms 20
Bitwait Taster, Reset 'Taster gedrückt
Stelle4 = Pina

Gosub Vergleichen

Loop

End

Sub Vergleichen
Do
If Stelle1 = &B10000000 And Stelle2 = &B00010000 And Stelle3 = &B01000000 And Stelle4 = &B11100000 Then
Gosub Erfolg
Else
Gosub Misserfolg
End If
Loop
End Sub

Allerdings erfordert das ja einen zweimaligen Tastendruck zur Eingabe. Da erst die Blinkschleife verlassen wird und dann Bitwait kommt. Und ein einbinden des Bitwait in die Until-Bedingung war mir nicht möglich.

Deshalb hab ich es dann so gestaltet:

Do

Do
Toggle Led1
Waitms 500
Toggle Led1
Waitms 500
Loop Until Taster = 0


'Taster gedrückt
Stelle1 = Pina

Do
Toggle Led2
Waitms 500
Toggle Led2
Waitms 500
Loop Until Taster = 0



'Taster gedrückt
Stelle2 = PinA

Do
Toggle Led3
Waitms 500
Toggle Led3
Waitms 500
Loop Until Taster = 0


'Taster gedrückt
Stelle3 = Pina


Do
Toggle Led4
Waitms 500
Toggle Led4
Waitms 500
Loop Until Taster = 0


'Taster gedrückt
Stelle4 = Pina

Gosub Vergleichen

Loop

End

Sub Vergleichen
Do
If Stelle1 = &B10000000 And Stelle2 = &B00010000 And Stelle3 = &B01000000 And Stelle4 = &B11100000 Then
Gosub Erfolg
Else
Gosub Misserfolg
End If
Loop
End Sub

Da werden bei gehaltenem Taster zwar alle Stellen beschrieben. Aber ein manipulieren ist nicht möglich.

for_ro
21.12.2011, 22:14
Eigentlich eher so:


Do

Do
Toggle Led1
Waitms 500
Toggle Led1
Waitms 500
Loop Until Taster = 0


Bitwait Taster, Set 'Taster losgelassen == Taster = 1
Waitms 20
Bitwait Taster, Reset 'Taster gedrückt == Taster = 0
Stelle1 = Pina

Do
Toggle Led2
Waitms 500
Toggle Led2
Waitms 500
Loop Until Taster = 1 'Taster wieder losgelassen



'Bitwait Taster, Set 'Taster losgelassen
'Waitms 20
Bitwait Taster, Reset 'Taster gedrückt
Stelle2 = PinA

Do
Toggle Led3
Waitms 500
Toggle Led3
Waitms 500
Loop Until Taster = 0


'Bitwait Taster, Set 'Taster losgelassen
'Waitms 20
Bitwait Taster, Reset 'Taster gedrückt
Stelle3 = Pina


Do
Toggle Led4
Waitms 500
Toggle Led4
Waitms 500
Loop Until Taster = 0


'Bitwait Taster, Set 'Taster losgelassen
'Waitms 20
Bitwait Taster, Reset 'Taster gedrückt
Stelle4 = Pina

Gosub Vergleichen

Loop

End