| |
 |
The 8051
|
|
|
|
| |
|
| |
|
| |
Peripheral Interfacing |
| |
|
| |
The following topics are covered in this section: |
| |
|
| |
|
| |
Inputs |
| |
|
| |
Interfacing
Digital Inputs to TTL |
| |
Before we can discuss interfacing digital
signals to TTL inputs, we must remind ourselves of the voltage and
current levels of a TTL input. |
| |
|
| |
The logic levels for TTL inputs are as follows: |
| |
- HIGH - between 2 V and 5 V
- LOW - between 0 V and 0.8 V
|
| |
When a HIGH is applied to a TTL input it draws
very little current (about 40 uA). When a LOW is applied to a TTL input
it sources approximately 1.6 mA. |
| |
|
| |
Therefore, when interfacing a digital input
(which will be either HIGH or LOW) to TTL we must ensure it meets the
requirements of a TTL input. |
| |
|
| |
The diagram below shows how to interface a
digital input (ie; either high or low) to TTL. |
| |
 |
| |
When the digital input is HIGH the transistor
will be turned on. This results in a direct path from the port pin to
ground, therefore the pin is logic 0. When the digital input is LOW the
transistor is off which means there is no path for current from the
collector to the emitter, therefore the port pin will read 5V. |
| |
This circuit results in logic inversion, but
this should not be a problem as inverting the port pin through software
is very easy. |
| |
|
| |
When the transistor is on the port pin is
connected directly to ground. Therefore there is a path for the 1.6 mA
from the port pin (TTL current when input is LOW). The 10 K emitter
resistor ensures the current from the supply is kept low, an important
consideration in battery powered devices. |
| |
When the transistor is off the port pin is at 5
V (in reality it will not be exactly 5V because a transistor is never
fully off and a small current will flow through the emitter resistor,
resulting in a small voltage drop across the resistor - but the voltage
level on the resistor will still be close to 5 V). Since there is very
little current flowing, power consumption is kept low. Also, as
mentioned above, a TTL input draws very little current when a HIGH is
applied to it, so this circuit satisfies the requirements of a TTL
input and keeps power consumption at a minimum. |
| |
|
| |
The digital HIGH need not be TTL level inputs. |
| |
The HIGH voltage applied to the base of the
transistor does not have to be 5V. For example, the input circuit could
be from temperature sensor that produces a HIGH voltage when the
temperature exceeds a certain value. The voltage level from this
circuit could be any voltage that is high enough to turn on the
transistor (say, 12V for example) and the value of the base resistor
can be calculated to suit. Because the voltage applied to the emitter
resistor is 5 V the digital HIGH from the sensor circuit is
level-shifted to suit a TTL input. |
| |
|
| |
|
| |
Switches |
| |
The circuit above is actually interfacing an
electronic switch, the transistor, to a TTL input. We can interface a
physical switch in exactly the same way, as shown below. |
| |
 |
| |
When the switch is open, no current flows
through the resistor and therefore the voltage on the microcontroller
pin is 5 V. When the switch is closed the pin is connected directly to
ground. As before, when the TTL input is HIGH practically no current
flows in the circuit and when the input is LOW there is a direct
current for the 1.6 mA that may flow from the pin. |
| |
|
| |
Switch Bounce |
| |
When a physical switch is closed the contacts
bounce open and closed rapidly for about 20 to 30 ms, as illustrated
below. |
| |
 |
| |
The opening of a switch is clean and without
bounce. However, when a switch is closed the contacts bounce open and
closed for about 30 ms. While this is a very short time in human terms
it is a very long time for a microcontroller (the basic 8051 running on
a system clock of 12 MHz executes a 1-byte instruction in 1 us).
Without switch debouncing, the microcontroller would 'think' the switch
was opened and closed many times. Imagine if a push-button switch was
being used to increment the output from a microcontrolled power supply.
If the switch was connected to the microcontroller without switch
bounce then a user pressing the switch once would actually result in
the output voltage being increased many times because the
microcontroller would respond as if the switch had been pressed many
times. |
| |
|
| |
Hardware Switch Debounce |
| |
One method of hardware debounce is shown below. |
| |
  |
