/*---*- Bits2.C (v1.00)
--- Reading and writing individual port pins.
NOTE: Both pins on the same port --- Generic version ---
-*---*/ #include <reg52.H>
// Function prototypes
void Write_Bit_P1(const unsigned char, const bit); bit Read_Bit_P1(const unsigned char);
/* ... */ void main (void)
{ bit x; while(1)
{
x = Read_Bit_P1(0); // Read Port 1, Pin 0 Write_Bit_P1(1,x); // Write to Port 1, Pin 1 }
}
/* --- */ void Write_Bit_P1(const unsigned char PIN, const bit VALUE)
{
unsigned char p = 0x01; // 00000001
// Left shift appropriate number of places p <<= PIN;
// If we want 1 output at this pin if (VALUE == 1)
{
P1 |= p; // Bitwise OR return;
}
// If we want 0 output at this pin p = ~p; // Complement
P1 &= p; // Bitwise AND }
/* --- */ bit Read_Bit_P1(const unsigned char PIN)
{
unsigned char p = 0x01; // 00000001
// Left shift appropriate number of places p <<= PIN;
// Write a 1 to the pin (to set up for reading) Write_Bit_P1(PIN, 1);
// Read the pin (bitwise AND) and return return (P1 & p);
}
/*---*- ---- END OF FILE --- -*---*/
4.6 The need for pull-up resistors
In our discussions in this chapter, we have assumed that we were reading from port pins in the simulator: we have not yet considered how a switch will actually be con- nected to the 8051 port pin in a real application. Figure 4.4 illustrates one possibility.
This hardware operates as follows:
● When the switch is open, it has no impact on the port pin. An internal resistor on the port ‘pulls up’ the pin to the supply voltage of the microcontroller (typi- cally 5V). If we read the pin, we will see the value ‘1’. (We say more about pull-up resistors below).
● When the switch is closed (pressed), the pin voltage will be 0V. If we read the the pin, we will see the value ‘0’.
The internal ‘pull up’ resistors referred to above can be thought of as small springs, connecting the port pin to a ‘1’ value. To change the port setting, we need to ‘push’ the pin down to 0, against the force of the spring (Figure 4.5).
Where there is no pull-up resistor, changing the state of the input pin is not possi- ble: not matter how hard we push, the pin will always read ‘0’ (Figure 4.6). 68 Embedded C
FIGURE 4.4 Connecting a switch to an 8051 port pin. See text for details
To pin on:
Port 1, Port 2,
or
Port 3.
FIGURE 4.5 A schematic representation of a switch connected to a port (with internal pull-up
resistors). See text for details
Vcc Switch pressed Reads ‘0’ Vcc Switch released Reads ‘1’
FIGURE 4.6 A schematic representation of a switch connected to a port (withoutinternal pull-
up resistors). See text for details
Vcc Switch pressed Reads ‘0’ Vcc Switch released Reads ‘0’
Returning to Figure 4.4, please note that the simple switch arrangement shown only applies to Port 1, Port 2 and Port 3, since these ports all have internal pull-up resistors. This arrangement does not apply to Port 0, which has no internal pull- ups. If you need to connect a switch (or similar device) to Port 0, you can do so, but you need to add an externalpull-up resistor: a resistance of 10 KΩis appropri- ate here (see Figure 4.7).
4.7 Dealing with switch bounce
In an ideal world, this change in voltage obtained by connecting a switch to the port pin of an 8051 microcontroller would take the form illustrated in Figure 4.8 (top). In practice, all mechanical switch contacts bounce(that is, turn on and off, repeatedly, for a short period of time) after the switch is closed or opened. As a result, the actual input waveform looks more like that shown in Figure 4.8 (bottom). Usually, switches bounce for less than 20 ms: however large mechanical switches exhibit bounce behaviour for 50 ms or more.
When you turn on the lights in your home or office with a mechanical switch, the switches will bounce. As far as humans are concerned, this bounce is imper- ceptible. However, as far as the microcontroller is concerned, each ‘bounce’ is equivalent to one press and release of an ‘ideal’ switch. Without appropriate soft- ware design, this can give rise to a number of problems, not least:
● Rather than reading ‘A’ from a keypad, we may read ‘AAAAA’.
● Counting the number of times that a switch is pressed becomes extremely difficult.
● If a switch is depressed once, and then released some time later, the ‘bounce’ may make it appear as if the switch has been pressed again (at the time of release).
FIGURE 4.7 An example of a push-button (‘normally open’) switch input. Where there is no
internal pull-up, this arrangement must be used
To pin on:
Port 0
Vcc
Fortunately, creating the software needed to check for a valid switch input is straightforward:
1 We read the relevant port pin.
2 If we think we have detected a switch depression, we wait for 20 ms and then read the pin again.
3 If the second reading confirms the first reading, we assume the switch really has been depressed.
Note that the figure of ‘20 ms’ will, of course, depend on the switch used: the data sheet of the switch will provide this information. If you have no data sheet, you can either experiment with different figures, or measure directly using an oscilloscope.
4.8 Example: Reading switch inputs (basic code)
In this example, we present a simple code library for reading the input from a mechanical switch. The code implements – directly – the algorithm described in Section 4.7: that is, it tests the switch state and – if the switch is pressed – executes a ‘debounce delay’ before testing the switch again.
70 Embedded C
FIGURE 4.8 The voltage signal resulting from the switch shown in Figure 4.7. [Top] Idealized
waveform resulting from a switch depressed at time t1 and released at time t2. [Bottom] Actual waveform showing leading edge bounce following switch depression and trailing edge bounce following switch release
Voltage +5v
t1 +5v
This switch-reading code is adequate if we want to perform operations such as:
● Drive a motor while a switch is pressed.
● Switch on a light while a switch is pressed.
● Activate a pump while a switch is pressed.
These operations could be implemented using an electrical switch, without using a microcontroller; however, use of a microcontroller may well be appropriate if we require more complex behaviour. For example:
● Drive a motor while a switch is pressed
Condition:If the safety guard is not in place, don’t turn the motor. Instead sound a buzzer for 2 seconds.
● Switch on a light while a switch is pressed
Condition:To save power, ignore requests to turn on the light during daylight hours.
● Activate a pump while a switch is pressed
Condition:If the main water reservoir is below 300 litres, do not start the main pump: instead, start the reserve pump and draw the water from the emergency tank. The key to this library is the function SWITCH_Get_Input(), which is shown in context in Listing 4.5.