Example: Counting goats


• With the simple code in the previous example, problems can
arise whenever a switch is pressed for a period longer than
the debounce interval.
• This is a concern, because in many cases, users will press
switches for at least 500 ms (or until they receive feedback
that the system has detected the switch press). As a result, a


user typing “Hello” on a keypad may see:
“HHHHHHHHHeeeeeeeeellllllllllllllllooooooooooo”
appear on the screen.


One consequence is that this code is not suitable for applications
where we need to count the number of times that a switch is pressed
and then released.




/*-------------------------------------------------------------*-
A 'goat counting' program for the 8051...
-*-------------------------------------------------------------*/
#include <Reg52.h>
/* Connect switch to this pin */
sbit Switch_pin = P1^0;
/* Display count (binary) on this port */
#define Count_port P3
/* Return values from Switch_Get_Input() */
#define SWITCH_NOT_PRESSED (bit) 0
#define SWITCH_PRESSED (bit) 1
/* Function prototypes */
void SWITCH_Init(void);
bit SWITCH_Get_Input(const unsigned char DEBOUNCE_PERIOD);
void DISPLAY_COUNT_Init(void);
void DISPLAY_COUNT_Update(const unsigned char);
void DELAY_LOOP_Wait(const unsigned int DELAY_MS);
/* ---------------------------------------------------------------- */
void main(void)
{
unsigned char Switch_presses = 0;
/* Init functions */
SWITCH_Init();
DISPLAY_COUNT_Init();
while(1)
{
if (SWITCH_Get_Input(30) == SWITCH_PRESSED)
{
Switch_presses++;
}
DISPLAY_COUNT_Update(Switch_presses);
}
}

/*-------------------------------------------------------------*/
void SWITCH_Init(void)
{
Switch_pin = 1; /* Use this pin for input */
}
/*-------------------------------------------------------------*-
SWITCH_Get_Input()
Reads and debounces a mechanical switch as follows:
1. If switch is not pressed, return SWITCH_NOT_PRESSED.
2. If switch is pressed, wait for the DEBOUNCE_PERIOD (in ms).
Then:
a. If switch is no longer pressed, return SWITCH_NOT_PRESSED.
b. If switch is still pressed, wait (indefinitely) for
switch to be released, *then* return SWITCH_PRESSED
See Switch_Wait.H for details of return values.
-*-------------------------------------------------------------*/
bit SWITCH_Get_Input(const unsigned char DEBOUNCE_PERIOD)
{
bit Return_value = SWITCH_NOT_PRESSED;
if (Switch_pin == 0)
{
/* Switch is pressed */
/* Debounce - just wait... */
DELAY_LOOP_Wait(DEBOUNCE_PERIOD);
/* Check switch again */
if (Switch_pin == 0)
{
/* Wait until the switch is released. */
while (Switch_pin == 0);
Return_value = SWITCH_PRESSED;
}
}
/* Now (finally) return switch value */
return Return_value;
}

/*-------------------------------------------------------------*-
DISPLAY_COUNT_Init()
Initialisation function for the DISPLAY COUNT library.
-*-------------------------------------------------------------*/
void DISPLAY_COUNT_Init(void)
{
Count_port = 0x00;
}
/*-------------------------------------------------------------*-
DISPLAY_COUNT_Update()
Simple function to display tByte data (COUNT)
on LEDs connected to port (Count_Port)
-*-------------------------------------------------------------*/
void DISPLAY_COUNT_Update(const unsigned char COUNT)
{
Count_port = COUNT;
}
/*-------------------------------------------------------------*-
DELAY_LOOP_Wait()
Delay duration varies with parameter.
Parameter is, *ROUGHLY*, the delay, in milliseconds,
on 12MHz 8051 (12 osc cycles).
You need to adjust the timing for your application!
-*-------------------------------------------------------------*/
void DELAY_LOOP_Wait(const unsigned int DELAY_MS)
{
unsigned int x, y;
for (x = 0; x <= DELAY_MS; x++)
{
for (y = 0; y <= 120; y++);
}
}


Conclusions
The switch interface code presented and discussed in this seminar
has allowed us to do two things:
• To perform an activity while a switch is depressed;
• To respond to the fact that a user has pressed – and then
released – a switch.
In both cases, we have illustrated how the switch may be
‘debounced’ in software.