Zählen der Eingangsimpulse und damit Ausgänge ansteuern

burmeiha

Neues Mitglied
03. März 2008
7
0
0
Sprachen
Guten morgen zusammen,
ich habe ein Problem, dass ich durch googlen und mit der Bascom-Hilfe nicht lösen konnte. :confused:
Eigentlich ist es ganz simpel:
Ich möchte durch einen Taster verschiedene Ansgänge anwählen können.
1. positive Flanke am Taster = Kanal 1 setzen
2. positive Flanke am Taster = Kanal 2 setzen
usw.
Hierfür brauche ich also einen Zähler, der die Eingangsimpulse des Tasters speichert, die ich dann wieder aufrufen kann.
Kann mir da vielleicht jemand einen Tipp geben?
Das wäre super
Ach ja, ich benutze Bascom und programmiere den Mega32.
Vielen Dank schonmal für die Mühe
mfg:)
Hans
 
Hi,

ich würde das so realisieren, das ich den Taster an einen Interrupt-Eingang hänge. Der INT wird so konfiguriert, dass er bei einer steigenden Flanke die ISR aufruft.
Auf diese Weise ersparst Du Dir aufwändiges polling.

Grüße,
Markus
 
Hallo Hans,

wenn du bei jedem Tastensignal einen anderen Port-Ausgang schalten möchtest, kannst du das entweder
  • durch if-Abfrage des letzten Portzustands machen, daraufhin dann den neuen Zustand schalten oder
  • eine Tabelle erzeugen, wo du dir in Abhängigkeit vom letzten Portzustand einen neuen Port-Wert holst und diesen am Port ausgibst oder
  • wenn du nur jeweils einen Portpin nacheinander aktivieren möchtest, alle Portpins die du schalten möchtest sich an einem Port befinden, dann könntest Du das Port-Register einlesen, um 1Bit schieben und dann wieder ausgeben (such mal in der Bascom-Suche nach "shift", da müsste eigentlich etwas zu finden sein)
... das könntest du in der Interruptroutine des ExtInt machen.

Grüße,
Dirk
 
Danke schonmal für eure Unterstützung.
Ich werde versuchen eure Vorschläge umzusetzen und melde mich dann wieder.
bis dann
Hans
 