| |
As can be seen from the waveforms above, when
the switch is closed the capacitor voltage drops to 0 V. When the
switch bounces open the capacitor begins to charge back up to 5 V, but
due to the RC constant, it cannot charge beyond the schmitt trigger's
HIGH reference voltage before the switch bounces closed again. Once the
switch closes, the capacitor again drops to 0 V. Since the voltage on
the capacitor never goes beyond the trigger's HIGH reference voltage
during the switch bounce, the output of the trigger remains LOW and the
switch bounce is not seen on the port pin. |
| |
When the switch is physically opened the
capacitor has plenty of time to charge beyond the trigger's HIGH
reference voltage, at which point the trigger output goes HIGH and this
is seen on the port pin. |
| |
|
| |
Software Switch Debounce |
| |
Hardware debounce requires extra circuitry. With
small devices, this extra hardware may not be tolerated. In most cases,
software debounce is more than adequate. Software debounce simply
incorporates a delay of about 30 ms while the switch bounces. In other
words, when a key press is detected, the system delays for about 30 ms
before processing the input. By then the switch will have stopped
bouncing and the microcontroller will only process the initial switch
contact. |
| |
 |
| |
Delaying for about 30 ms will not be noticed by
the user, but the microcontroller could do quite a bit of work in that
time. Therefore, in a multifunction system it is more efficient to
initialise a timer and start it so that it will overflow and generate
an interrupt 30 ms after the switch was pressed. In that way, the
controller can be doing some other work while the switch bounces. |
| |
 |
| |
In the above flow chart diagrams, processing the
key press is handled in the ISR. This may not be the case in a
multifunction system. It is more likely that the ISR would set a flag
to let the main program know that a key has been pressed (or, in an
RTOS system, to move a process from the waiting state to the ready
state). |
| |
|
| |
|
| |
Keypads |
| |
Keypads are assembled in a matrix form, as
illustrated below. |
| |
 |
| |
The above diagram shows a 4 X 4 keypad - 16 switches
configured in 4 columns and 4 rows. |
| |
In the default state (all switches open) there
is no connection between the rows and columns. When a switch is pressed
a connection between the switch's row and the switch's column is made. |
| |
|
| |
Keypad Decoder |
| |
Many keypads are built with an onboard decoder
that scans the keypad and, if a key is pressed, returns a number
identifying the key. Alternatively, a keypad decoder chip can be
purchased separately and interfaced with a keypad. The diagram below
shows a 4 X 4 keypad
interfaced with such a decoder. |
| |
 |
| |
The decoder is shown connected to the 8051, as a
suggestion. Obviously, the outputs from the decoder don't need to go to
the LSBs of P1, nor does the data available line (DA) need to be
connected to the external 0 interrupt line. However, the above
configuration is one way of interfacing a 4 X 4 keypad decoder to the
8051. |
| |
The decoder has 8 inputs; the 4 X inputs are
connected to the 4 keypad columns while the Y inputs are connected to
the 4 keypad rows. Not shown in the diagram are pins for connecting
capacitors to the decoder. These capacitors govern the rate at which
the keypad is scanned. |
| |
When a key is pressed the 4-bit code for the key
(there are 16 keys, therefore there are codes 0000 to 1111 in binary)
appears on the four output lines (and in this case will appear on the 4
LSBs of P1) and the data available line (DA) goes LOW. If connected to
an external interrupt line (in this case, the INT0-bar line) the
microcontroller will be interrupted when a key is pressed. The ISR
could then read the 4 LSBs of P1 and process the data. |
| |
The decoder chip takes care of switch debounce,
therefore the programmer is freed from this responsibility, which is an
advantage of using a decoder chip. |
| |
|
| |
Software Decoder |
| |
The above decoder function can be implemented in
software. The keypad could be interfaced with the 8051 as detailed
below. |
| |
 |
