Text1.c
/************************************************************************/
/* */
/* Debouncing 8 Keys */
/* Sampling 4 Times */
/* With Repeat Function */
/* */
/* Author: Peter Dannegger */
/* danni@specs.de */
/* */
/************************************************************************/
#include <reg52.h>
#include <stdio.h>
typedef unsigned char u8;
#define Timer0L 0xCC // 1ms Tick bei 22,118 MHz
#define Timer0H 0xF8 // Dezimal 63692
#define Timer1L 0xFD // 19200 Baud bei 22,118 MHz
#define Timer1H 0xFD
sbit KEY_PIN=P0^2;
#define KEY0 0
#define KEY1 1
#define KEY2 2
#define REPEAT_MASK (1<<KEY1^1<<KEY2) // repeat: key1, key2
#define REPEAT_START 500 // after 500ms
#define REPEAT_NEXT 200 // every 200ms
u8 key_state; // debounced and inverted key state:
// bit = 1: key pressed
u8 key_press; // key press detect
u8 key_rpt;
void timer0() interrupt 1
{
static u8 ct0, ct1,rpt;
u8 j;
j = key_state ^ ~KEY_PIN; // key changed ?
ct0 = ~( ct0 & j ); // reset or count ct0
ct1 = ct0 ^ (ct1 & j); // reset or count ct1
j &= ct0 & ct1; // count until roll over ?
key_state ^= j; // then toggle debounced state
key_press |= key_state & j; // 0->1: key press detect
if( (key_state & REPEAT_MASK) == 0 ) // check repeat function
rpt = REPEAT_START; // start delay
if( --rpt == 0 ){
rpt = REPEAT_NEXT; // repeat delay
key_rpt |= key_state & REPEAT_MASK;
}
}
u8 get_key_press( u8 key_mask )
{
TR0=0 ; // Timer anhalten
key_mask &= key_press; // read key(s)
key_press ^= key_mask; // clear key(s)
TR0=1; // Timer starten
return key_mask;
}
u8 get_key_rpt( u8 key_mask )
{
TR0=0 ; // Timer anhalten
key_mask &= key_rpt; // read key(s)
key_rpt ^= key_mask; // clear key(s)
TR0=1; // Timer starten
return key_mask;
}
u8 get_key_short( u8 key_mask )
{
//cli(); // read key state and key press atomic !
return get_key_press( ~key_state & key_mask );
}
u8 get_key_long( u8 key_mask )
{
return get_key_press( get_key_rpt( key_mask ));
}
int main( void )
{
TMOD = 0x21; // Timer 1 = 8-Bit-Timer mit Auto-Reload-Modus.
// Timer 0 = 16-Bit-Timer.
TL1 = Timer1L; // 19200 Baud bei 22,118 MHz
TH1 = Timer1H; // Nachladewert fuer TL1
TR1 = 1; // Timer 1 starten
SCON = 0x52; // Freigabe von Sender und Empfaenger; Betriebsart: Modus 1
TL0 = Timer0L; // Startwert für Timer0 0x7000
TH0 = Timer0H; // dezimal 28672 => Interrupt alle 20ms
ET0 = 1; // Timer0 Interrupt einschalten
EA = 1; // Interrupt einschalten
TR0 = 1; // Timer 0 starten
for(;;){ // main loop
// single press
if( get_key_press( 1<<KEY0 ))
printf("Taste gedrueckt\n");
// release after short press: task 1
// long press: task 2
if( get_key_short( 1<<KEY1 ))
printf("KURZ\n");
if( get_key_long( 1<<KEY1 ))
printf("LANG\n");
// single press and repeat
if( get_key_press( 1<<KEY2 ) || get_key_rpt( 1<<KEY2 )){
printf("wiederholung\n");
}
}
}