Hallo,
ich komme trotz eurer bestimmt guten Vorschläge nicht weiter. Mit der einfachen if-Funktion nimmt Bascom die Befehle nicht an, da ich nicht nur einen Ausgang bei einem Zählzustand schalten möchte, sondern mehrere.
Zu den Tabellen gibt es zwar viele Beschreibungen im Forum, doch ich kann mit den Befehlen und der Fachsprache einfach nichts anfangen.:confused:
Gibt es bei Bascom nicht etwas, wie einen Flip-Flop? Quasi eine Funktion, die ich setzen, später einmal oder häufiger aufrufen und dann zurücksetzen kann. Ich weiß, das ist hier sicherlich nicht der richtige Ausdruck:( , aber ich habe mich noch nicht wirklich tief in der Materie reingearbeitet und habe vorher nur SPS-Steuerungen erstellt. Ich denke mit dieser Funktion wäre die Aufgebe zu lösen.
Nochmal danke für die Antworten
Gruß
Hans
 
Hallo Hans,

kannst du uns dein Programm als Dateianhang an einen Beitrag anhängen oder genau erklären, wann du welche Portpins ein- bzw. ausschalten möchtest, gibt es hier eine bestimmte Abfolge (eine Tabelle wäre interessant).


Gruß,
Dirk
 
Hi Hans,

bin mir nicht sicher was Du mit einer Flip-Flop-Funktion meinst und was Du damit tun möchtest. OK, hab grad auch nicht die Zeit alles genau durchzulesen aber vielleicht aknn ich Dir noch das ein oder andere sagen.

Schau Dir hierzu mal die folgenden Themen in BASCOM an:

With TOGGLE you can simply invert the output state of a port pin.

When the pin is driving a relays for example and the relays is OFF, one TOGGLE statement will turn the relays ON. Another TOGGLE will turn the relays OFF again.


SET
Action: Set a bit to the value one.
Syntax
SET bit
SET var.x
Remarks
Var = A byte, integer, word or long variable.
X = Bit of variable (0-7) to set. (0-15 for Integer/Word) and (0-31) for Long

RESET
Action: Reset a bit to zero.

Syntax
RESET bit
RESET var.x
Remarks
bit = Can be a SFR such as PORTB.x, or any bit variable where x=0-7.
var = Can be a byte, integer word or long variable.
x = Constant of variable to reset.(0-7) for bytes and (0-15) for Integer/Word. For longs(0-31)

You can also use the constants from the definition file to set or reset a bit.
RESET PORTB.PB7 'will reset bin 7 of portB. This because PB7 is a constant in the def file.

Grüße,
Markus
 
Guten Morgen,
also erkläre ich mal das ganze Projekt.
Ich habe eine Umschaltbox mit einem RS232-Eingang und 16 RS232-Ausgängen. Auf Tastendruck soll nun ein BCD-Code ausgegeben werden, der dann die Ausgänge nacheinander mit dem Eingang durchschaltet.
Außerdem soll der gewählte Kanal (1-16) über zwei 7-Segment-Anzeige angezeigt werden (wobei ich bei der 10er nur B und C für die 1 angeschlossen habe, da ich ja nur bis 16 zählen möchte)
Hier die Tabelle:

Zähler der----------BCD-Code-------Ansteuerung der 7-Segm. Anzeigen
Tastimpulse-------------------------Anzeige 10er-----Anzeige 1er
-------------------A0 A1 A2 A3-----B10 C10---------A B C D E F G
1(Kanal 1)----------0--0--0--0------0----0-----------0 1 1 0 0 0 0
2(Kanal 2)----------1--0--0--0------0----0-----------1 0 1 1 0 1 1
3(Kanal 3)----------0--1--0--0------0----0-----------1 1 1 1 0 0 1
....
16(Kanal 16)--------1--1--1--1------1----1-----------1 0 1 1 1 1 1

Tast alias Portb.0
A0 alias Portb.1
A1 alias Portb.2
A2 alias Portb.3
A3 alias Portb.4
A alias Portd.7
B alias Portc.0
C alias Portc.1
.....
C10 alias Portc.7

Ich hoffe ihr versteht mein Problem.
Es ist im einfachsten Fall eine Ablaufsteuerung.
Danke
viele Grüße
Hans
 
RS232 Umschalter

Hallo Hans,

ich hätte für dein Problem eine Lösung, zwar nicht die schönste, dafür aber eine sehr einfach.

Ich würde mit dem „Tast“ einfach eine Variable hoch zählen und bei > 16 auf 0 zurück setzen. Das ganze würde ich Verbindung mit einer Select Case schleife machen. In der Select Case schleife stellst du dann deine Ports so wie du sie haben möchtest.

Habe mal das Programm angefügt:

$regfile = "m2561def.dat" ' Must du auf deinen Atmel einstellen
$crystal = 14745600 ' Must du auf deinen Atmel einstellen

Config Pinb.0 = Input ' Pin als Eingang setzen
Config Pinb.1 = Output ' Pin als Ausgang setzen
Config Pinb.2 = Output ' Pin als Ausgang setzen
Config Pinb.3 = Output ' Pin als Ausgang setzen
Config Pinb.4 = Output ' Pin als Ausgang setzen
Config Pind.7 = Output ' Pin als Ausgang setzen
Config Pinc.0 = Output ' Pin als Ausgang setzen
Config Pinc.1 = Output ' Pin als Ausgang setzen
Config Pinc.2 = Output ' Pin als Ausgang setzen
Config Pinc.3 = Output ' Pin als Ausgang setzen
Config Pinc.4 = Output ' Pin als Ausgang setzen
Config Pinc.5 = Output ' Pin als Ausgang setzen
Config Pinc.6 = Output ' Pin als Ausgang setzen
Config Pinc.7 = Output ' Pin als Ausgang setzen

Dim B_kanal As Byte

Tast Alias Portb.0
A0 alias Portb.1
A1 alias Portb.2
A2 alias Portb.3
A3 alias Portb.4
A alias Portd.7
B alias Portc.0
C alias Portc.1
D Alias Portc.2
E Alias Portc.3
F Alias Portc.4
G Alias Portc.5
B10 Alias Portc.6
C10 alias Portc.7

B_kanal = 0 ' Zählwert für Kanal wird auf 0 gesetzt

Config Debounce = 30 ' Gibt die Zeit in ms an um die die Taste entprellt wird, man sollte so 20-40 ms nehmen

Do

Debounce Tast , 1 , Zaehlen , Sub ' Abfrage der Taste, 1 für High, 0 für Low wenn gedrückt

Loop


Zaehlen:

B_kanal = B_kanal + 1 ' Zählwert für Kanal wird um eins erhöht

Select Case B_kanal

Case 1
A0 = 0
A1 = 0
A2 = 0
A3 = 0
A = 0
B = 1
C = 1
D = 0
E = 0
F = 0
G = 0
B10 = 0
C10 = 0

Case 2
A0 = 1
A1 = 0
A2 = 0
A3 = 0
A = 1
B = 0
C = 1
D = 1
E = 0
F = 1
G = 1
B10 = 0
C10 = 0

Case 3
A0 = 0
A1 = 1
A2 = 0
A3 = 0
A = 1
B = 1
C = 1
D = 1
E = 0
F = 0
G = 1
B10 = 0
C10 = 0

' Case 4 bis Case 16 kannst Du ja selber einfügen, habe ehrlich gesagt keine große Lust dazu

End Select

If B_kanal = 16 Then
B_kanal = 0 ' Zählwert für Kanal wird auf 0 gesetzt
End If
Return


End


Ich hoffe dir damit geholfen zu haben.

mfg Jörg
 
Aaaaaaaaaaah, hilfä, leute, was macht Ihr da :eek:
Das ist ja Spaghetti-Code in Reinform :)