| |
With the above configuration, an interrupt is
generated on the INT0-bar line when a key is pressed. We will deal with
how this works in a moment. Firstly, let's see how the keyboard is
scanned. |
| |
The steps are: |
| |
- Scan row 1
- Scan row 2
- Scan row 3
- Scan row 4
|
| |
Scanning a row is achieved by applying 0 V to
the port pin for that row and 5 V to the other three rows, then
scanning each individual column to see if one of them is LOW. If it is,
then the key at the junction between the current row and column being
scanned is the pressed key. |
| |
- Clear row 1, set other 3
- Scan column 1
- Scan column 2
- Scan column 3
- Scan column 4
- Clear row 2, set other 3
- Scan column 1
- Scan column 2
- Scan column 3
- Scan column 4
- Clear row 3, set other 3
- Scan column 1
- Scan column 2
- Scan column 3
- Scan column 4
- Clear row 4, set other 3
- Scan column 1
- Scan column 2
- Scan column 3
- Scan column 4
|
| |
For example, let's say the key being pressed is
key 6. When scanning the first row, P1.0 will be cleared while the
other 3 rows (P1.1, P1.2 and P1.3) are set, as detailed in the diagram
below. |
| |
 |
| |
Since no key in this row is closed there is no
path for current through any of the pull-up resistors and all 4 columns
(on P1.4 to P1.7) are HIGH. Therefore, the key pressed was not found
while scanning row 1. |
| |
The diagram below illustrates scanning row 2.
(Note that key 6 is still closed.) |
| |
 |
| |
In this case, column 3 is connected through the
closed switch to row 2. Since row 2 is LOW, column 3 is LOW. |
| |
|
| |
A series of flowcharts for implementing software
keypad scan is given below: |
| |
|
| |
 |
| |
 |
| |
 |
| |
 |
| |
 |
