8Bit-Port abfragen und Wert zuteilen?

dg2ygq

Neues Mitglied
23. Juli 2007
239
0
0
Bielefeld
Sprachen
So, nun bin ich beim mechanischen Kanalschalter angelangt.
Dieser schaltet 8 Pins je nach Kanal gegen Masse.

Beispiel:
Kanal 3 = 10010111
Kanal 4 = 01010111
Kanal 5 = 00011111
....
Kanal 40 = 00100010

(Niderwertiges Bit Links)

Wie bewerkstellige ich das (mit Bascom) in einer Schleife, dass das Bitmuster einem Kanal zugeordnet und einer Variablen übergeben wird?

Ich finde jeden Kanal mit IF-Then zu vergleichen, ist viel zu aufwändig!
Fällt Euch da noch was besseres ein?

Müsste doch mit einer Tabelle auch gehen?
Wie bei der 7Segment-Geschichte einer Zahl dem dazugehörigen Tabelleninhalt zugeordnet werden kann, so muss doch auch dem Tabelleninhalt die (Kanal-)Zahl
zugeortnet werden können ?

Mir würde es auch reichen (gern auch aus weniger Bit`s) ein UP/Down Impuls zu erzeugen, aber da bin ich noch ganz und gar nich schlau draus geworden.
Wenn ihr versuchen wollt mir dabei zu helfen : im Datenblatt zum Sanyo LC7132 stehen die Codes beschrieben :
http://malzev.tripod.com/comp/lc7132.htm


Foto zeigt mein ExperimentierBoard mit Mega8515: PortA und PortB steuern die beiden Anzeigen, an PortD hängt der Kanalschalter, PortC übernimmt dann die Steuerung des PLLs ....
 

Anhänge

  • 8515-kanalschalter.jpg
    8515-kanalschalter.jpg
    91 KB · Aufrufe: 11
Hallo Michael,

eine Tabelle ist hier schon sinnvoll. Ich sehe aus den von dir angegebenen Werten leider keine Möglichkeit den Wertebereich und somit die Tabelle zu verkleinern, so dass man eine Tabelle mit 256Byte erhält. (Kann aber auch sein, dass ich es im Moment einfach nur nicht sehe, mein Kleiner wollte heute Morgen einfach nicht länger schlafen, "schlafen ist ja sooo langweilig" ;), und somit bin ich noch nicht so fit :rolleyes:).

Beispiel:
Kanal 3 = 10010111
Kanal 4 = 01010111
Kanal 5 = 00011111
....
Kanal 40 = 00100010
(Niderwertiges Bit Links)
Anlegen der Tabelle und auslesen:
Code:
Byte_KanalTabelle:
  DATA  $00, $01, 26, ...   'nur ein Beispiel, erster Wert ist für Kanalschalter 0b00000000, letzter Wert für 0b11111111. 

DIM Wert as Byte 
Kanalwert = LOOKUP (PinD, Byte_KanalTabelle) 'PinB ist hier der Anschlußport des Schalters
Die Tabelle wird schon ziemlich groß, ideal wäre es, wenn man den Wertebereich noch verkleinern könnte, wenigstens auf 7bit (128 Werte), besser 6bit (64 Werte).
Den Kanalwert (1 bis 40) könntest du über eine Tabelle mit 7Segment-Anzeige darstellen und über eine wietere Tabelle den PLL ansteuern.

Alternativ könntest du den Kanalschalter durch einen Up/Down-Taster ersetzen. Die Tabelle Byte_KanalTabelle würde dann entfallen und du müsstest die Variable Kanalwert zwischen 1 und 40 inkrementieren/dekrementieren, wenn der entsprechende Taster betätigt wird.

Grüße,
Dirk
 
Hallo Dirk,
ja, schlafen ist soo langweilig, und ganz dolle unproduktiv, kenn ich auch :p

Von den Up/Down-Tastrn möchte ich weg. Ich hatte bissher die U/D-Funktion mit Drehimpulsgeber realisiert. Aber die Drehgeber passen mechnisch nicht in das Funkgerätgehäuse. Dazu muss der originale Schalter ausgebaut werden .... Stress pur :mad:

Ich hatte heute Nacht noch experimentiert, es wurd halb 4 :eek:

Ich habe ein Tabelle mit den 40 8Bit Daten erstellt:
Channel:
Data &B10101111 , &B10100001 , &B11001010 , &B11011000 ....
Aulesen tu ich diese Tabelle mit:
Schalter = Pind
Kanal = Lookdown(schalter , Channel , 40)
Somit erhalte ich die Kanalzahl, indem ich die Tabelle mit dem Bitmuster "vergleiche".


Soweit, so gut!
Nun möchte ich mit diesem 40Kanalschalter aber 80 Kanäle schalten.
Variable "Kanal" soll also einen Zahlenwert von 1 bis 80 durchschalten.
Das aber "durchgehend", also nach 40 soll die 41, nach 80 die 1 erscheinen. Rückwärts natürlich genau so, nach 1 die 80, nach 41 die 40 usw ....

Behelfsweise habe ich ein Portpin abgefragt :
If Pinc.0 = 0 Then Kanal = Kanal + 40
Somit kann ich zwischen oberen und unteren 40 Kanälen wählen, ist aber nicht das was ich haben will, soll eben durchgehend sein.

Könnt ihr mir da mal mit etwas "logik" auf die Sprünge helfen?
 
Hallo Michael,

siehste, jetzt habe ich schon wieder etwas gelernt, Lookdown kannte ich noch nicht.

Um über 80 Kanäle schalten zu können, musst du dir den letzten gewählten Kanal "merken". Zusätzlich musst du noch eine weitere Variable einführen, mit der du dir "merken" kannst, ob der untere oder obere Kanalbereich aktiviert ist (Offset).

Ist der zuletzt gewählte Kanal 40 und der aktuelle Kanal 1 (positiver Überlauf):
  • Offset +40 nicht aktiviert, dann Offset aktivieren: Tatsächlicher Kanal = Kanal + 40 (Überlauf von 40 nach 41)
  • Offset +40 aktiviert, dann offset deaktivieren: Tatsächlicher Kanal = Kanal +0 (Überlauf von 80 nach 1)
Ist der zuletzt gewählte Kanal 1 und der aktuelle Kanal 40 (negativer Überlauf):
  • Offset +40 nicht aktiviert, dann Offset aktivieren: Tatsächlicher Kanal = Kanal + 40 (Überlauf von 1 nach 80)
  • Offset +40 aktiviert, dann Offset deaktivieren: Tatsächlicher Kanal = Kanal +0 (Überlauf von 41 nach 40)
Kanal ist der Wert aus der Tabelle Channel (Wertebereich 1 bis 40).
"Tatsächlicher Kanal" ist der korrigierte Kanal mit dem Wertebereich 1 bis 80.
Bei Programmstart musst du die Variable für den letzten gewählten Kanal initialsieren (=aktuell gewählter Kanal). Die Variable für den aktiven Offset muss ebenfalls initialisiert werden (=nicht aktiviert).

Das hört sich alles ein bisschen kompliziert an, ich hoffe, du kannst mir hier folgen.

Grüße,
Dirk
 
Ja, verständlich ist es, nur das Umsetzen ....... Will ich mich mal drann setzen!

Ich habe mir schon den "alten" Kanal (Variable "A") gemerkt, damit nicht bei jedem Durchlauf der Abfrage (Main) die Kanalanzeige augewertet wird, und das PLL IC unnötigerweise angesprochen wird:

Code:
Main:
   Do
      Schalter = Pind
      If A <> Schalter Then Gosub Auslesen
   Loop
End

Auslesen:
   A = Schalter
   Kanal = Lookdown(schalter , Channel , 40)
   Gosub Ausgabe
   Return
End

So, nun will ich mal sehen ob ich weiter komme!
Danke dir erstmal :)
 
Ahjeh, ich sollte mal ausschlafen fürchte ich :eek:

Wenn Variable "A" auf 40 steht, und "Schalter" nun auf "1" steht, setz ich die +40 Variable.

Nun kann ich aber NICHT in einer IF-Abfrage gleich 2 Bedingungen abfragen?
if A = &B01000100 and Schalter = &B01000100 Then Band = 1
Ist klar "And" bedeutet ja was anderes als Und, aber gibt es da eine Möglichkeit?
Oder muss ich wenn EINE Bedingung erfüllt ist, zu einer anderen Stelle springen?
 
Hilfeeeeeeee,

Ich komm einfach nicht weiter:

Code:
'***** Abfrage-Loop *****
Main:  
   Do
      Schalter = Pind
      If A <> Schalter Then Gosub Auslesen
  Loop
End

Auslesen:

   Kanal = Lookdown(schalter , Channel , 40)
   If Kanal_alt = 40 Then Gosub Ueberlauf  ' War der alte Kanal = 40, verzweige nach ÜBERLAUF

   If Band = 1 Then Kanal = Kanal + 40  ' Über 40, also +40 dazu

   A = Schalter
   Kanal_alt = Kanal
   Gosub Ausgabe  ' LED-Anzeigen Ausgabe
   Return

End

Ausgabe:
    Einer = Kanal Mod 10
    Zehner = Kanal / 10
    Porta = Lookup(einer , Segmente)

    Raus = Lookup(zehner , Segmente)
         If Raus = &H3F Then Raus = 0
         Portb = Raus
    Return

Ueberlauf:
If Schalter = &B11101111 Then Band = 1 'Schalter JETZT auf 1, dann Band-Bit setzen
Return
End

Sollte so funktionieren:
Der alte Kanal wird gemerkt, war der alte Kanal = 40, dann springe nach Überlauf!
Hier wird abgefragt, ob der Schalter JETZT auf 1 (&B11101111) steht, falls ja, wird dem Kanal 40 hinzu addiert......
Falls nicht, müsste der Kanalschalter ja auf 39 (&B10001000) stehen und somit das Band-Bit nicht setzen....

Auch wenn das jetzt nur den Übergang von 40 auf 41 machen soll, und ich mit den Übergängen 80 auf 1 und die Rückwärts-Geschichte noch garnicht berücksichtigt habe, sollte es doch wenigstens diese eine Richtung tun!
Funzt aber alles nicht :confused:

Wo ist mein verflixter Denkfehler ?


Kann ich in einer If-Abfrage 2 Bedingungen gleichzeitig abfragen?
zB : If Kanal_alt = 40 and Schalter = &B10001000 Then Gosub irgendwas ???
 
Hallo Michael,

PortD ist als Eingang geschaltet? Die Darstellung von Werten 1 bis 80 durch 7Segment-Anzeige funktioniert (vielleicht hier einfach einmal langsam mit Pausen einen Wert ab 1 hochlaufen lassen und die Anzeige überprüfen)?

Vielleicht könntest du die Bandumschaltung wie in dem unteren Beispielprogramm realisieren (ich hoffe verschachtelte if-then-else Anweisungen sind in Bascom möglich).

In Main initialisiere ich Band (=unteres Band) und Kanal_alt (=aktueller Kanal) (Man könnte sich später Band im EEPROM beim ausschalten des Gerätes "merken")


Code:
[B]Main[/B]:  

   ' Initialisierung von Kanal_alt und Display, Kanäle 1 bis 40
   Band = 0;
   Schalter = Pind
   Kanal = Lookdown(schalter , Channel , 40)
   Kanal_alt = Kanal
   Gosub Ausgabe

   Do
      Schalter = Pind
      If A <> Schalter Then Gosub Auslesen
  Loop
[B]End[/B]


[B]Auslesen[/B]:

   Kanal = Lookdown(Schalter , Channel , 40)

   ' Umschaltung oberes und unteres Band
   If Kanal_alt = 40 Then 
      If Kanal = 1 Then      
         Band = 1          ' Positiver Überlauf 40->41, auf oberes Band schalten
      EndIf                ' (Schalterposition von 40 auf 1, unteres Band aktiv)
   EndIf

   If Kanal_alt = 80 Then
      If Kanal = 1 Then      
         Band = 0          ' Positiver Überlauf 80->1, auf unteres Band schalten
      EndIf                ' (Schalterposition von 40 auf 1, oberes Band aktiv)
   EndIf

   If Kanal_alt = 41 Then 
      If Kanal = 40 Then      
         Band = 0          ' Negativer Überlauf 41->40, auf unteres Band schalten
      EndIf                ' (Schalterposition von 1 auf 40, oberes Band aktiv)
   EndIf

   If Kanal_alt = 80 Then
      If Kanal = 1 Then      
         Band = 1          ' Negativer Überlauf 1->80, auf oberes Band schalten
      EndIf                ' (Schalterposition von 1 auf 40, unteres Band aktiv)
   EndIf


   ' Band-Offset berücksichtigen
   If Band = 1 Then Kanal = Kanal + 40;

   ' alten Kanalwert merken (einschliesslich Offset)
   Kanal_alt = Kanal

   ' Ausgabe LED-Anzeige
   Gosub Ausgabe

   Return
[B]End[/B]

Grüsse,
Dirk
 
Âlso hier lag mein Denkfehler :
Durch das drehen am Schalter, werden nicht alle Bits zu genau der selben Zeit gesetzt, das Viech sitzt auf mehreren Ebenen, und prellen tuts auch noch. Aus diesem Grunde konnte ich nicht den alten Kanal und den neuen Kanal vergleichen, IF funktionierte einfach nicht, weil die Bits nicht alle gleichzeitig gesetzt waren.

Die Verschachtelung funktioniert auch hier unter Bascom.
Aber auch hier das selbe Problem wie oben beschrieben. Ich sehe es an der 7Segmentanzeige, dass kurzzeitig andere Segmente aufblitzen, sogar der DP blinkt lustig mit.
Ich denke der Programmcode darf erst weiter arbeiten, wenn der Schalter eine Wahrheitsgetreue Stellung gefunden hat ?!
Eine kleine Warteschleife bringt jedenfalls schon Linderung, ist aber auch nicht das gelbe vom Ei.

Wenn ich in "Main" schon die Tabelle abfrage, und checke ob "Kanal" zwischen 1 und 40 steht, dass ich dann erst zur "abfrage" weiter gehe?
 
Hallo Michael,

melde mich auch mal wieder :), war im Urlaub und schaue gerade mal so die Beiträge durch die ich die letzten 4 Wochen verpasst habe :p

Vielleicht habe ich eine Idee und ein Vorschlag für Dich zum Thema prellen, so wie ich es vielleicht lösen würde.

Das Prellen wird bei Dir zum Problem weil Du kein Ereignis hast auf das Du abprüfen kannst ob der Schalter jetzt betätigt wurde oder nicht. Die Bitmuster des Schalters sind willkürlich und daraus läßt sich beim ersten Hinsehen auch nix vernünftiges ableiten.
Prellen bedeutet weiter dass sich die Zustände der Bits noch eine definierte Zeit x beliebig ändern. Man könnte aber jetzt folgendes machen:
Port einlesen (Wert a) und in Variable speichern
Prellzeit x (einstellbar über Konstante) warten
Port nochmals einlesen (Wert b) und schauen ob Wert a=b.
Wenn a=b so hast Du einen stationären Zustand, Du kannst annehmen, dass es sich ausgeprellt hat und die Auswertung starten.
Wenn a<>b so zappelt das ganze noch. Dann einfach nix auswerten und das ganze von vorn.

Jetzt liegt es nur noch an der Größe von x so dass Du über das Zeitfenster des Prellens hinaus kommst.

Was meinst Du, könnte funktieren, oder? So würde ich das Thema mal angehen.

Grüße,
Markus
 
Hallo Markus, du Urlauber (schwarz gebrannt, Bauch voller leckerer Getränke, und jetzt erst recht Urlaubsreif) :D

Klingt schon echt gut, was mich hier nur wieder irritiert, ist die Zeitkonstante ?! Ich werde mich dran setzen, und diese Lösung mal probieren...... Ergebnis kommt demnächst !

Ich habe doch die Bitfolgen sämtlicher 40 Kanäle schon in der Tabelle erfasst. Wäre ja mehr als ein dummer Zufall, wenn er gerade einen dieser Zustände beim prellen erwischt (40 von 256 Möglichkeiten).

Wenn ich den Schalter auslese, und mit den Bitfolgen der Tabelle vergleiche:
- Ist die die ausgelesene Bitfolge vorhanden, dann weiter im Programm
- Ist die Bitfolge nicht vorhanden, nochmals einlesen

Theoretisch klingt das doch auch nicht schlechter, oder?
Aber wie kann ich das praktisch hin bekommen, wenn ich nicht 40 IF-Abfragen machen will ?
 
Hey Michael,

ja, braungebrannt und den Bauch voller Pizza :p Wir warten 14 Tage in der nähe von Jesolo / Venedig am Meer. Mit einer 3,5 Jahre alten Tochter kann man nicht mehr machen als passiver Strandulruab :cool:

Aber nun hat mich die Realität wieder und damit auch das Forum:)

Mit Zeitkonstante meine ich einfach eine Variable z.B.
Code:
DIM wartezeit AS byte
wartezeit = 20
Darüber kannst Du dann folgendes machen:

schalter_a = PIND ' Lese mal den gesamten port
waitms wartezeit ' warte 20 ms
schalter_b = PIND ' Lese nochmals den gesamten port

if schalter_a<>schalter_b then
    ' da hat was gezappelt, also das ganze nochmals
else
     ' stationärer zustand, mach was du willst
endif

weißt du was ich meine? ich würde beim einlesen des bitmusters vom port so lange warten bis sich ein stationärer zustand eingestellt hat. da musst du erstmal noch garnicht mit der tabelle arbeiten.

grüße,
markus
 
Hallo zusammen,

ich hoffe es geht in Ordnung, wenn ich jetzt nichts zum Thread von Michael beitrage. Aber ich möchte Markus auch einmal herzliche Grüße schicken, also Markus ... willkommen wieder zurück :) Das mit dem passiven Strandurlaub kann ich mir gut vorstellen, mein Kleiner wird nächste Woche vier ;) :D

Also beste Grüsse,
Dirk
 
Guten Morgen ihr beiden!
Was waren das für Zeiten als wir unsern Urlaub noch passiv verbringen durften! Mittlerweile müssen wir schon wieder alleine in Urlaub, der große wird nächsten Monat 18 :eek:

Markus, Ich habe deinen Codevorschlag mal eingebracht! Funktioniert wunderbar :eek:
Die Wartezeit konnte ich noch bequem auf 10 herab setzen, somit klappt das auch wenn ich mal schnell (durch)drehe.

Super Lösung. Danke dir!


Dirk,
(Man könnte sich später Band im EEPROM beim ausschalten des Gerätes "merken")
Dann müsste das Band gespeichert werden, wenn die Spannung wegfällt. Ist nur ein einpoliger Einschalter, der die gesamte Versorgungsspannung kappt.

Wie könnte ich das denn realisieren?
- Dicken Elko hinter dem 5VSpannungsregler vom AVR (AVR arbeitet nen bissel ohne "Betriebsspannung" weiter)
- Betriebsspannung vom Einschalter (auf 5V regeln) und auf ein Portpin geben
- Portbin auslesen, wenn low ist, Variable Band ins EEprom schreiben

Oder gibts da noch eine andere (bessere) Möglichkeit ?
 
Hallo Michael,

Wie könnte ich das denn realisieren?
- Dicken Elko hinter dem 5VSpannungsregler vom AVR (AVR arbeitet nen bissel ohne "Betriebsspannung" weiter)
- Betriebsspannung vom Einschalter (auf 5V regeln) und auf ein Portpin geben
- Portbin auslesen, wenn low ist, Variable Band ins EEprom schreiben

Oder gibts da noch eine andere (bessere) Möglichkeit ?

so in etwa. Du könntest hierfür den Komparator des AVR nutzen, in Verbindung mit dem Komparator-Interrupt.
Die Spannung am nicht-invertierenden Eingang stellst du zum Beispiel über einen Spannungsteiler (5V - GND) auf 2,5V ein und die Spannung am invertierenden Eingang entspricht der über einen weiteren Spannungsteiler geteilten Eingangsspannung vor dem 5V-Regler. Angehängt habe ich ein Beispiel.
Den Komparator-Interrupt musst du hier auf steigende Flanke einstellen. In der Interruptserviceroutine speicherst du deine Variable im EEPROM. Bei Programmstart liest du sie wieder aus dem EEPROM in deine Variable.

Grüsse,
Dirk
 

Anhänge

  • comparator.png
    comparator.png
    7,2 KB · Aufrufe: 7

Über uns

  • Makerconnect ist ein Forum, welches wir ausschließlich für einen Gedankenaustausch und als Diskussionsplattform für Interessierte bereitstellen, welche sich privat, durch das Studium oder beruflich mit Mikrocontroller- und Kleinstrechnersystemen beschäftigen wollen oder müssen ;-)
  • Dirk
  • Du bist noch kein Mitglied in unserer freundlichen Community? Werde Teil von uns und registriere dich in unserem Forum.
  •  Registriere dich

User Menu

 Kaffeezeit

  • Wir arbeiten hart daran sicherzustellen, dass unser Forum permanent online und schnell erreichbar ist, unsere Forensoftware auf dem aktuellsten Stand ist und der Server regelmäßig gewartet wird. Auch die Themen Datensicherheit und Datenschutz sind uns wichtig und hier sind wir auch ständig aktiv. Alles in allem, sorgen wir uns darum, dass alles Drumherum stimmt :-)

    Dir gefällt das Forum und unsere Arbeit und du möchtest uns unterstützen? Unterstütze uns durch deine Premium-Mitgliedschaft!
    Wir freuen uns auch über eine Spende für unsere Kaffeekasse :-)
    Vielen Dank! :ciao:


     Spende uns! (Paypal)