Also, wenns denn dann so funktioniert könnt Ihrs wegen mir so lassen aber ich kommt nicht drum herum meinen Senf hierzu abzugeben denn das was ich gerade gesehen habe tuzt mir echt weh. Doch schauen wir uns zunächst die Einzelthemen im einzelnen an.

Konfiguration von PIN's:
Unter Bascom ist es möglich mittels einfachem Befehl
Code:
Config Portc = Output
einen gesamten Port als Ausgang zu setzen. Ihr könnt Euch auf diesem Weg 7 Zeilen Code sparen.
Die Megas haben zur Konfiguation ob Eingang oder Ausgang ein Data-Direction-Register das man in BASCOM auch direkt ansprechen kann. Schauen wir uns das an Eurem beispiel bei Port B mit gemischten I/O's mal an.
Hier gibt es prinzipiell zwei Mögichkeiten. Entweder Ihr beschreibt das Register direkt (1) oder Ihr holt Euch vorher den Inhalt und modifiziert die Stellen welche Ihr braucht (2).
Bit = 0 im DDR sagt Eingang, Bit = 1 im DDR sagt Ausgang. In Eurem Beispiel soll Bit 0 Eingang sein und Bit 1- 4 Ausgang. Das sieht binär so aus &Bxxx11110.
Zu (1):
Code:
DDRB = &B00011110
konfiguriert den Port wie gewünscht wobei mit dieser Methode die Bits 5-7 auch noch überschrieben werden. Mit dieser Methode spart Ihr 4 Zeilen Code!
Zu(2):
DIM helpbyte AS Byte
helpbyte = DDRB AND &B11100000 ' verwendete Bits erst mal ausmaskieren
DDRB = helpbyte OR &B11110 ' Konfiguration schreiben
Die Lösung ist eleganter und schneller!

Der Zähler:
Die Möglichkeit die die Steuerung über einen Zähler mit debounce Abfrage zu machen ist möglich und nicht schlecht.
Sollten jedoch im Programm noch weitere Aufgaben dazu kommen so könnte man sich auch überlegen die Abfrage des externen Tasters über Interrupt zu machen. Das ist aber wirklich reine Geschmackssache.

Ansteuerung:
Ich würde nie und nimmer bei solch einer schönen Problemstellung die Ausgabe auf die Ports in sequentieller Spaghetti-Form machen.
Mit einem BASCOM Befehl wie z.B.
Code:
PortC = &B01010101
kann mit einem Befehl ein komplettes Bitmuster auf den Port geschrieben werden. Damit spart Ihr Euch wieder 7 Zeilen Code.

