registriert
16.10.2014, 09:20
Hallo,
ich habe eine kleine Routine zum Entprellen eines Tastersignals geschrieben. Ich benutze das MK2 Übungsboard mit einem 2MHz µC. Der Taster ist an Port D.3 angeschlossen. An den Ports B.1 bis B.3 sind die LEDs angeschlossen, an B.0 der Tongeber, der bei jedem Schalten einmal kurz piept. Über den externen Interrupt (bei fallender Flanke) werden die LEDs umgeschaltet (quasi in Form eines kleinen Binärzählers). Beim Drücken des Tasters wird leider öfter mehrere Male geschaltet, ich kann mir aber nicht erklären, warum das so ist.
Hier die Entprellroutine:
#define bit_3 3
.
.
.
void entprellen()
{
uint8_t zustand, alterzustand;
uint16_t countdown;
countdown = 255;
while (countdown > 0)
{
zustand = PIND & (1<<bit_3); // aktueller Schaltzustand (maskiert)
if (alterzustand != zustand) countdown = 255; // bei Änderung zum vorherigen: Countdown von vorne
else countdown--; // sonst: runterzählen
alterzustand = zustand; // Schaltzustand merken
}
return;
}
Zur Vollständigkeit die Interrupts:
ISR(INT1_vect)
{
entprellen();
temp = (PORTB>>1);
if (++temp == 8) temp = 0;
PORTB = (temp<<1);
// Ton einschalten (Timer 0 Interrupt bei Überlauf aktiv)
TIMSK0 = 1;
}
ISR(TIMER0_OVF_vect)
{
// aktuelles Ausgangssignal: Bits 1 bis 7 maskieren, bleiben unverändert
maske = PORTB & 0b11111110;
// aktuelles Ausgangssignal: Bit 0 maskieren und umkehren
temp = PORTB & 1;
temp ^= 1;
// Ausgabe des neuen Signals
PORTB = maske | temp;
// Timer zurücksetzen
TCNT0 = 190;
// Ton unterbrechen
if (++zaehler == 0) TIMSK0 = 0;
}
Ich hatte das ganze vorher schon in Assembler umgesetzt. Da funktioniert das Entprellen, beim Drücken des Tasters wird genau einmal weiter geschaltet. Aber meiner Meinung sind die C- und die Assembler-Version absolut gleichwertig.
entprellen: ; Register sichern
push r16
push r17
push r18
ldi r16, 255
debounce: ; Zustand von PORT D einlesen und maskieren
in r17, PIND
andi r17, 0b00001000
; Debounce-Zeit zurücksetzen, wenn der Schaltzustand anders ist
cpse r18, r17
ldi r16, 255
mov r18, r17
; Countdown bis 0
dec r16
brne debounce
; Register wiederherstellen
pop r18
pop r17
pop r16
ret
Wer weiß Rat?
ich habe eine kleine Routine zum Entprellen eines Tastersignals geschrieben. Ich benutze das MK2 Übungsboard mit einem 2MHz µC. Der Taster ist an Port D.3 angeschlossen. An den Ports B.1 bis B.3 sind die LEDs angeschlossen, an B.0 der Tongeber, der bei jedem Schalten einmal kurz piept. Über den externen Interrupt (bei fallender Flanke) werden die LEDs umgeschaltet (quasi in Form eines kleinen Binärzählers). Beim Drücken des Tasters wird leider öfter mehrere Male geschaltet, ich kann mir aber nicht erklären, warum das so ist.
Hier die Entprellroutine:
#define bit_3 3
.
.
.
void entprellen()
{
uint8_t zustand, alterzustand;
uint16_t countdown;
countdown = 255;
while (countdown > 0)
{
zustand = PIND & (1<<bit_3); // aktueller Schaltzustand (maskiert)
if (alterzustand != zustand) countdown = 255; // bei Änderung zum vorherigen: Countdown von vorne
else countdown--; // sonst: runterzählen
alterzustand = zustand; // Schaltzustand merken
}
return;
}
Zur Vollständigkeit die Interrupts:
ISR(INT1_vect)
{
entprellen();
temp = (PORTB>>1);
if (++temp == 8) temp = 0;
PORTB = (temp<<1);
// Ton einschalten (Timer 0 Interrupt bei Überlauf aktiv)
TIMSK0 = 1;
}
ISR(TIMER0_OVF_vect)
{
// aktuelles Ausgangssignal: Bits 1 bis 7 maskieren, bleiben unverändert
maske = PORTB & 0b11111110;
// aktuelles Ausgangssignal: Bit 0 maskieren und umkehren
temp = PORTB & 1;
temp ^= 1;
// Ausgabe des neuen Signals
PORTB = maske | temp;
// Timer zurücksetzen
TCNT0 = 190;
// Ton unterbrechen
if (++zaehler == 0) TIMSK0 = 0;
}
Ich hatte das ganze vorher schon in Assembler umgesetzt. Da funktioniert das Entprellen, beim Drücken des Tasters wird genau einmal weiter geschaltet. Aber meiner Meinung sind die C- und die Assembler-Version absolut gleichwertig.
entprellen: ; Register sichern
push r16
push r17
push r18
ldi r16, 255
debounce: ; Zustand von PORT D einlesen und maskieren
in r17, PIND
andi r17, 0b00001000
; Debounce-Zeit zurücksetzen, wenn der Schaltzustand anders ist
cpse r18, r17
ldi r16, 255
mov r18, r17
; Countdown bis 0
dec r16
brne debounce
; Register wiederherstellen
pop r18
pop r17
pop r16
ret
Wer weiß Rat?