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:

Code:
#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:

Code:
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.

Code:
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?