Weiter würde ich nicht die einzelnen Bits im Case oder im Code jeweils einzeln setzen sondern ich würde mir eine Tabelle zur Ansteuerung der 7-Segment-Anzeige erstellen, zur Laufzeit über den Zähler gesteuert in die Tabelle greifen, mir den entsprechenden Wert rausholen und auf die Ports schreiben. Dabei reicht ein Byte-Wert nicht sondern ich würde ein Word verwenden. Das Word könnt ihr genauso mit Bits befüllen wie alle anderen Variablen.
Beispiel:
Code:
Dim word_var As Word
word_var = &B0101010101010101 ' Achtung: word hat 16 Bit!

Ähnliche wie bei der Initialisierung kann man ganze Bytes auf Ports schreiben oder aber mit Operationen wie OR, AND, SHIFT Bitmanipulationen durchführen.
Ich würde nie und nimmer für 16 verschiedene Zählerstände 16 Ausgaben implementieren. Es reicht wie gesagt eine Ausgaberoutine zu programmieren die dann mit Daten aus der Tabelle befüttert wird.
Wie man mit Tabellen arbeitet könnt Ihr Euch unetr dem Thread
http://www.avr-praxis.de/forum/showthread.php?t=62
mal ansehen.

Dann noch ein Wort zur BCD-Problemstellung. Die BCD-Codierung ergibt sich 1:1 aus dem Wert des Zähler, da dieser nur Werte zwischen 0 und 15 (16) Zahlen annehmen kan (&B0000 bis &B1111, Achtung &B1111 ist 15!!!)
In Euerem Programmbeispiel ist ein Denkfehler. Ihr startet mit B_kanal = 0, soweit OK! Aber die Abfrage auf 16 muss unmittelbar danach erfolgen da 16 bereits schon ein Überlauf des Wertebereich zur folge hat. Also bitte:
Code:
B_kanal = B_kanal + 1 ' Zählwert für Kanal wird um eins erhöht
If B_kanal = 16 Then B_kanal = 0 ' Zählwert für Kanal wird auf 0 gesetzt
Wenn Ihr das IF-Statement in einer Zeile schreibt dann kann man End If verzichten.
So, nun ist sichergestellt, das die Variable, bevor Ihr in den Case reinlauft wirklich nur 0-15 (16 Zustände) hat, sonst hättet Ihr nämlich einen 17 und damit undefinierten Zustand.

Noch ein paar Sätze zur Ausgabe:
Ihr wollt die Daten auf PortB.1 bis PortB.4 ausgeben. OK, was haltet Ihr von der folgenden Lösung (der Zähler ist Basis!):

Code:
Dim Helpbyte1 As Byte
Dim Helpbyte2 As Byte

Helpbyte1 = PortB AND &B11100001  ' Inhalt PortB auslesen und maskieren
Helpbyte2 = B_kanal                      ' Zähler in Arbeitsvariable
Shift Helpbyte2, Left, 1                  ' Zähler auf richtige Bitposition
Helpbyte1 = Helpbyte1 + Helpbyte2  ' Zähler auf Port-Variable addieren
PortB = Helpbyte1                         ' Port mit neuem Inhalt setzen.

Mit dieser Methode spart Ihr Euch 16x die Ausgabe einzelner Bits auf den Ports und das Programm wird überschaubar, strukturierter und übersichlicher.


Fazit:
Schaut Euch einfach mal die von mir dargestellten Themen an und probiert sie aus. Mittels der von mir vorgestellten Methoden könnt Ihr komplett auf einen aufwändigen Case-Verteiler verzichten und alles schon "runterprogrammieren"

Soll keine Kritik sondern nur eine Hilfestellung sein denn der Spass entsteht durch neue Herausforderungen und man wächst schließlich mit seinen Aufgaben.

Vielleicht könnt Ihr das ein oder andere verwenden oder wollt es einfach mal ausprobieren. Wenn ja freut es mich ansonsten könnt ihr auch bei der italienischen Variante bleiben. :D

Grüße,
Markus
 

Ü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)