| |
|
| |
The keypad is initialised in the main program;
all rows are cleared. Therefore, when a key is pressed, since all rows
are LOW, then one of the columns (the one containing the key that has
been pressed) will be connected to 0 V. This logic 0 into the AND gate
will result in a logic 0 out. Since the output of the AND gate is
connected to INT0-bar, a key press will result in an external 0
interrupt. |
| |
|
| |
The keyPressedISR is the ISR for dealing with an
external 0 interrupt. The first thing this ISR does is disable the
external 0 interrupt and call a 30 ms (typical) delay subroutine. When
the delay subroutine returns the key will have stopped bouncing and the
keypad can now be scanned. |
| |
|
| |
In this example, the value of the key pressed (0
to 15) will be stored in R0. Therefore, at the start of the scanKeypad
subroutine R0 is set to 0. Row 1 is cleared while the other three rows
are set. The columnScan subroutine is then called. It tests the status
of each column. If the first column is 0 then, since we are currently
scanning row 1, key 0 was pressed and its value is in R0. Therefore the
keyFound flag is set and the subroutine returns. |
| |
If the first column is not 0, R0 is incremented
(it now holds 1) and the next column is tested. If it is 0 then key 1
was pressed and this value is in R0 - therefore the keyFound flag is
set and the subroutine returns. |
| |
This is repeated for all columns until the key
is found. |
| |
If none of the four columns is 0 then the key
pressed is not in this row and the subroutine returns without setting
the keyFound flag. |
| |
|
| |
When columnScan returns, the keyFound flag is
tested. If it is not 1 then the key was not found and the scanKeypad
subroutine continues with the next row. Throughout this process, R0 is
incremented so that when the key is finally found R0 will contain the
value of that key. |
| |
|
| |
When scanKeypad returns to the ISR the value of
the key is in R0. The ISR then calls a subroutine to wait for the key
to be released. If we do not wait for the key to be released and
immediately enable the external 0 interrupt, then the system will react
as if the key was pressed again. Even if a user presses and releases
the key as quickly as possible, the microcontroller will have executed
the ISR and enabled the INT0 interrupt before the user actually
released the key. Therefore we wait for the user to release the key
before proceeding. |
| |
The waitForKeyRelease subroutine is quite
simple. All four rows are cleared so that no matter which key is
pressed, one of the columns will be 0 which will result in a 0 out of
the AND gate to the INT0-bar line. Therefore, while the key is held
down this line will be 0. Once the key is released then all four
columns will be 1 resulting in a 1 at INT0-bar and the subroutine
returns. |
| |
|
| |
The external 0 interrupt flag (IE0) is then
cleared because it may have been set as the key bounces and as we
scanned the keyboard (remember, disabling an interrupt does not prevent
the interrupt from occurring - a 0 on INT0 will still set the flag,
IE0). If we did not clear this flag, once we again enable the external
0 interrupt the system would again vector to keyPressedISR. |
| |
The processKeyFlag is then set to alert the main
program to the fact that a key was pressed. The main program can then
retrieve the value of the key from R0 and process it in whatever way
the system design requires. |
| |
|
| |
Separate Debounce Interrupt |
| |
One of the problems with the above
implementation is the fact that the system is held in a 30 ms delay
while the key bounces. The microcontroller could be doing something a
lot more useful in that time (remember, a basic 8051 running on a
system clock of 12 MHz could execute 30,000 1-byte instructions in that
time). One way would be to set one of the timers to overflow in 30 ms,
enable the timer's interrupt, start the timer and exit the
keyPressedISR. The timer's ISR could then execute the rest of the
keypad scan process (ie; what's left in keyPressedISR above goes into
the timer's ISR instead). |
| |
|
| |
Doing Nothing While the Key is Held Down |
| |
In the above implementation the system is held
up doing nothing as it waits for the key to be released. Even in the
short space of time of an ordinary key press, the controller could be
doing something useful, but it is even more wasteful if you imagine a
user holding the key down for a long time. One solution with the 8051
would be to initialise the external 0 interrupt as negative-edge
activated rather than low-level activated. In this case, the
waitForKeyRelease subroutine would not be needed at all. Once the
external 0 interrupt is again enabled in keyPressedISR another external
0 interrupt could not occur until the key was released and another (or
the same one) pressed; only this would result in a negative edge on
INT0-bar. |
| |
Note: there is one other task performed
by waitForKeyRelease - in performing its function it resets all four
rows. If this subroutine is removed, as suggested, then the code for
clearing the rows (ie; CLR P1.0; CLR P1.1; CLR P1.2; CLR P1.3) must be
included in keyPressedISR so that the system is then ready for the next
key press. |
| |
|
| |
|
| |
ADC
Interfacing |
| |
The schematic symbol for a typical
analogue-to-digital converter is shown below. On the right is an
illustration of how the ADC may be interfaced with the 8051. |
| |
|
| |
The function of the ADC pins are as follows: |
| |
- CS-bar is the chip select
- INTR-bar is the interrupt line - goes low when a conversion
is complete.
- RD-bar enables the data lines.
- WR-bar is cleared and then set to start a conversion.
|
| |
In the above example of interfacing the ADC to
the 8051, the CS-bar line is connected to ground to permanently enable
the chip. The INTR-bar line goes LOW once a conversion is complete,
therefore it is connected to one of the external interrupt pins on the
8051. In this way, the 8051 will be interrupted when a conversion is
complete and data is ready for reading. |
| |
The data lines are tri-state (hence the inverted
triangle symbol) which means this chip can be memory mapped and the
data lines can be connected directly to the data bus. In the above
example the data lines are connected to port 1, but since they are
tri-state the port can also be used for something else. Only when the
conversion is complete is P2.0 cleared which enables the data lines and
the analogue conversion appears on port 1. |
| |
The WR-bar line is used for starting a
conversion. Clearing this line resets the internal
successive-approximation register and the 8-bit shift register. When
the line is set conversion begins. |
| |
Therefore, taking a reading from the ADC is a
two step process: |
| |
- Clear and then set WR-bar to initiate a conversion.
- Sometime later (typically 100 us), the INTR-bar line will
go LOW to indicate the conversion is complete. This will cause an
external 0 interrupt and it is up to the external 0 ISR to read the
data by clearing P2.0 and reading the data from port 1.
|
| |
Using an interrupt allows the microcontroller to
do some work during the 100 us it takes to convert the analogue input
into digital. |
| |
|
| |
|
| |
|
| |
Outputs |
| |
We will now look at interfacing output devices
to microcontroller ports, focusing on the following topics: |
| |
- LEDs
- 7-segment LED displays
- Multiplexing 7-segment LED displays
- DC motors
|
| |
|
| |
TTL Compatibility |
| |
When discussing interfacing to TTL inputs above,
we noted the current sinked by a TTL input when the input is HIGH is
approximately 40 uA. Since the fan-out of TTL is 10, the maximum
current sourced by a TTL output HIGH is 400 uA. |
| |
The current sourced by a TTL input when the
input is LOW is 1.6 mA, therefore (with a fan-out of 10) the maximum
current sinking for a TTL output LOW is 16 mA. |
| |
|
| |
|
| |
LEDS |
| |
Therefore, when interfacing an LED to a TTL
output, the maximum current through the LED is 16 mA. The circuit below
shows how to interface an LED to a microcontroller port pin. |
| |
 |
|
 |
| Basic LED interface providing max. LED on current of
16 mA |
|
LED interface to provide extra LED on current |
| The value for the resistor is calculated to result in
the desired LED on current - most LEDs have a forward voltage drop of
about 2 V. |
|
The values of both resistors are calculated, using the
transistor Bdc value, to achieve the desired LED on current. |
|
| |
|
| |
|
| |
As explained, this limits the LED on current to
16 mA, which in most cases is adequate. However, if more current is
required, the second circuit shown above may be used. Note that both
circuits result in the microcontroller port pin sinking current when
the LED is on, which is desirable as port pins will sink a lot more
current than they will source. |
| |
|
| |
|
| |
7-segment Displays |
| |
Interfacing a single 7-segment display to a
microcontroller port is done in the same manner as interfacing a single
LED. Again, the LEDs can be connected directly to the port pins or, if
high current LEDs are being used, they can be connected through p-n-p
transistors. Both methods are detailed below. |
| |
 |
|
 |
| Basic 7-segment display interface providing max.
LED-on current of 16 mA |
|
7-segment interface to provide extra LED-on current |
| |
|
The complete configuration for only one segment and the
decimal point is shown. However, the configuration for the other 6
segments is exactly the same. |
|
| |
|
| |
|
| |
Multiplexing |
| |
It is often necessary to interface a number of
7-segment displays to a microcontroller. Rather than use a separate
port for each display, all of the displays are connected to the same
port and other port pins are used for switching on one display at a
time. |
| |
 |
| |
As long as the
displays are turned on and off fast enough, to the eye it
will seem as if they are all on together. A timer interrupt could be
used to
switch from one display to the next. For example, timer zero could be
set to
interrupt once every five milliseconds. The operation of the timer zero
ISR
would be:
- Turn off all
displays by setting the display enable port pins.
- Send data
for next display to the data port.
- Turn on next
display (if current display is 4, next display is 1) by clearing the
appropriate enable port pin.
|
| |
|
| |
|
| |
DC Motors |
| |
An interfacing method for turning on and off a
DC motor via a microcontroller is shown below. |
| |
 |
| |
However, the above circuit will only work for a
5 V motor. If the supply voltage is changed (for example, if the supply
is changed to 12 V to run a 12 V motor) then the motor will be on all
the time because 5 V applied to the base of the p-n-p transistor is not
enough to turn it off. |
| |
|
| |
To interface to larger motors the following
circuit may be used. |
| |
 |
| |
In the above example a 12 V DC motor is
interfaced to a microcontroller. When the port pin is set (ie; is equal
to 5 V) the p-n-p transistor is off which means the n-p-n transistor is
also off. Therefore there is no path for current through the motor and
the motor is off. |
| |
When the port pin is cleared the p-n-p
transistor is on. This turns on the n-p-n transistor which allows
current to flow through the motor to ground; the motor is on. |
| |
The value of R2 needs to be carefully chosen;
too high and the current into the base of the n-p-n transistor will not
be enough to turn on the transistor, too low and the circuit draws too
much current. |
| |
|
| |
Bi-directional DC Motor |
| |
A circuit diagram for interfacing a 12V DC motor
to a microcontroller in a way that allows the controller to not only
turn on and off the motor but also to set the direction in which the
motor runs when it is on, is given below. |
| |
 |
| |
The circuit is made up of a bridge. If both
sides of the motor are at the same voltage the motor is off. So, if T1
and T3 are on, both sides of the motor are connected to 12 V and the
motor is off. If T2 and T4 are on both sides of the motor are connected
to ground and, again, the motor is off. |
| |
If T1 and T4 are on then the left side of the
motor is at 12 V and the right side is at ground, therefore the motor
runs in one direction. We will call this forward. |
| |
If T3 and T2 are on then the left side of the
motor is at ground and the right side is at 12 V, therefore the motor
runs in the opposite direction; ie, reverse. |
| |
|
| |
The circuit is designed so that T1 and T2 cannot
be on at the same time and T3 and T4 cannot be on at the same time.
This is very important; if T1 and T2 were on at the same time there
would be a short circuit between 12 V and ground and the transistors
would burn out. The same is true for T3 and T4. |
| |
|
| |
The truth table for the circuit with its two
inputs, A and B, is given below. |
| |
| A |
B |
Motor |
| 0 |
0 |
off |
| 0 |
1 (5 V) |
reverse |
| 1 (5 V) |
0 |
forward |
| 1 (5 V) |
1 (5 V) |
off |
|
| |
An explanation of the four entries in the table
is given below: |
| |
- Entry 1:
- With A at 0 (ie; ground) T5 is on which turns on T2;
left side of motor is at ground. A at 0 also means T6 is off. Since
there is no path for current through R3 and R4 there is no voltage drop
across them which in turn means the base of T1 is at 12 V, hence it is
off.
- The right-hand side of the circuit is a mirror image of
the left, therefore with B at 0, T4 is on and T3 is off - hence the
right side of the motor is also at ground; the motor is off.
- Entry 2:
- A is still at 0 which means T1 is still off and T2 is
still on; the left side of the motor is at ground.
- With B at 5 V (ie; logic 1 on the port pin which is
being used for B) T7 is off which means T4 is off. But T8 is on which
generates a path for current through T8 to ground and also through R9
to the base of T3. There is a certain amount of voltage dropped across
R9, but the base of T3 is close enough to ground for T3 to turn on; the
right side of the motor is at 12 V.
- The motor is therefore on and we stated above that
ground on the left of the motor and 12 V on the right would be called
reverse.
- Entry 3:
- This is the mirror image of entry 2, resulting in T1
on, T2 off, T3 off and T4 on; hence the left side of the motor is at 12
V and the right side is at ground - the motor runs forward.
- Entry 4:
- As in entry 3, with A at 5 V the left side of the motor
is at 12 V.
- As in entry 2, with B at 5 V the right side of the
motor is at 12 V.
- Therefore the motor is off.
|
| |
|
| |
|
| |
|
| |
|
| |
|
| |
Copyright (c) 2005-2006 James Rogers
|