Hallo zusammen, gibt es irgendwo ein Programm von Peter Dannegger das die Tasten entprellt aber in ASM ? Wenn möglich für MPLAB. Grüße caine
Ob gerade in Assembler weiss ich nicht. Aber such mal hier im Forum. Der C Code an den ich mich erinnere ist für AVR. Sollte sich aber leicht in jede andere Sprache umsetzen lassen. (Ist halt nichts für die CopyNPaste-Progammierer).
Hast du in der Artikelsammlung schon nach "Entprellen" gesucht? http://www.mikrocontroller.net/articles/Hauptseite
NONAME, den in C für AVR habe ich ja gefunden in der Codesammulung, da ich aber totaler Anfänger bin aber Assembler lerne, ist es für mich schon problematisch den C Code und dann auch noch für AVR zu verstehen. Da ich den 16f877 von Microchip benutze. Keine Chance den selber umzuändern. Gruß caine
1) pin abchecken jede ms 2) wenn pin aktiv zähler runterzählen, wenn nicht zähler gleich 10 3) wenn zähler gleich 0 4) ereignis auslösen pin checken mit btfss oder btfsc goto _LABEL_X hochzählen mit incf gleich 0 abchecken mit zerobit (z Bit im Statusregister, ich meine das ist STATUS,Z) also btfss STATUS,Z Das bis ist gesetzt wenn im w Register eine 0 steht. Gruß, TS
nedim muratovic schrieb: > Da ich den 16f877 von Microchip benutze. > Keine Chance den selber umzuändern. Dann nimm dir nicht zu viel auf einmal vor. Bring erstmal eine LED auf deinem µC zum Blinken - Version 1: mit Delay Version 2: mit Timer IRQ Aber selbst geschrieben und nicht blind kopiert, gell ;-)
Die Tastenentprellung von PeDa ist ein paralleler 2-Bit-Zähler, der gleichzeitg auf einem ganzen Byte zählt. Eigentlich eine ganz einfache Sache, aber recht trickreich. Und natürlich kann das auch in Assembler realisiert werden. Man muss nur vorher verstanden haben, was da passiert...
Lothar Miller schrieb: > Die Tastenentprellung von PeDa ist ein paralleler 2-Bit-Zähler, der > gleichzeitg auf einem ganzen Byte zählt. Eigentlich eine ganz einfache > Sache, aber recht trickreich. Und natürlich kann das auch in Assembler > realisiert werden. Man muss nur vorher verstanden haben, was da > passiert... "Mann muss nur vorher verstanden haben, was da passiert..." Lothar, das "nur" in dem Satz hättest du aber auch weg lassen können :-)
my2ct schrieb: > Dann nimm dir nicht zu viel auf einmal vor. Bring erstmal eine LED auf > deinem µC zum Blinken - > Version 1: mit Delay > Version 2: mit Timer IRQ > > Aber selbst geschrieben und nicht blind kopiert, gell ;-) > my2ct das habe ich, sogar 4 Programme. 1. led leuchtet. 2.Led leuchtet wenn Taster betätigt. 3. Led geht aus oder wenn aus dann ein bei Taster betätigung. 4. Programm Nr3 aber das ganze über eine Interrupt Routine um mich bischen mit dem INCON Register vertraut zu machen. Und jetzt möchte ich mich mit der Taster entprellung vertraut machen. Grüß caine
...und wie hast du das realisiert, wo ist denn das Problem? Man prüft den Pin, wenn keine Bewegung mehr ist, dann wird das Ereignis gültig. Das läuft im 1ms 10ms Bereich ab, wie ich oben beschrieben habe...hat man schnell gemacht.... Gruß, TS
1 | .DEF KEYstA = r1 ; |
2 | .DEF KEYctA1 = r2 ; |
3 | .DEF KEYctA2 = r3 ; |
4 | |
5 | ;init Register |
6 | |
7 | clr KEYstA ;Tasten Status Null |
8 | clr KEYctA1 |
9 | com KEYctA1 ;Tasten Counter 0xFF |
10 | clr KEYctA2 |
11 | com KEYctA2 |
12 | |
13 | ;in der durchlaufenden Mainloop mit 32ms oder im Timer Interrupt |
14 | |
15 | in TEMP1, PINswA ;Tasten einlesen, low-aktiv |
16 | |
17 | ;**** Software-Entprellung 4 Zyklen **** |
18 | |
19 | com TEMP1 ;Tasten invertieren |
20 | eor TEMP1, KEYstA ;veränderte Tasten high |
21 | and KEYctA1, TEMP1 ;unveränderte Prellzähler Bit0 löschen |
22 | and KEYctA2, TEMP1 ;unveränderte Prellzähler Bit1 löschen |
23 | com KEYctA1 ;Prellzähler Bit0 inc |
24 | eor KEYctA2, KEYctA1 ;Prellzähler Bit1 inc |
25 | and TEMP1, KEYctA1 ;veränderte Tasten nur erhalten, wenn in Prellzähler |
26 | and TEMP1, KEYctA2 ;beide Bits gesetzt |
27 | eor KEYstA, TEMP1 ;veränderte Tasten toggeln, neuer gültiger Status |
28 | and TEMP1, KEYstA ;nur gedrückte Tasten berücksichtigen |
29 | or KEYchA, TEMP1 ;neue Tasten merken |
Jetzt nur mal damit ich das verstehe. Bei mir ist das so , dass der Taster einen Interrupt auslöst der eine LED anmacht wenn aber schon ein , dann eben aus. Wenn also Taster betätigt wird und der prellt und den Interrupt auslöst,(mehrere male anstatt einmal) nutzt es doch nix den Taster in den ISR zu entprellen , da die Prellung mehrere Interrupts auslöst die dann von dem Stack abgearbeitet werden. Oder rede ich wieder Mist.??
Also ich habe schon oft gelesen, dass man Taster generell eigentlich nicht über Interrupts auswertet. Sondern diese werden wohl tatsächlich eher "gepollt" und dann je nach dem aktuellen Status des Tasters ihn dann noch ein paar mal mehr abfrägt, wie weiter oben ja auch schon mal beschrieben wurde, indem ein Zähler (beispielsweise mit 10 initialisiert) jede 1 ms dekrementiert wird. Wenn der Tasterstatus sich innerhalb dieser 10 ms nicht verändert hat und konstant (high oder low, je nach Ansteuerung) geblieben ist, kann man davon ausgehen, dass der Taster gedrückt wurde und somit entprellt ist.
Wäre es dann nicht eleganter die Taster Prellung mittels RC Glied zu lösen und Trotzdem die Taster über Interrupts zu machen? Kann mir nicht vorstellen das die Taster ständig abgefragt werden müssen, was bei polling der Fall ist. Der ideale weg wäre doch die Prellng softwaremäsig zu lösen und die Taster über ISR. Wenn das überhaupt geht.
nedim muratovic schrieb: > Wäre es dann nicht eleganter die Taster Prellung mittels RC Glied zu > lösen Wie sieht diese Entprellung mittels RC Glied aus? Gruß
Such mal ein bisschen. In den Threads zu dem Thema gibt es auch ein Dokument von Peter Dannegger resp. Atmel wie das funktioniert. Wenn Du das verstanden hast, dann kannst Du es auch in Assembler schreiben. Ich weiss das ist jetzt bösartig von mir. Aber ich habe keine Lust für Dich zu suchen. Jedenfalls solltest Du Dir die Tastenerkennung im Interrupt gleich mal abschminken. Und das RC-Geraffel brauchst Du nicht.
nedim muratovic schrieb: > Der ideale weg wäre doch die Prellng softwaremäsig zu lösen und die > Taster über ISR. > Wenn das überhaupt geht. Du meinst wohl hardwaremäßig? Da kenn ich mich nicht wirklich so gut aus. Habe glaub ich mal gelesen, dass man die so nicht gnaz entprellen kann. Der Mikrocontroller ist doch im Allgemeinen sowieso nicht wirklich ausgelastet. Von daher steht einem ständigem Abfragen doch nichts im Weg. Man müsste halt vermutlich nur darauf achten, dass dies zuverlässig zyklisch geschieht. Viele nutzen ja auch Timer um einen zyklischen Interrupt auszulösen um so eine zuverlässige Zeitbasis für ihr Programm zu schaffen. In der ISR werden dann Flags gesetzt etc., welche innerhalb der Superloop ausgewertet werden und so kann man dann auch bspw. seine Taster entprellen.
Noname schrieb: > Jedenfalls solltest Du Dir die Tastenerkennung im Interrupt gleich mal > abschminken. Warum genau?
PIC schrieb im Beitrag #2747324: > Der Mikrocontroller ist doch im Allgemeinen sowieso nicht wirklich > ausgelastet. Von daher steht einem ständigem Abfragen doch nichts im > Weg. Genau so isses! Fast jede Anwendung braucht einen Timer als Zeitbasis. Und da noch etwa 10 Instruktionen mit reinzupacken, da lacht die CPU nur drüber. Auch habe nur wenige MCs 8 Interrupteingänge. Peter
PIC schrieb im Beitrag #2747245: > Sondern diese werden wohl tatsächlich eher "gepollt" Richtig, dabei hat sich ein Intervall von 10 bis 30 ms als optimal erwiesen. Dies sollte allerdings nicht durch eine Warteschleife, sondern durch einen Timer realisiert werden. Dieser kann aber nebenher noch andere Dinge tun, geht dem System also nicht verloren. > und dann je nach > dem aktuellen Status des Tasters ihn dann noch ein paar mal mehr > abfrägt, wie weiter oben ja auch schon mal beschrieben wurde, indem ein > Zähler (beispielsweise mit 10 initialisiert) jede 1 ms dekrementiert > wird. Zu umständlich und zu ressourcenfressend. Es braucht außer einem Temp-Register weitere 4 Register für folgende Zwecke (Registernamen gemäß Routine von Timm, ich benutze andere Namen, PeDa wieder andere): KEYstA ;letzter gültiger Status der 8 Tasten KEYchA ;Flags der 8 Tasten mit der Info, dass sie neu betätigt wurden KEYctA1 ;Bit 0 der 2-Bit-Zähler der 8 Tasten KEYctA2 ;Bit 1 der 2-Bit-Zähler der 8 Tasten Ich kommentiere jetzt mal mal die Routine von Timm, wobei mir Timms Kommentare verdammt bekannt vorkommen (von PeDa sind sie nicht...): Timm Thaler schrieb: > in TEMP1, PINswA ;Tasten einlesen, low-aktiv Hier erfolgt das Einlesen des neuen Zustandes der 8 Tasten in ein temporäres Register. > com TEMP1 ;Tasten invertieren Die folgende Logik erwartet H-aktive Eingangssignale von 8 Tastern. Die Taster sind aber gegen GND geschaltet, um die internen Ziehwiderstände (PullUp) nutzen zu können. Daher muss das Eingangssignal invertiert werden. > eor TEMP1, KEYstA ;veränderte Tasten high Durch EXOR mit dem zuletzt gültigen Zustand werden nur die Tastenbits 1, die anders sind als der letzte gültige Zustand. Denn Gleichheit ergibt 0, Ungleichheit ergibt 1. Es werden 8 Tasten gleichzeitig verglichen. In TEMP1 stehen jetzt die Bits auf 1, deren Taster einen anderen Zustand haben als der zuletzt als gültig erklärte Status in KEYstA. > and KEYctA1, TEMP1 ;unveränderte Prellzähler Bit0 löschen > and KEYctA2, TEMP1 ;unveränderte Prellzähler Bit1 löschen In diesen beiden Zeilen werden beide Prellzählerbits der Tasten gelöscht, deren Bits in TEMP1 0 sind, also die denselben Zustand wie der zuletzt gültige Status haben. Die Prellzähler der Tasten, die anders sind, bleiben erhalten. Die beiden Register enthalten 8 separate Zähler, von denen jeweils das Bit0 in dem einen Register liegt, das Bit 1 im anderen. > com KEYctA1 ;Prellzähler Bit0 inc > eor KEYctA2, KEYctA1;Prellzähler Bit1 inc COM invertiert das Bit 0 aller Zähler, unabhängig vom Zustand der Tasten. EOR übernimmt den Übertrag aus Bit 0 der 8 Zähler in Bit 1. Dabei werden alle 8 Zähler erhöht, unabhängig davon, ob eine Taste anders als vorher ist. Die Zähler unveränderter Tasten erreichen aber ihren Endwert (3, also beide Bits gesetzt) nicht, da sie zuvor immer wieder per AND gelöscht wurden. > and TEMP1, KEYctA1 ;veränderte Tasten nur erhalten, wenn in > and TEMP1, KEYctA2 ;Prellzähler beide Bits gesetzt Nun werden nur die Tastenänderungen in TEMP1 erhalten, deren Prellzähler den Zählerstand 3 erreicht haben, also deren Bits in beiden Zählregistern gesetzt sind. Ist nur eines der Zählerbits 0, dann wird das Bit in TEMP1 auch 0. Es bleiben also nur die veränderten Tasten stehen, deren Prellzählerstand 3 ist, die also 4 mal hintereinander als verändert erkannt wurden. > eor KEYstA, TEMP1 ;veränderte Tasten toggeln, neuer gültiger Status Nun werden die Bits im "gültigen Status" getoggelt (gekippt, umgeschaltet), die in TEMP1 1 sind, also deren Taster 4 Runden lang anders waren als der gültige Zustand. > and TEMP1, KEYstA ;nur gedrückte Tasten berücksichtigen Jetzt werden die Bits in TEMP1 "rausgeschmissen" (gelöscht), an denen KEYstA 0 ist, also deren Taster nicht betätigt sind. Übrig bleiben nur die Bits, deren Taster von der Entprellung als "betätigt" erkannt wurden. Da nur die veränderten Tastenbits (TEMP1) mit den betätigten Tastenbits (KEXstA) verANDet werden, bleiben nur die Bits erhalten, die in dieser Entprellrunde (Pollrunde) als "neu betätigt" erkannt wurden. Und das pro Betätigung nur 1 mal, egal wie lange der Taster noch betätigt bleibt. > or KEYchA, TEMP1 ;neue Tasten merken Und diese Bits, die sagen, dass der Taster JETZT (nach 4 maligem Erkennen als betätigt) als AKTIV übernommen wurde, werden jetzt in KEYchA gesetzt. Dieses Register kann nun von der Mainloop oder einem Job davon bitweise ausgelesen und darauf reagiert (verzweigt) werden. Dabei führt die Mainloop (oder deren Job) die vorgesehene Aktion aus und löscht dieses Bit in KEYchA, denn die Arbeit ist ja getan und soll erst dann wieder getan werden, wenn der zugehörige Taster losgelassen und wieder betätigt wurde. Das Geniale an dieser Routine ist der geringe Ressourcenberbrauch. Es werden zum wirksamen Entprellen von 8 Tasten neben dem Tempregister nur 4 Register (für 8 Tasten!!!) gebraucht. Der zyklisch aufgerufene Code hat nur 13 Instruktionen und braucht (auf dem AVR bei 1 MHz Takt) nur 13 Takte (mit Interrupt-Aufruf etwa 25 Takte) alle 25000 Takte. Das sind etwa 0,1% der Verfügbaren Rechenleistung. Durch ein paar wenige Zusätze lässt sich auch das Loslassen der Tasten separat erkennen, oder eine Repeat-Funktion hinzufügen. Ich hoffe, diese ausführliche Analyse der Routine hilft etwas zu deren Verständnis. ...
@Hannes: Danke für die Analyse, so isses. Der Code von Peter ist für mehrere Tasten extrem effizient. Da ich im betreffenden Programm 10 Tasten an 2 Ports einlese, steht da xxA, es gibt folglich das Gleiche nochmal mit den Registern xxB. Für eine oder zwei Tasten kann man einfach je Taste ein Register nehmen, dieses bei jedem Timerdurchlauf links schieben und den Pinzustand in Bit 0 schreiben. Dann prüfen: Register ist 0x80 => Taste gerade gedrückt (low-aktiv, Pegelwechsel high=>low) Register ist 0x00 => Taste bleibt gedrückt (low-aktiv) Register ist 0xFF => Taste losgelassen (pull-up) Damit hat man 8 Durchläufe zum Entprellen, braucht pro Taste ein Register / SRAM-Byte, und wenig Code. Andere Verfahren mit extra Zähler sind immer aufwändiger. Direkten Tasten-Interrupt macht man nicht, weil: - nicht so viele ExtInts vorhanden, bei PinChange Interrupt der µC auf jeden Mist regiert - Tasten zu langsam sind, um einen Interrupt zu rechtfertigen - Störungen auf der Zuleitung den µC über den Interrupt ausbremsen könnten - eventuell noch andere Sachen über die Pins / den Port laufen, die den Interrupt auslösen Tasten an ExtInt sind nur sinnvoll, um den µC per Tastendruck aufwecken zu können, danach sollte der ExtInt aber abgeschalten werden (und vorm Schlafenlegen natürlich wieder ein) Externe Entprellung über RC benötigt natürlich zusätzliche Bauteile und ist eigentlich nicht zu rechtfertigen, wenn man das Problem so schnell und effizient per Code lösen kann. Ausserdem stören externe RCs eventuell in der Schaltung. Obiger Code ist aus einem Programm, wo an den Pins noch LEDs hängen, die die Tastenzustände anzeigen, es wird zwischen den Tasten und LEDs gemuxt, wo soll da ein RC hin? Auch bei einer Tastenmatrix gehen externe RCs nicht sinnvoll, der Entprell-Code aber durchaus. Ob man die Entprellung im Main oder in der Timer-ISR macht, hängt vom Programm und Programmierstil ab. Grundsätzlich gilt: ISRs so kurz wie sinnvoll möglich.
Timm Thaler schrieb: > Für eine oder zwei Tasten kann man einfach je Taste ein Register nehmen, Für eine Taste gibt es ja noch den hocheffizienten Code von Peter Dannegger, der mit 4 Bit auskommt:
1 | .def srsk=r2 ;Kopie SREG |
2 | .def key_reg=r23 ;Entprellzähler |
3 | .equ key_state=2 ;Bit Tastenstatus |
4 | .equ key_press=3 ;Bit Tastenflag |
5 | |
6 | ... |
7 | |
8 | takt: ;ISR Timer... |
9 | in srsk,sreg ;SREG sichern |
10 | ... |
11 | entprellung: ;Entprellung bei Peter Dannegger abgeguckt |
12 | bst key_reg, key_state ;alten Tastenzustand ins T-Flag |
13 | sbis key_in, key_pin ;Taste betätigt? nein... |
14 | rjmp _deb_x0 ;ja... |
15 | brts _deb_11 ;nein, vorher auch nicht? nein... |
16 | rjmp _deb_10 ;ja, Unterschied |
17 | _deb_x0: |
18 | brts _deb_10 ;vorher auch betätigt? nein, Unterschied... |
19 | _deb_00: |
20 | _deb_11: ;key_state gleich key_pin |
21 | cbr key_reg,63 ;reset Prellzähler |
22 | _deb_10: |
23 | _deb_01: ;key_state ungleich key_pin |
24 | sbrs key_reg, key_press |
25 | inc key_reg ;hochzählen |
26 | rjmp takt_ende ;fertig... |
27 | ... |
28 | takt_ende: ;Ende der Timer-ISR |
29 | out sreg,srsk ;SREG wiederherstellen |
30 | reti |
31 | |
32 | |
33 | mainloop: ;Hauptschleife |
34 | sbrc key_reg,key_press ;Taster erneut gedrückt? nein... |
35 | rjmp neuimp ;ja, abarbeiten... |
36 | ... |
37 | sleep ;schlafen gehen |
38 | rjmp mainloop ;nochmal... |
39 | |
40 | neuimp: ;Job |
41 | ... |
42 | rjmp mainloop |
Die oberen 4 Bit können dann immernoch für andere Flags genutzt werden. ...
Vielleicht hab ich ja den Punkt nicht verstanden, aber im Vergleich zu Byte schieben, Bit setzen und Bitmuster auswerten scheint mir der Aufwand zur Einsparung von 3 Bits doch recht hoch.
Timm Thaler schrieb: > scheint mir der > Aufwand zur Einsparung von 3 Bits doch recht hoch. Das sehe ich nicht so. Die eigentliche Entprellung kommt mit 9 Instruktionen daher. Das sieht nur aufgrund der vielen Labels so groß aus. ...
Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.