Hallo allerseits,
ich suche eine Möglichkeit Hardwareinterrupts im Assembler zu
entprellen.
Die Aufgabe ist:
Ein Lauflicht soll durchlaufen. Wenn ein Taster gedrückt wird wird der
Hardwareinterrupt Int0 ausgelöst, nun soll auf der 7-Segmentanzeige
inkrementiert werden.
Das Problem:
Wenn der Taster gedrückt wird zählt die 7-Segmentanzeige manchmal um
mehr als einen Schritt rauf.
Ich habe schon versucht, dies mit einer Delayschlaufe, Mehrfachabfrage,
... zu lösen aber bin bis jezt noch auf kein Ergebnis gekommen.
Ich wäre froh wenn mir jemand helfen kann.
Freundliche Grüsse Leon
Leon schrieb:> Die Aufgabe ist:> Wenn ein Taster gedrückt wird wird der> Hardwareinterrupt Int0 ausgelöst
Ist das eine Schulaufgabe? Und der Taster am Hardwareinterrupt gehört
dazu?
Dann hat Dein Lehrer keinerlei praktische Erfahrung mit µC. Du hast
mittlerweile mehr Erfahrung. Denn diese hast Du zumindest schon gemacht.
Wenn Dein Lehrer sagt, daß das mit sw gelöst werden soll, dann hat er
auch keine theoretische Erfahrung - Warterei in einem Interrupt ist zwar
nicht unmöglich, aber ungeschickt. (Würde dann so aussehen, daß zu
Beginn des IRQs 10ms gewartet wird und wenn das Portbit dann immer noch
einen gedrückten Taster anzeigt Euer Zähler Inkrementiert wird, wenn er
dann nicht gedrückt ist, wird der IRQ einfach wieder verlassen.)
1. Möglichkeit: Den Taster per Hardware entprellen. (Ihr könnt dann auch
einen Hardwarezähler benutzen und Euch den µC sparen.)
2. Möglichkeit: Wie schon beschrieben, den Timerinterrupt benutzen.
EDIT:
Leon schrieb:> Delayschlaufe
Wie lange hast Du gewartet?
Schlaufe finde ich schön :-)
Gruß
Jobst
Hi
Egal ob Schulaufgabe oder Hobby... einen Taster mit einem Interrupt zu
erfassen ist unklug und überhaupt nicht erforderlich. Wie schnell kannst
du einen Taster drücken und loslassen ? 100m Sek oder gar 10 mSek.?
Beides Zeiten, in dem ein Controllersich auch bei umfangreichen
Programmen mehrfach überschlagen hat. Völlig ausreichend, Taster im
Polling zu erfassen. Erst, wenn du ganz kurze Signale erfassen willst,
dann ist ein Interrupt angesagt. Angenommen, du nimmt ein Rad und machst
an eine Speiche einen Magneten. Diesen erfaßt du mit einem Reedkontakt
und willst die Umdrehung zählen. Auch wenn dein Rad relativ langsam
dreht, ist der Reedkontakt nur vielleicht 1/2 Grad geschaltet, das heißt
bei einer Umdrehung nur ein 720stel. Also, 1 Umd/Sek bedeutet ein
auswertbares Signal von 1/720 Sek, also rd. 1,3 mSek. Nur wenn dein
Programmzyklus kürzer als 1,3 mSek ist, wird der Impuls erfasst. Da aber
auch höhere Umdrehungen einbezogen werden müssen, kannst du nicht mehr
davon ausgehen, das der Impuls vom Reedkontakt erkannt wird und dann
macht ein Interrupt Sinn.
Grup oldmax
oldmax schrieb:> Egal ob Schulaufgabe oder Hobby... einen Taster mit einem Interrupt zu> erfassen ist unklug und überhaupt nicht erforderlich.
Nein. Egal ist es nicht. Wenn er es für sein Hobby macht, kann er die
Anforderung ändern. Wenn es eine Schulaufgabe ist, wonach es sich für
mich anhört, müsste er diese Anforderung erfüllen - so dämlich sie ist.
Gruß
Jobst
oldmax schrieb:> ... Wie schnell kannst> du einen Taster drücken und loslassen ? 100m Sek oder gar 10 mSek.?> ...> Grup oldmax
Frag mal nen Hardcore Gamer, die merken sogar Verzögerungen von 10 us.
[iRonie]
Nein, es ist keine Schulaufgabe. Ich muss dies im Geschäft machen.
Dass warten in einer Interruptroutine nicht schöhn ist weiss ich. Ich
wollte nur ausprobieren ob es so funktionieren würde. (Ich habe ungefähr
10mal so lange gewartet, wie der Taster Prellt.)
Zur Idee mit einer Hardwareentprellung und Zähler... <- Es geht ja um
Interrupts und das Entprellen! Ich muss programmieren lernen, Hardware
war leztes Jahr dran.
Die Idee mit dem Timerinterrupt finde ich gut, werde diese Variante mal
ausprobieren.
Hi
Zum einen ist es das Prellen, möglicherweise aber auch die direkte
Abfrage des Tastersignales.
EVA sagt dazu "Einlesen" "Verarbeiten" und "Ausgeben"
Das ist im Prinzip deine Programmschleife. Wenn du nun deine Taster
betätigst, dann erkennt der µC bei jedem Durchlauf "Aha, ein ganz
schlauer.... " und zählt fröhlich hoch. Also brauchst du die Flanke des
Signales "Taster gedrückt" und das erhälst du mit einer EOR-Verknüpfung
des alten Zustandes.
Angenommen, dein Taster war nicht gedrückt und der alte Zustand ist "0".
Nun drückst du drauf und bekommst eine "1".
Exclusiv-Oder = 0 und 1 = 1. Das ist deine Flanke. Anschließend setzt du
Alt = neu, also Alt auf "1"
Du kannst nun den taster halten, bis du alt und grau wirst, es gibt
keine neue "1" da Exclusiv Oder "1" und "1" = 0 ist
Diese "1" aus dem vorherigen Ergebnis benutzt du, um das Kriteriun für
den Zählimpuls zu haben. Dann setzt du diese "1" zurück. Eine neue "1"
gibt es erst, wenn du die taste losläßt und erneut drückst.
Hier mal die Wahrheitstabelle einer Exclusiv-Oder Verknüpfung:
E 1 E 2 A
0 0 0
1 0 1
0 1 1
1 1 0
Daran erkennst du, das das Ergebnis "A" nur "1" ist, wenn "E 1" und "E
2" unterschiedlich sind.
Gruß oldmax
Leon schrieb:> Nein, es ist keine Schulaufgabe. Ich muss dies im Geschäft machen.> Dass warten in einer Interruptroutine nicht schöhn ist weiss ich. Ich> wollte nur ausprobieren ob es so funktionieren würde. (Ich habe ungefähr> 10mal so lange gewartet, wie der Taster Prellt.)
In einem Interrupt warten macht man nicht. Du könntest in der ISR
checken, wie lange der letzte Interrupt vergangen ist und dann den
aktuellen Interrupt einfach ignorieren, wenn er innerhalb x msec
eingetroffen ist.
Zur Realisierung bräuchtest Du dann noch zusätzlich(!) einen
Timerinterrupt, damit Du die vergangene Zeit mitzählen kannst. Und wenn
Du dann schon einen Timerinterrupt hast, kannst Du die INT0-ISR kicken
und direkt auf Polling übergehen...
Ich hoffe, ich habe Dich im letzten Abschnitt von der Sinnlosigkeit
eines INT0-Interrupts für eine Tastenabfrage überzeugt ;-)
@oldmax
Mit einer XOR-Verknüpfung erkennt er zwar die Flanke und kann diese
Auswerten. Beim Prellen des Tasters kommt es aber zu mehreren Flanken
(an-aus-an-aus-an-aus, deshalb ja prellen), welche dann auch einzelln
gezählt werden.
Um eine Verzögerung nach einer Flanke kommt man nicht herum. Diese durch
einen Timer zu erledigen ist natürlich besser als eine Delayschleife zu
benutzen. Wenn der Taster über Interupts ausgelesen wird, ist es am
einfachsten diese an und ab zu schalten.
-> Flanke erkannt dann Timer starten und Interupt aus
-> Timer abgelaufen Interupt wieder an
Dazu kommt, dass in einem realen Programm sowieso in >95% aller Fälle
ein Timer in der einen oder anderen Form involviert ist. D.h. du hast
die Maschinerie im Grunde schon im Gang.
Da du Lauflicht erwähnt hast: Auch so etwas macht man sinnvollerweise
mit einem Timer! Da du keinen Timer erwähnt hast, geh ich davon aus,
dass du das Lauflicht mit _delay_ms gemacht hast, was dann wiederrum
dazu geführt hat, dass du meinst, du müsstest einen Taster an einen
externen Interrupt hängen. So führt dann ein Fehldesign zum nächsten.
Timer sind deine Arbeitspferde! Immer dann wenn es um Zeiten oder
zeitliche Koordinierungen geht, ist ein Timer involviert.
Preller schrieb:> -> Flanke erkannt dann Timer starten und Interupt aus> -> Timer abgelaufen Interupt wieder an
Da kannst du es aber auch gleich bleiben lassen und im Timerinterrupt
pollen. Ist in Summe um einiges einfacher als dieser 'Zusammenhang'.
Hi
>Mit einer XOR-Verknüpfung erkennt er zwar die Flanke und kann diese>Auswerten. Beim Prellen des Tasters kommt es aber zu mehreren Flanken>(an-aus-an-aus-an-aus, deshalb ja prellen), welche dann auch einzelln>gezählt werden.
Natürlich geh ich davon aus, das das viel beschriebene Prellen erledigt
wird, bevor man sich an die Flankenauswertung setzt.
Deshalb hab ich es j auch erwähnt, das nicht nur das Prellen für ein
unkontrolliertes Zählen verantwortlich ist.
Gruß oldmax
Stefan schrieb:> Schalte mal einfach einen 100nF Kondensator parallel zum Taster, dann> kannst Du Dir den Programmieraufwand sparen.
Für manche Leute ist das zwar verpöhnt, hat aber zusätzlich den Vorteil,
das der Taster mit einigem Strom geschaltet wird. Ich erinnere mal an
diesen Thread:
Beitrag "Mindeststrom bei Taster/Schalter für sicheren Betrieb?"
Allerdings muss der Kondensator ja über den Pullup des AVR wieder
geladen werden, deswegen erscheint mir 100n ein wenig hoch. 4n7 - 22n
sind da auch o.k.
Noch ein Vorteil ist, das etwaige Störungen von der LED Schalterei nicht
auf den INT zurückwirken.
Für manche Leute ist es vor allen Dinge verpöhnt, einen 5 Monate alten
Thread aus der Versenkung zu holen. Noch dazu zu einem Thema, welches
jede Woche mindestens 8 mal auf der Agenda steht.