422 CHAPTER 11
mov al,bit
out dx,al
}
Delay();
}
unsigned char void SendByte(unsigned char data)
{
for (int a = 7; a >= 0; a—)
{
PC0out((data >> a) & 0xef);
PC0out((data >> a) | 0x10);
}
PC0in(0xef); //ack bit
return PC0in(0x10);
}
unsigned char GetByte()
{
unsigned char temp = 0;
for (int a = 7; a >= 0; a—)
{
PC0in(0xef);
temp |= PC0in(0x10) << a;
}
PC0in(0xef); //ack bit
PC0in(0x10);
return temp;
}
void SendStart()
{ // start is one
PC0out(0xef);
PC0out(0x10);
}
void SendStop()
{ // stop is zero
PC0out(0xee);
PC0out(0x10);
}
void SendData(char device, short address, unsigned char data)
{
Char c = 0;
SendStart();
SendByte(0xa0 | device << 1);
SendByte(address >> 8);
SendByte(address);
SendByte(data);
while (c == 0)
{ // wait for ACK = 1;
C = SendByte(0xa0 | device << 1);
}
SendStop();
}
unsigned char ReadData(char device, short address)
{
SendStart();
SendByte(0xa0 | device << 1);
SendByte(address >> 8);
SendByte(address);
SendByte(0xa1 | device << 1);
unsigned char temp = GetByte();
SendStop();
return temp;
}
BASIC I/O INTERFACE 423
11–4 8254 PROGRAMMABLE INTERVAL TIMER
The 8254 programmable interval timer consists of three independent 16-bit programmable coun-
ters (timers). Each counter is capable of counting in binary or binary-coded decimal (BCD). The
maximum allowable input frequency to any counter is 10 MHz. This device is useful wherever
the microprocessor must control real-time events. Some examples of usage include real-time
clock and an events counter, and for motor speed and direction control.
This timer also appears in the personal computer decoded at ports 40H–43H to do the
following:
1. Generate a basic timer interrupt that occurs at approximately 18.2 Hz.
2. Cause the DRAM memory system to be refreshed.
3. Provide a timing source to the internal speaker and other devices. The timer in the personal
computer is an 8253 instead of an 8254.
8254 Functional Description
Figure 11–33 shows the pin-out of the 8254, which is a higher-speed version of the 8253, and a
diagram of one of the three counters. Each timer contains a CLK input, a gate input, and an output
(OUT) connection. The CLK input provides the basic operating frequency to the timer, the gate
pin controls the timer in some modes, and the OUT pin is where we obtain the output of the timer.
The signals that connect to the microprocessor are the data bus pins (D7–D0), RD, WR, CS,
and address inputs A1 and A0. The address inputs are present to select any of the four internal
registers used for programming, reading, or writing to a counter. The personal computer contains
an 8253 timer or its equivalent, decoded at I/O ports 40H–43H. Timer zero is programmed to
generate an 18.2 Hz signal that interrupts the microprocessor at interrupt vector 8 for a clock
tick. The tick is often used to time programs and events in DOS. Timer 1 is programmed for
15 μs, which is used on the personal computer to request a DMA action used to refresh the
dynamic RAM. Timer 2 is programmed to generate a tone on the personal computer speaker.
FIGURE 11–33 The 8254 programmable interval timer. (a) Internal structure and (b) pin-out.
(Courtesy of Intel Corporation.)
424 CHAPTER 11
TABLE 11–4 Address A1 A0 Function
selection inputs to the 8254.
0 0 Counter 0
0 1 Counter 1
1 0 Counter 2
1 1 Control word
Pin Definitions
A0, A1 The address inputs select one of four internal registers within the 8254. See
Table 11–4 for the function of the A1 and A0 address bits.
CLK The clock input is the timing source for each of the internal counters. This input is
often connected to the PCLK signal from the microprocessor system bus controller.
CS
G Chip select enables the 8254 for programming and reading or writing a counter.
GND
OUT The gate input controls the operation of the counter in some modes of operation.
RD
Vcc Ground connects to the system ground bus.
WR
A counter output is where the waveform generated by the timer is available.
Read causes data to be read from the 8254 and often connects to the IORC signal.
Power connects to the +5.0 V power supply.
Write causes data to be written to the 8254 and often connects to the write strobe
(IOWC).
Programming the 8254
Each counter is individually programmed by writing a control word, followed by the initial
count. Figure 11–34 lists the program control word structure of the 8254. The control word
allows the programmer to select the counter, mode of operation, and type of operation
(read/write). The control word also selects either a binary or BCD count. Each counter may be
programmed with a count of 1 to FFFFH. A count of 0 is equal to FFFFH+l (65,536) or 10,000
FIGURE 11–34 The control
word for the 8254-2 timer.
BASIC I/O INTERFACE 425
in BCD. The minimum count of 1 applies to all modes of operation except modes 2 and 3, which
have a minimum count of 2. Timer 0 is used in the personal computer with a divide-by count of
64K (FFFFH) to generate the 18.2 Hz (18.196 Hz) interrupt clock tick. Timer 0 has a clock input
frequency of 4.77 MHz + 4 or 1.1925 MHz.
The control word uses the BCD bit to select a BCD count (BCD = 1) or a binary count
(BCD = 0). The M2, M1, and M0 bits select one of the six different modes of operation (000–101)
for the counter. The RW1 and RW0 bits determine how the data are read from or written to the
counter. The SC1 and SC0 bits select a counter or the special read-back mode of operation, dis-
cussed later in this section.
Each counter has a program control word used to select the way the counter operates. If
two bytes are programmed into a counter, then the first byte (LSB) will stop the count, and the
second byte (MSB) will start the counter with the new count. The order of programming is
important for each counter, but programming of different counters may be interleaved for better
control. For example, the control word may be sent to each counter before the counts for indi-
vidual programming. Example 11–23 shows a few ways to program counters 1 and 2. The first
method programs both control words, then the LSB of the count for each counter, which stops
them from counting. Finally, the MSB portion of the count is programmed, starting both counters
with the new count. The second example shows one counter programmed before the other.
EXAMPLE 11–23
PROGRAM CONTROL WORD 1 PROGRAM CONTROL WORD 2 PROGRAM LSB 1
PROGRAM LSB 2
PROGRAM MSB 1
PROGRAM MSB 2
;setup counter 1
;setup counter 2
;stop counter 1 and program LSB
;stop counter 2 and program LSB ;program MSB of counter 1 and start it
;program MSB of counter 2 and start it
or
PROGRAM CONTROL WORD 1 PROGRAM LSB 1
PROGRAM MSB 1
PROGRAM CONTROL WORD 2 PROGRAM LSB 2
PROGRAM MSB 2
;setup counter 1
;stop counter 1 and program LSB ;program MSB of counter 1 and start it
;setup counter 2
;stop counter 2 and program LSB ;program MSB of counter 2 and start it
Modes of Operation. Six modes (mode 0–mode 5) of operation are available to each of the
8254 counters. Figure 11–35 shows how each of these modes functions with the CLK input, the
gate (G) control signal, and OUT signal. A description of each mode follows:
MODE 0 Allows the 8254 counter to be used as an events counter. In this mode, the
MODE 1 output becomes a logic 0 when the control word is written and remains
there until N plus the number of programmed counts. For example, if a
count of 5 is programmed, the output will remain a logic 0 for 6 counts
beginning with N. Note that the gate (G) input must be a logic 1 to allow the
counter to count. If G becomes a logic 0 in the middle of the count, the
counter will stop until G again becomes a logic 1.
Causes the counter to function as a retriggerable, monostable multivibrator
(one-shot). In this mode the G input triggers the counter so that it develops
a pulse at the OUT connection that becomes a logic 0 for the duration of the
426 CHAPTER 11
FIGURE 11–35 The six modes of operation for the 8254-2 programmable interval timer. The G input stops the
count when 0 in modes 2, 3, and 4.
MODE 2 count. If the count is 10, then the OUT connection goes low for 10 clocking
periods when triggered. If the G input occurs within the duration of the out-
put pulse, the counter is again reloaded with the count and the OUT con-
nection continues for the total length of the count.
Allows the counter to generate a series of continuous pulses that are one
clock pulse wide. The separation between pulses is determined by the
count. For example, for a count of 10, the output is a logic 1 for nine clock
periods and low for one clock period. This cycle is repeated until the
counter is programmed with a new count or until the G pin is placed at a
logic 0 level. The G input must be a logic 1 for this mode to generate a con-
tinuous series of pulses.
BASIC I/O INTERFACE 427
MODE 3 Generates a continuous square wave at the OUT connection, provided that
MODE 4 the G pin is a logic 1. If the count is even, the output is high for one half of
MODE 5 the count and low for one half of the count. If the count is odd, the output is
high for one clocking period longer than it is low. For example, if the
counter is programmed for a count of 5, the output is high for three clocks
and low for two clocks.
Allows the counter to produce a single pulse at the output. If the count is
programmed as a 10, the output is high for 10 clocking periods and low for
one clocking period. The cycle does not begin until the counter is loaded
with its complete count. This mode operates as a software triggered one-
shot. As with modes 2 and 3, this mode also uses the G input to enable the
counter. The G input must be a logic 1 for the counter to operate for these
three modes.
A hardware triggered one-shot that functions as mode 4, except that it is
started by a trigger pulse on the G pin instead of by software. This mode is
also similar to mode 1 because it is retriggerable.
Generating a Waveform with the 8254. Figure 11–36 shows an 8254 connected to function
at I/O ports 0700H, 0702H, 0704H, and 0706H of an 80386SX microprocessor. The addresses
are decoded by using a PLD that also generates a write strobe signal for the 8254, which is
connected to the low-order data bus connections. The PLD also generates a wait signal for the
microprocessor that causes two wait states when the 8254 is accessed. The wait state generator
connected to the microprocessor actually controls the number of wait states inserted into the tim-
ing. The program for the PLD is not illustrated here because it is the same as many of the prior
examples.
(8 MHz) VCC
CLOCK
8 U2 10K
7 100 KHz square wave
D0 D0 CLK0 9 200 KHz continuous pulses
D1 6 D1 G0 11
D2 5 D2 10
D3 OUT0
D4 4 D3 15
D5 3 D4 CLK1 14
D6 G1 13
D7 2 D5
1 D6 OUT1 18
RD D7 16
CLK2 17
A1 WR 22 RD G2
A2
23 WR OUT2
WAIT2 A0
19 A1
M/IO 20
A0
A3 21 CS
A4
A5 U1 8254
A6
A7 1 I1 O1 19
A8 2 I2 O2 18
A9
3 I3 O3 17
A10 4 I4 O4 16
15
A11 5 I5 O5
A12 6 I6 O6 14
A13 I7 O7 13
A14 7 I8 O8 12
A15 8 I9
9 I10
11
16L8
FIGURE 11–36 The 8254 interfaced to an 8 MHz 8086 so that it generates a 100 KHz square
wave at OUT0 and a 200 KHz continuous pulse at OUT1.
428 CHAPTER 11
Example 11–24 lists the program that generates a 100 KHz square-wave at OUT0 and a
200 KHz continuous pulse at OUT1. Counter 0 uses mode 3 and counter 1 uses mode 2. The
count programmed into counter 0 is 80 and the count for counter 1 is 40. These counts generate
the desired output frequencies with an 8 MHz input clock.
EXAMPLE 11–24
;A procedure that programs the 8254 timer to function
;as illustrated in Figure 11–36
TIME PROC NEAR USES AX DX
MOV DX,706H ;program counter 0 for mode 3
MOV AL,00110110B ;program counter 1 for mode 2
OUT DX,AL
MOV AL,01110100B
OUT DX,AL
MOV DX,700H ;program counter 0 with 80
MOV AL,80
OUT DX,AL
MOV AL,0
OUT DX,AL
MOV DX,702H ;program counter 1 with 40
MOV AL,40
OUT DX,AL
MOV AL,0
OUT DX,AL
RET
TIME ENDP
Reading a Counter. Each counter has an internal latch that is read with the read counter port
operation. These latches will normally follow the count. If the contents of the counter are needed,
then the latch can remember the count by programming the counter latch control word (see
Figure 11–37), which causes the contents of the counter to be held in a latch until they is read.
Whenever a read from the latch or the counter is programmed, the latch tracks the contents of the
counter.
When it is necessary for the contents of more than one counter to be read at the same time,
we use the read-back control word, illustrated in Figure 11–38. With the read-back control word,
the CNT bit is a logic 0 to cause the counters selected by CNT0, CNT1, and CNT2 to be latched.
If the status register is to be latched, then the ST bit is placed at a logic 0. Figure 11–39 shows the
status register, which shows the state of the output pin, whether the counter is at its null state (0),
and how the counter is programmed.
FIGURE 11–37 The 8254-2
counter latch control word.
BASIC I/O INTERFACE 429
FIGURE 11–38 The 8254-2
read-back control word.
FIGURE 11–39 The 8254-2
status register.
DC Motor Speed and Direction Control
One application of the 8254 timer is as a motor speed controller for a DC motor. Figure 11–40
shows the schematic diagram of the motor and its associated driver circuitry. It also illustrates the
interconnection of the 8254, a flip-flop, and the motor and its driver.
The operation of the motor driver circuitry is straightforward. If the Q output of the
74ALS112 is a logic 1, the base Q2 is pulled up to +12 V through the base pull-up resistor, and
the base of Q2 is open circuited. This means that Q1 is off and Q2 is on, with ground applied to
the positive lead of the motor. The bases of both Q3 and Q4 are pulled low to ground through the
inverters. This causes Q3 to conduct or turn on and Q4 to turn off, applying ground to the nega-
tive lead of the motor. The logic 1 at the Q output of the flip-flop therefore connects +12 V to the
positive lead of the motor and ground to the negative lead. This connection causes the motor to
spin in its forward direction. If the state of the Q output of the flip-flop becomes a logic 0, then
the conditions of the transistors are reversed and +12 V is attached to the negative lead of the
motor, with ground attached to the positive lead. This causes the motor to spin in the reverse
direction.
If the output of the flip-flop is alternated between a logic 1 and 0, the motor spins in either
direction at various speeds. If the duty cycle of the Q output is 50%, the motor will not spin at all
and exhibits some holding torque because current flows through it. Figure 11–41 shows some
timing diagrams and their effects on the speed and direction of the motor. Notice how each
counter generates pulses at different positions to vary the duty cycle at the Q output of the flip-
flop. This output is also called pulse width modulation
To generate these wave forms, counters 0 and 1 are both programmed to divide the input
clock (PCLK) by 30,720. We change the duty cycle of Q by changing the point at which
430
*open-collector inverters
(8 MHz) VCC
CLOCK 10K
D0 8 U2 CLK0 < 9 4
D1 7 G0 11
D2 6 D0 10 3J P Q
D3 5 D1 OUT0 Q
D4 4 D2 15 1 CLK R
D5 3 D3 CLK1< 14
D6 2 D4 G1 13 2K C
D7 1 D5 L
D6 OUT1 18
RD WR 22 D7 16 1
23 CLK2< 17 5
A1 19 RD G2
A2 20 WR
A0 OUT2
WAIT2 21 A1
CS
U1 8254
M/IO 1 I1 O1 19
A0 2 I2 O2 18
A3 I3
A4 3 I4 O3 17
A5 4 I5 O4 16
A6 I6 15
A7 5 I7 O5
A8 6 I8 14
A9 I9 O6 13
7 I10 12
A10 8 O7
9 16L8 O8
A11 11
A12
A13
A14
A15
FIGURE 11–40 Motor speed and direction control using the 8254 tim
U4A 2 Q1 +12V Q3 U4C
1 Q2 Q4 65
+
* − *
7406 7406
s U4B 4 U4D
3 89
U3A
Q5 * *
Q6
7406 7406
74ALS112
mer.
BASIC I/O INTERFACE 431
FIGURE 11–41 Timing for the motor speed and direction control circuit of Figure 11–40. (a) No rotation,
(b) high-speed rotation in the reverse direction, and (c) high-speed rotation in the forward direction.
counter 1 is started in relationship to counter 0. This changes the direction and speed of
the motor. But why divide the 8 MHz clock by 30,720? The divide rate of 30,720 is divisible
by 256, so we can develop a short program that allows 256 different speeds. This also produces
a basic operating frequency for the motor of about 260 Hz, which is low enough in frequency
to power the motor. It is important to keep this operating frequency below 1000 Hz, but
above 60 Hz.
Example 11–25 lists a procedure that controls the speed and direction of the motor. The
speed is controlled by the value of AH when this procedure is called. Because we have an 8-bit
number to represent speed, a 50% duty cycle, for a stopped motor, is a count of 128. By chang-
ing the value in AH when the procedure is called, we can adjust the motor speed. The speed of
the motor will increase in either direction by changing the number in AH when this procedure is
called. As the value in AH approaches 00H, the motor begins to increase its speed in the reverse
432 CHAPTER 11
direction. As the value of AH approaches FFH, the motor increases its speed in the forward
direction.
EXAMPLE 11–25
;A procedure that controls the speed and direction of the motor
;in Figure 11–40.
;
;AH determines the speed and direction of the motor where
;AH is between 00H and FFH.
CNTR EQU 706H
CNT0 EQU 700H
CNT1 EQU 702H
COUNT EQU 30720
SPEED PROC NEAR USES BX DX AX
MOV BL,AH ;calculate count
MOV AX,120
MUL BL
MOV BX,AX
MOV AX,COUNT
SUB AX,BX
MOV BX,AX
MOV DX,CNTR ;program control words
MOV AL,00110100B
OUT DX,AL
MOV AL,01110100B
OUT DX,AL
MOV DX,CNT1 ;program counter 1
MOV AX,COUNT ;to generate a clear
OUT DX,AL
MOV AL,AH
OUT DX,AL
.REPEAT ;wait for counter 1
IN AL,DX
XCHG AL,AH
IN AL,DX
XCHG AL,AH
.UNTIL BX == AX
MOV DX,CNT0 ;program counter 0
MOV AX,COUNT ;to generate a set
OUT DX,AL
MOV AL,AH
OUT DX,AL
RET
SPEED ENDP
The procedure adjusts the wave form at Q by first calculating the count at which counter 0
is to start in relationship to counter 1. This is accomplished by multiplying AH by 120 and then
subtracting it from 30,720. This is required because the counters are down-counters that count
from the programmed count to 0 before restarting. Next, counter 1 is programmed with a count
of 30,720 and started so it generates the clear-wave form for the flip-flop. After counter 1 is
started, it is read and compared with the calculated count. Once it reaches this count, counter 0 is
started with a count of 30,720. From this point forward, both counters continue generating the
clear and set wave forms until the procedure is again called to adjust the speed and direction of
the motor.
BASIC I/O INTERFACE 433
11–5 16550 PROGRAMMABLE COMMUNICATIONS INTERFACE
The National Semiconductor Corporation’s PC16550D is a programmable communications inter-
face designed to connect to virtually any type of serial interface. The 16550 is a universal asyn-
chronous receiver/transmitter (UART) that is fully compatible with the Intel microprocessors. The
16550 is capable of operating at 0–1.5 M baud. Baud rate is the number of bits transferred per sec-
ond (bps), including start, stop, data, and parity (Bps is bytes per second and bps are bits per sec-
ond). The 16550 also includes a programmable baud rate generator and separate FIFOs for input
and output data to ease the load on the microprocessor. Each FIFO contains 16 bytes of storage.
This is the most common communications interface found in modem microprocessor-based
equipment, including the personal computer and many modems.
Asynchronous Serial Data
Asynchronous serial data are transmitted and received without a clock or timing signal.
Figure 11–42 illustrates two frames of asynchronous serial data. Each frame contains a start bit,
seven data bits, parity, and one stop bit. The figure shows a frame that contains one ASCII char-
acter and 10 bits. Most dial-up communications systems of the past, such as CompuServe,
Prodigy, and America Online, used 10 bits for asynchronous serial data with even parity. Most
Internet and bulletin board services also use 10 bits, but they normally do not use parity. Instead,
eight data bits are transferred, replacing parity with a data bit. This makes byte transfers of non-
ASCII data much easier to accomplish.
16550 Functional Description
Figure 11–43 illustrates the pin-out of the 16550 UART. This device is available as a 40-pin DIP
(dual in-line package) or as a 44-pin PLCC (plastic leadless chip carrier). Two completely
separate sections are responsible for data communications: the receiver and the transmitter.
Because each of these sections is independent, the 16550 is able to function in simplex, half-
duplex, or full-duplex modes. One of the main features of the 16550 is its internal receiver and
transmitter FIFO (first-in, first-out) memories. Because each is 16 bytes deep, the UART
requires attention only from the microprocessor after receiving 16 bytes of data. It also holds
16 bytes before the microprocessor must wait for the transmitter. The FIFO makes this UART
ideal when interfacing to high-speed systems because less time is required to service it.
An example simplex system is one in which the transmitter or receiver is used by itself
such as in an FM (frequency modulation) radio station. An example half-duplex system is a
CB (citizens band) radio, on which we transmit and receive, but not both at the same time. The
full-duplex system allows transmission and reception in both directions simultaneously. An
example of a full-duplex system is the telephone.
The 16550 can control a modem (modulator/demodulator), which is a device that converts
TTL levels of serial data into audio tones that can pass through the telephone system. Six pins on
FIGURE 11–42 Asynchronous serial data.
434 CHAPTER 11
FIGURE 11–43 The pin-out 28 A0 16550 D0 1
of the 16550 UART. 27 A1 D1 2
26 A2 D2 3
D3 4
12 CS0 D4 5
13 CS1 D5 6
D6 7
14 CS2 D7 8
35 MR SIN 10
22 RD SOUT 11
21 RD
19 WR BAUDOUT 15
18 WR RCLK 9
25 ADS
16 XIN RTS 32
17 XOUT CTS 36
DTR 33
24 TXRDY DSR 37
29 RXRDY DCD 38
23 DDIS 39
30 INTR RI
34
OUT 1 31
OUT 2
the 16650 are devoted to modem control: DSR (data set ready), DTR (data terminal ready),
CTS (clear-to-send), RTS (request-to-send), RI (ring indicator), and DCD (data carrier
detect). The modem is referred to as the data set and the 16550 is referred to as the data terminal.
16550 Pin Functions
A0, A1, A2 The address inputs are used to select an internal register for programming
ADS and also data transfer. See Table 11–5 for a list of each combination of the
BAUDOUT address inputs and the registers selected.
CS0, CS1, CS2 The address strobe input is used to latch the address lines and chip select
CTS lines. If not needed (as in the Intel system), connect this pin to ground. The
ADS pin is designed for use with Motorola microprocessors.
The baud out pin is where the clock signal generated by the baud rate gen-
erator from the transmitter section is made available. It is most often con-
nected to the RCLK input to generate a receiver clock that is equal to the
transmitter clock.
The chip select inputs must all be active to enable the 16550 UART.
The clear-to-send (if low) indicates that the modem or data set is ready to
exchange information. This pin is often used in a half-duplex system to turn
the line around.
TABLE 11–5 The register A2 A1 A0 Function
selected by A0, A1, and A2.
00 0 Receiver buffer (read) and transmitter holding (write)
00 1 Interrupt enable
01 0 Interrupt identification (read) and FIFO control (write)
01 1 Line control
10 0 Modem control
10 1 Line status
11 0 Modem status
11 1 Scratch
BASIC I/O INTERFACE 435
D0–D7 The data bus pins are connected to the microprocessor data bus.
DCD
DDIS The data carrier detect input is used by the modem to signal the 16550
that a carrier is present.
DSR
DTR The disable driver output becomes a logic 0 to indicate that the micro-
INTR processor is reading data from the UART. DDIS can be used to change the
direction of data flow through a buffer.
MR
OUT1, OUT2 Data set ready is an input to the 16550, indicating that the modem or data
RCLK set is ready to operate.
RD, RD
RI Data terminal ready is an output that indicates that the data terminal
RTS (16550) is ready to function.
SIN, SOUT
RXRDY Interrupt request is an output to the microprocessor used to request an
TXRDY interrupt (INTR = 1) whenever the 16550 has a receiver error, it has
WR, WR received data, and the transmitter is empty.
XIN, XOUT
Master reset initializes the 16550 and should be connected to the system
RESET signal.
User-defined output pins that can provide signals to a modem or any other
device as needed in a system.
Receiver clock is the clock input to the receiver section of the UART. This
input is always 16 times the desired receiver baud rate.
Read inputs (either may be used) cause data to be read from the register
specified by the address inputs to the UART.
The ring indicator input is placed at the logic 0 level by the modem to indi-
cate that the telephone is ringing.
Request-to-send is a signal to the modem indicating that the UART wishes
to send data.
These are the serial data pins. SIN accepts serial data and SOUT transmits
serial data.
Receiver ready is a signal used to transfer received data via DMA tech-
niques (see text).
Transmitter ready is a signal used to transfer transmitter data via DMA
techniques (see text).
Write (either may be used) connects to the microprocessor write signal to
transfer commands and data to the 16550.
These are the main clock connections. A crystal is connected across these
pins to form a crystal oscillator, or XIN is connected to an external timing
source.
Programming the 16550
Programming the 16550 is simple, although it may be slightly more involved when compared to
some of the other programmable interfaces described in this chapter. Programming is a two-part
process that includes the initialization dialog and operational dialog.
In the personal computer, which uses the 16550 or its programming equivalent, the I/O
port addresses are decoded at 3F8H through 3FFH for COM port 0 and 2F8H through 2FFH for
COM port 2. Although the examples in this section of the chapter are not written specifically for
the personal computer, they can be adapted by changing the port numbers to control the COM
ports on the PC.
436 CHAPTER 11
FIGURE 11–44 The contents Line Control Register
of the 16550 line control 7 6 54 32 1 0
register.
DL SB ST P PE S L1 L0
Data Length
00 = 5 bits
01= 6 bits
10 = 7 bits
11 = 8 bits
Stop bits
0 = 1 stop bit
1 = 1.5 or 2 stop bits
Parity enable
0 = no parity
1 = parity enabled
Parity type
0 = odd parity
1 = even parity
Stick bit
0 = stick parity off
1 = stick parity on
Send break
0 = no break sent
1 = send break on SOUT
Enable Divisor Latch
0 = divisor latch off
1 = enable divisor latch
Initializing the 16550. Initialization dialog, which occurs after a hardware or software reset,
consists of two parts: programming the line control register and the baud rate generator. The line
control register selects the number of data bits, number of stop bits, and parity (whether it’s even
or odd, or if parity is sent as a 1 or a 0). The baud rate generator is programmed with a divisor
that determines the baud rate of the transmitter section.
Figure 11–44 illustrates the line control register. The line control register is programmed
by outputting information to I/O port 011 (A2, A1, A0). The rightmost two bits of the line control
register select the number of transmitted data bits (5, 6, 7, or 8). The number of stop bits is
selected by S in the line control register. If S = 0, one stop bit is used; if S = 1, 1.5 stop bits are
used for five data bits, and two stop bits are used with six, seven, or eight data bits.
The next three bits are used together to send even or odd parity, to send no parity, or to send
a 1 or a 0 in the parity bit position. To send even or odd parity, the ST (stick) bit must be placed
at a logic 0 level, and parity enable must be a logic 1. The value of the parity bit then determines
even or odd parity. To send no parity (common in Internet connections), ST = 0 as well as the
parity enable bit. This sends and receives data without parity. Finally, if a 1 or a 0 must be
sent and received in the parity bit position for all data, ST = 1 with a 1 in parity enable. To send
a 1 in the parity bit position, place a 0 in the parity bit; to send a 0, place a 1 in the parity bit. (See
Table 11–6 for the operation of the parity and stick bits.)
TABLE 11–6 The operation
of the ST and parity bits. ST P PE Function
00 0 No parity
00 1 Odd parity
01 0 No parity
01 1 Even parity
10 0 Undefined
10 1 Send/receive 1
11 0 Undefined
11 1 Send/receive 0
BASIC I/O INTERFACE 437
TABLE 11–7 The divisor Baud Rate Divisor Value
used with the baud rate
generator for an 18.432 MHz 110 10,473
crystal illustrating common 300 3840
baud rates. 1200 920
2400 480
4800 240
9600 120
19,200 60
38,400 30
57,600 20
115,200 10
The remaining bits in the line control register are used to send a break and to select
programming for the baud rate divisor. If bit position 6 of the line control register is a logic 1, a
break is transmitted. As long as this bit is a 1, the break is sent from the SOUT pin. A break, by
definition, is at least two frames of logic 0 data. The software in the system is responsible for
timing the transmission of the break. To end the break, bit position 6 or the line control register
is returned to a logic 0 level. The baud rate divisor is only programmable when bit position 7 of
the line control register is a logic 1.
Programming the Baud Rate. The baud rate generator is programmed at I/O addresses 000 and
001 (A2, A1, A0). Port 000 is used to hold the least significant part of the 16-bit divisor and port
001 is used to hold the most significant part. The value used for the divisor depends on the exter-
nal clock or crystal frequency. Table 11–7 illustrates common baud rates obtainable if an 18.432
MHz crystal is used as a timing source. It also shows the divisor values programmed into the
baud rate generator to obtain these baud rates. The actual number programmed into the baud rate
generator causes it to produce a clock that is 16 times the desired baud rate. For example, if 240
is programmed into the baud rate divisor, the baud rate is (18.432 MHz ÷ 16) × 240 = 4800 baud.
Sample Initialization. Suppose that an asynchronous system requires seven data bits, odd par-
ity a baud rate of 9600, and one stop bit. Example 11–24 lists a procedure that initializes the
16550 to function in this manner. Figure 11–45 shows the interface to the 8088 microprocessor,
using a PLD to decode the 8-bit port addresses F0H through F7H. (The PLD program is not
shown.) Here port F3H accesses the line control register and F0H and F1H access the baud
rate divisor registers. The last part of Example 11–26 is described with the function of the FIFO
control register in the next few paragraphs.
EXAMPLE 11–26
;Initialization dialog for Figure 11–45
;Baud rate 9600, 7 data, odd parity, 1 stop
LINE EQU 0F3H
LSB EQU 0F0H
MSB EQU 0F1H
FIFO EQU 0F2H
INIT PROC NEAR
MOV AL,10001010B ;enable baud rate divisor
OUT LINE,AL
MOV AL,120 ;program baud 9600
OUT LSB,AL
438 CHAPTER 11
FIGURE 11–45 The 16550 VCC
interfaced to the 8088 micro- 10K
processor at ports
00F0H–00F7H. Data Bus (D0-D7)
IO/M 1 I1 01 19 U2
2 I2 02 18
A3 A0 28 A0 D1 1
A4 3 I3 03 17 A1 A1 D2 2
A5 4 I4 04 16 A2 27 A2 D3 3
A6 5 I5 05 15 26 D4 4
A7 RESET D5 5
A8 6 I6 06 14 RD 12 CS0 D6 6
A9 7 I7 07 13 WR CS1 D7 7
A10 13 CS2 D8 8
A11 8 I8 08 12 14
A12 9 I9 SIN 10
SOUT 11
A13 11 I10 35 MR
A14 22 RD BAUDOUT 15
A15 16L8 21 RD RCLK 9 Serial
19 WR data
18 WR RTS 32
25 ADS CTS 36
DTR 33
16 XIN DSR 37
17 XOUT DCD 38
39
18.432 MHz 24 TXRDY RI
RXRDY 34
29 OUT 1 31
23 DDIS OUT 2
INTR
30
16550
MOV AL,0
OUT MSB,AL
MOV AL,00001010B ;program 7 data, odd
OUT LINE,AL ;parity, 1 stop
MOV AL,00000111B ;enable transmitter and
OUT FIFO,AL ;receiver
RET
INIT ENDP
After the line control register and baud rate divisor are programmed into the 16550, it is
still not ready to function. After programming the line control register and baud rate, we still
must program the FIFO control register, which is at port F2H in the circuit of Figure 11–45.
Figure 11–46 illustrates the FIFO control register for the 16550. This register enables the
transmitter and receiver (bit 0 = 1), and clears the transmitter and receiver FIFOs. It also provides
control for the 16550 interrupts, which are discussed in Chapter 12. Notice that the last section of
Example 11–26 places a 7 into the FIFO control register. This enables the transmitter and
receiver, and clears both FIFOs. The 16550 is now ready to operate, but without interrupts.
Interrupts are automatically disabled when the MR (master reset) input is placed at a logic 1 by
the system RESET signal.
Sending Serial Data. Before serial data can be sent or received through the 16550, we need to
know the function of the line status register (see Figure 11–47). The line status register contains
information about error conditions and the state of the transmitter and receiver. This register is
tested before a byte is transmitted or can be received.
Suppose that a procedure (see Example 11–27) is written to transmit the contents of AH
to the 16550 and out through its serial data pin (SOUT). The TH bit is polled by software to
determine whether the transmitter is ready to receive data. This procedure uses the circuit of
Figure 11–45.
BASIC I/O INTERFACE 439
FIGURE 11–46 The FIFO FIFO Control Register
control register of the 16550 7 6 54 32 1 0
UART.
XMIT REVC
RT1 RT0 0 0 DMA EN
RST RST
FIFO Enable
0 = disable the FIFO
1 = enable the FIFO
Receiver Reset
0 = no effect
1 = reset receiver FIFO
Transmitter Reset
0 = no effect
1 = reset transmitter FIFO
DMA mode control
0 = set to function as 16450 UART
1 = FIFO mode
Receiver Trigger level
00 = 1 bytes in FIFO
01 = 4 bytes in FIFO
10 = 8 bytes in FIFO
11 = 14 bytes in FIFO
FIGURE 11–47 The con- Line Status Register
tents of the line status regis- 7 6 54 32 1 0
ter of the 16550 UART.
ER TE TH BI FE PE OE DR
Data Ready
0 = no data to read
1 = data in FIFO
Overrun Error
0 = no overrun error
1 = overrun error
Parity Error
0 = no parity error
1 = parity error
Framing Error
0 = no framing error
1 = framing error
Break Indicator
0 = no break
1 = break being received
Transmitter Holding Register
0 = wait for transmitter
1 = transmitter ready for data
Transmitter Empty
0 = transmitter not empty
1 = transmitter empty
Error
0 = no error
1 = at least one error in FIFO
EXAMPLE 11–27
;A procedure that transmits AH via the 16650 UART
LSTAT EQU 0F5H
DATA EQU 0F0H
SEND PROC NEAR USES AX
.REPEAT ;test the TH bit
IN AL,LSTAT
TEST AL,20H
.UNTIL !ZERO?
MOV AL,AH ;send data
OUT DATA,AL
RET
SEND ENDP
440 CHAPTER 11
11–6 Receiving Serial Data. To read received information from the 16550, test the DR bit of the line
status register. Example 11–28 lists a procedure that tests the DR bit to decide whether the 16550
has received any data. Upon the reception of data, the procedure tests for errors. If an error is
detected, the procedure returns with AL equal to an ASCII ‘?’. If no error has occurred, then the
procedure returns with AL equal to the received character.
EXAMPLE 11–28
;A procedure that receives data from the 16550 UART and
;returns it in AL.
LSTAT EQU 0F5H
DATA EQU 0F0H
REVC PROC NEAR
.REPEAT ;test DR bit
IN AL,LSTAT
TEST AL,1
.UNTIL !ZERO?
TEST AL,0EH ;test for any error
.IF ZERO? ;no error
IN AL,DATA ;any error
.ELSE
MOV AL,’?’
.ENDIF
RET
RECV ENDP
UART Errors. The types of errors detected by the 16550 are parity error, framing error, and over-
run error. A parity error indicates that the received data contain the wrong parity. A framing
error indicates that the start and stop bits are not in their proper places. An overrun error
indicates that data have overrun the internal receiver FIFO buffer. These errors should not occur
during normal operation. If a parity error occurs, it indicates that noise was encountered during
reception. A framing error occurs if the receiver is receiving data at an incorrect baud rate. An
overrun error occurs only if the software fails to read the data from the UART before the receiver
FIFO is full. This example does not test the BI (break indicator bit) for a break condition. Note
that a break is two consecutive frames of logic 0s on the SIN pin of the UART. The remaining reg-
isters, which are used for interrupt control and modem control, are developed in Chapter 12.
ANALOG-TO-DIGITAL (ADC) AND DIGITAL-TO-ANALOG (DAC) CONVERTERS
Analog-to-digital (ADC) and digital-to-analog (DAC) converters are used to interface the micro-
processor to the analog world. Many events that are monitored and controlled by the micro-
processor are analog events. These can range from monitoring all forms of events, even speech,
to controlling motors and like devices. In order to interface the microprocessor to these events,
we must have an understanding of the interface and control of the ADC and DAC, which convert
between analog and digital data.
The DAC0830 Digital-to-Analog Converter
A fairly common and low-cost digital-to-analog converter is the DAC0830 (a product of
National Semiconductor Corporation). This device is an 8-bit converter that transforms an 8-bit
binary number into an analog voltage. Other converters are available that convert from 10-, 12-,
BASIC I/O INTERFACE 441
FIGURE 11–48 The pin-out
of the DAC0830 digital-to-
analog converter.
or 16-bit binary numbers into analog voltages. The number of voltage steps generated by the
converter is equal to the number of binary input combinations. Therefore, an 8-bit converter gen-
erates 256 different voltage levels, a 10-bit converter generates 1024 levels, and so forth. The
DAC0830 is a medium-speed converter that transforms a digital input to an analog output in
approximately 1.0 μs.
Figure 11–48 illustrates the pin-out of the DAC0830. This device has a set of eight data bus
connections for the application of the digital input code, and a pair of analog outputs labeled
IOUT1 and IOUT2 that are designed as inputs to an external operational amplifier. Because this
is an 8-bit converter, its output step voltage is defined as -VREF (reference voltage), divided by
255. For example, if the reference voltage is -5.0 V, its output step voltage is +.0196 V. Note that
the output voltage is the opposite polarity of the reference voltage. If an input of 1001 00102 is
applied to the device, the output voltage will be the step voltage times 1001 00102, or, in this
case, +2.862 V. By changing the reference voltage to -5.1 V, the step voltage becomes +.02 V.
The step voltage is also often called the resolution of the converter.
Internal Structure of the DAC0830. Figure 11–49 illustrates the internal structure of the
DAC0830. Notice that this device contains two internal registers. The first is a holding register,
FIGURE 11–49 The internal
structure of the DAC0830.
442 CHAPTER 11
VCC
10K
1 CS VREF 8
2 WR1
WR2
18
AD0 7 DI0 RFB 9 4 +12
AD1 6 DI1
AD2 DI2 IOUT2 12 −6 Q1
5 IOUT1 11 + NPN
AD3 4 DI3 + MOTOR
AD4 DI4 741
16 −
AD5 15 DI5 7
AD6 14 DI6
13
AD7 DI7
WR 1 I1 O1 19 17 XFER
A0 2 I2 O2 18 19 ILE
A1 I3 O3
A2 3 I4 O4 17 10 DGND AGND 3
A3 4 I5 O5 16
A4 I6 O6 15 DAC0830
A5 5 I7 O7
A6 6 I8 O8 14
A7 I9 13
7 I10 12
IO/M 8
9 16L8
11
= digital ground = analog ground
FIGURE 11–50 A DAC0830 interfaced to the 8086 microprocessor at 8-bit I/O location 20H.
and the second connects to the R–2R internal ladder converter. The two latches allow one byte to
be held while another is converted. In many cases, we disable the first latch and only use the
second for entering data into the converter. This is accomplished by connecting a logic 1 to ILE
and a logic 0 to CS (chip select).
Both latches within the DAC0830 are transparent latches. That is, when the G input to the
latch is a logic 1, data pass through the latch, but when the G input becomes a logic 0, data are
latched or held. The converter has a reference input pin (VREF) that establishes the full-scale out-
put voltage. If -10 V is placed on VREF, the full-scale (111111112) output voltage is + 10 V. The
output of the R–2R ladder within the converter appears at IOUT1 and IOUT2. These outputs are
designed to be applied to an operational amplifier such as a 741 or similar device.
Connecting the DAC0830 to the Microprocessor. The DAC0830 is connected to the micro-
processor as illustrated in Figure 11–50. Here, a PLD is used to decode the DAC0830 at 8-bit I/O
port address 20H. Whenever an OUT 20H,AL instruction is executed, the contents of data bus
connections AD0–AD7 are passed to the converter within the DAC0830. The 741 operational
amplifier, along with the -12 V zener reference voltage, causes the full-scale output voltage to
equal +12 V. The output of the operational amplifier feeds a driver that powers a 12 V DC motor.
This driver is a Darlington amplifier for large motors. This example shows the converter driving
a motor, but other devices could be used as outputs.
The ADC080X Analog-to-Digital Converter
A common, low-cost ADC is the ADC080X, which belongs to a family of converters that are all
identical, except for accuracy. This device is compatible with a wide range of microprocessors
such as the Intel family. Although there are faster ADCs available and some have more resolution
than 8 bits, this device is ideal for many applications that do not require a high degree of accuracy.
The ADC080X requires up to 100 μs to convert an analog input voltage into a digital output code.
Figure 11–51 shows the pin-out of the ADC0804 converter (a product of National
Semiconductor Corporation). To operate the converter, the WR pin is pulsed with CS grounded
to start the conversion process. Because this converter requires a considerable amount of time for
the conversion, a pin labeled INTR signals the end of the conversion. Refer to Figure 11–52 for
BASIC I/O INTERFACE 443
FIGURE 11–51 The pin-out
of the ADC0804 analog-to-
digital converter.
FIGURE 11–52 The timing diagram for the ADC0804 analog-to-digital converter.
a timing diagram that shows the interaction of the control signals. As can be seen, we start the
converter with the WR pulse, we wait for INTR to return to a logic 0 level, and then we read the
data from the converter. If a time delay is used that allows at least 100 μs of time, then we don’t
need to test the INTR pin. Another option is to connect the INTR pin to an interrupt input, so that
when the conversion is complete, an interrupt occurs.
The Analog Input Signal. Before the ADC0804 can be connected to the microprocessor, its ana-
log inputs must be understood. There are two analog inputs to the ADC0804: VIN(+) and VIN(-).
These inputs are connected to an internal operational amplifier and are differential inputs,
as shown in Figure 11–53. The differential inputs are summed by the operational amplifier to
FIGURE 11–53 The analog
inputs to the ADC0804 con-
verter. (a) To sense a 0- to
+5.0 V input. (b) To sense an
input offset from ground.
444 CHAPTER 11
FIGURE 11–54 Connecting
the RC circuit to the CLK IN
and CLK R pins on the
ADC0804.
produce a signal for the internal analog-to-digital converter. Figure 11–53 shows a few ways to
use these differential inputs. The first way (see Figure 11–53a) uses a single input that can vary
between 0 V and +5.0 V. The second way (see Figure 11–53b) shows a variable voltage applied
to the VIN(-) pin, so the zero reference for VIN(+) can be adjusted.
Generating the Clock Signal. The ADC0804 requires a clock source for operation. The clock
can be an external clock applied to the CLK IN pin or it can be generated with an RC circuit. The
permissible range of clock frequencies is between 100 KHz and 1460 KHz. It is desirable to use
a frequency that is as close as possible to 1460 KHz, so conversion time is kept to a minimum.
If the clock is generated with an RC circuit, we use the CLK IN and CLK R pins connected
to an RC circuit, as illustrated in Figure 11–54. When this connection is in use, the clock
frequency is calculated by the following equation:
Fclk ϭ 1
1.1RC
Connecting the ADC0804 to the Microprocessor. The ADC0804 is interfaced to the 8086 micro-
processor, as illustrated in Figure 11–55. Note that the VREF signal is not attached to anything,
which is normal. Suppose that the ADC0804 is decoded at 8-bit I/O port address 40H for the data
and port address 42H for the INTR signal, and a procedure is required to start and read the data
from the ADC. This procedure is listed in Example 11–29. Notice that the INTR bit is polled and
if it becomes a logic 0, the procedure ends with AL, containing the converted digital code.
FIGURE 11–55 The U1 Analog input
ADC0804 interfaced to the
microprocessor. AD0 18 DB0 VI+ 6 1K
AD1 17 DB1 .001 uF
AD2 DB2 VI− 7
AD3 16 CLKR 19
AD4 15 DB3
AD5 DB4
AD6 14
AD7 13 DB5
RD 12 DB6
A0 11
A1 DB7
A2 4
A3 U2A 1 CS CLK< 9
A4 74LS125 2 VREF 8
A5 RD AGND
A6 32 3 WR
A7 5 INTR
IO/M
ADC0804
WR
1
1 I1 O1 19
2 I2 O2 18
3 I3 O3 17
4 I4 O4 16
15
5 I5 O5
6 I6 14
I7 O6 13
7 I8 12
8 I9 O7
9 I10 O8
11
16L8
BASIC I/O INTERFACE 445
EXAMPLE 11–29 ;test INTR
ADC PROC NEAR
OUT 40H,AL
.REPEAT
IN AL,42H
TEST AL,80H
.UNTIL ZERO?
IN AL,40H
RET
ADC ENDP
Using the ADC0804 and the DAC0830
This section of the text illustrates an example that uses both the ADC0804 and the DAC0830 to cap-
ture and replay audio signals or speech. In the past, we often used a speech synthesizer to generate
speech, but the quality of the speech was poor. For human quality speech, we can use the ADC0804
to capture an audio signal and store it in memory for later playback through the DAC0830.
Figure 11–56 illustrates the circuitry required to connect the ADC0804 at I/O ports 0700H
and 0702H. The DAC0830 is interfaced at I/O port 704H. These I/O ports are in the low bank of
VCC
10K +12
U1
1 CS VREF 8
2 WR1
18 WR2 RFB 9
IOUT2 12
7 DI0 IOUT1 11 4 6 Q1
6 DI1 2– SPEAKER
5 DI2 3 + 741
4 DI3
DI4 7
16 DI5
DI6
15 DI7
14
13
17 XFER
19 ILE
10 DGND AGND 3 –12
DAC0830
U2
AD0 18 DB0 VI+ 6 Amplifier
AD1 17 DB1
AD2 16 DB2 VI– 7 1K MICROPHONE
AD3 DB3 CLKR 19 .001
AD4 15 DB4
AD5 14 DB5
AD6 13 DB6
AD7 DB7
12
U3A
11
74LS125
1 CS CLK 4
32 2 RD VREF 9
3 WR AGND 8
5
INTR
ADC0804
U4 01 19 1
A0 1 I1 02 18 Analog Ground
A1 2 I2 03 17
A2 3 I3 04 16
A3 4 I4 05 15
A4 5 I5 06
A5 6 I6 07 14
A6 7 I7 08 13
A7 8 I8
I9 12
RD 9 I10
11
16L8
WR U5
A8 1 I1 01 19
A9 2 I2 02 18
A10 3 I3 03 17
A11 4 I4 04 16
A12 5 I5 05 15
A13 6 I6 06 14
A14 7 I7 07
A15 8 I8 08 13
I9
M/IO 9 I10 12
11
16L8
FIGURE 11–56 A circuit that stores speech and plays it back through the speaker.
446 CHAPTER 11
11–7 a 16-bit microprocessor such as the 8086 or 80386SX. The software used to run these converters
appears in Example 11–30. This software reads a 1-second burst of speech and then plays it back
10 times. One procedure reads the speech called READS and the other, called PLAYS, plays it
back. The speech is sampled and stored in a section of memory called WORDS. The sample rate
is chosen at 2048 samples per second, which renders acceptable-sounding speech.
EXAMPLE 11–30
;Software that records a second of speech and plays it back
;10 times.
;Assumes the clock frequency is 20 MHz on an 80386EX microprocessor
READS PROC NEAR USES ECX DX
MOV ECX,2048 ;count = 2048
MOV DX,700H ;address port 700H
.REPEAT
;start conversion
OUT DX,AL ;address status port
ADD DX,2 ;wait for converter
.REPEAT
;address data port
IN AL,DX ;get data
TEST AL,80H
.UNTIL ZERO? ;wait for 1/2048 sec
SUB DX,2
IN AL,DX
MOV WORDS[ECX-1]
CALL DELAY
.UNTILCXZ
RET
READS ENDP
PLAYS PROC NEAR USES DX ECX
MOV ECX,2048 ;count = 2048
MOV DX,704H ;address DAC
.REPEAT
MOV AL,WORDS[EAX-1]
OUT DX,AL ;send byte to DAC
CALL DELAY ;wait for 1/2048 sec
.UNTILCXZ
RET
PLAYS ENDP
DELAY PROC NEAR USES CX
MOV CX,888 ;waste 1/2048 sec
.REPEAT
.UNTILCXZ
RET
DELAY ENDP
SUMMARY
1. The 8086–Core2 microprocessors have two basic types of I/O instructions: IN and OUT.
The IN instruction inputs data from an external I/O device into either the AL (8-bit) or AX
(16-bit) register. The IN instruction is available as a fixed port instruction, a variable port
instruction, or a string instruction (80286–Pentium 4) INSB or INSW. The OUT instruction
BASIC I/O INTERFACE 447
outputs data from AL or AX to an external I/O device and is available as a fixed, variable, or
string instruction OUTSB or OUTSW. The fixed port instruction uses an 8-bit I/O port
address, while the variable and string I/O instructions use a 16-bit port number found in the
DX register.
2. Isolated I/O, sometimes called direct I/O, uses a separate map for the I/O space, freeing the
entire memory for use by the program. Isolated I/O uses the IN and OUT instructions to
transfer data between the I/O device and the microprocessor. The control structure of the iso-
lated I/O map uses IORC (I/O read control) and IOWC (I/O write control), plus the bank
selection signals BHE and BLE (A0 on the 8086 and 80286), to effect the I/O transfer. The
early 8086/8088 used the M/IO (IO/M) signal with RD and WR to generate the I/O control
signals.
3. Memory-mapped I/O uses a portion of the memory space for I/O transfers. This reduces the
amount of memory available, but it negates the need to use the IORC and IOWC signals for
I/O transfers. In addition, any instruction that addresses a memory location using any
addressing mode can be used to transfer data between the microprocessor and the I/O device
using memory-mapped I/O.
4. All input devices are buffered so that the I/O data are connected only to the data bus during
the execution of the IN instruction. The buffer is either built into a programmable peripheral
or located separately.
5. All output devices use a latch to capture output data during the execution of the OUT
instruction. This is necessary because data appear on the data bus for less than 100 ns for an
OUT instruction, and most output devices require the data for a longer time. In many cases,
the latch is built into the peripheral.
6. Handshaking or polling is the act of two independent devices synchronizing with a few
control lines. For example, the computer asks a printer if it is busy by inputting the BUSY
signal from the printer. If it isn’t busy, the computer outputs data to the printer and informs
the printer that data are available with a data strobe (DS) signal. This communication
between the computer and the printer is a handshake or a poll.
7. Interfaces are required for most switch-based input devices and for most output devices that
are not TTL-compatible.
8. The I/O port number appears on address bus connections A7–A0 for a fixed port I/O instruc-
tion and on A15–A0 for a variable port I/O instruction (note that A15–A8 contains zeros for
an 8-bit port). In both cases, address bits above A15 are undefined.
9. Because the 8086/80286/80386SX microprocessors contain a 16-bit data bus and the I/O
addresses reference byte-sized I/O locations, the I/O space is also organized in banks, as is
the memory system. In order to interface an 8-bit I/O device to the 16-bit data bus, we often
require separate write strobes (an upper and a lower) for I/O write operations. Likewise, the
80486 and Pentium–Core2 also have I/O arranged in banks.
10. The I/O port decoder is much like the memory address decoder, except instead of decoding
the entire address, the I/O port decoder decodes only a l6-bit address for variable port
instructions and often an 8-bit port number for fixed I/O instructions.
11. The 82C55 is a programmable peripheral interface (PIA) that has 24 I/O pins that are
programmable in two groups of 12 pins each (group A and group B). The 82C55 operates in
three modes: simple I/O (mode 0), strobed I/O (mode 1), and bidirectional I/O (mode 2).
When the 82C55 is interfaced to the 8086 operating at 8 MHz, we insert two wait states
because the speed of the microprocessor is faster than the 82C55 can handle.
12. The LCD display device requires a fair amount of software, but it displays ASCII-coded
information.
13. The 8254 is a programmable interval timer that contains three l6-bit counters that count
in binary or binary-coded decimal (BCD). Each counter is independent and operates in six
different modes: (1) events counter, (2) retriggerable, monostable multivibrator, (3) pulse
448 CHAPTER 11
11–8 generator, (4) square-wave generator, (5) software-triggered pulse generator, and (6) hardware-
triggered pulse generator.
14. The 16550 is a programmable communications interface, capable of receiving and transmitting
asynchronous serial data.
15. The DAC0830 is an 8-bit digital-to-analog converter that converts a digital signal to an analog
voltage within 1.0 μs.
16. The ADC0804 is an 8-bit analog-to-digital converter that converts an analog signal into a
digital signal within 100 μs.
QUESTIONS AND PROBLEMS
1. Explain which way the data flow for an IN and an OUT instruction.
2. Where is the I/O port number stored for a fixed I/O instruction?
3. Where is the I/O port number stored for a variable I/O instruction?
4. Where is the I/O port number stored for a string I/O instruction?
5. To which register are data input by the 16-bit IN instruction?
6. Describe the operation of the OUTSB instruction.
7. Describe the operation of the INSW instruction.
8. Contrast a memory-mapped I/O system with an isolated I/O system.
9. What is the basic input interface?
10. What is the basic output interface?
11. Explain the term handshaking as it applies to computer I/O systems.
12. An even-number I/O port address is found in the ____________ I/O bank in the 8086
microprocessor.
13. In the Pentium 4, what bank contains I/O port number 000AH?
14. How many I/O banks are found in the Pentium 4 or Core2 microprocessor?
15. Show the circuitry that generates the upper and lower I/O write strobes.
16. What is the purpose of a contact bounce eliminator?
17. Develop an interface to correctly drive a relay. The relay is 12 V and requires a coil current
of 150 mA.
18. Develop a relay coil driver that can control a 5.0 V relay that requires 60 mA of coil current.
19. Develop an I/O port decoder, using a 74ALS138, that generates low-bank I/O strobes, for a
16-bit microprocessor, for the following 8-bit I/O port addresses: 10H, 12H, 14H, 16H, 18H,
1AH, 1CH, and 1EH.
20. Develop an I/O port decoder, using a 74ALS138, that generates high-bank I/O strobes, for a
16-bit microprocessor, for the following 8-bit I/O port addresses: 11H, 13H, 15H, 17H, 19H,
1BH, 1DH, and 1FH.
21. Develop an I/O port decoder, using a PLD, that generates 16-bit I/O strobes for the following
16-bit I/O port addresses: 1000H–1001H, 1002H–103H, 1004H–1005H, 1006H–1007H,
1008H–1009H, 100AH–100BH, 100CH–100DH, and 100EH–100FH.
22. Develop an I/O port decoder, using a PLD, that generates the following low-bank I/O
strobes: 00A8H, 00B6H, and 00EEH.
23. Develop an I/O port decoder, using a PLD, that generates the following high-bank I/O
strobes: 300DH, 300BH, 1005H, and 1007H.
24. Why are both BHE and BLE (A0) ignored in a 16-bit port address decoder?
25. An 8-bit I/O device, located at I/O port address 0010H, is connected to which data bus
connections in a Pentium 4?
26. An 8-bit I/O device, located at I/O port address 100DH, is connected to which data bus
connections in a Core2 microprocessor?
BASIC I/O INTERFACE 449
27. The 82C55 has how many programmable I/O pin connections?
28. List the pins that belong to group A and to group B in the 82C55.
29. Which two 82C55 pins accomplish internal I/O port address selection?
30. The RD connection on the 82C55 is attached to which 8086 system control bus connection?
31. Using a PLD, interface an 82C55 to the 8086 microprocessor so that it functions at I/O
locations 0380H, 0382H, 0384H, and 0386H.
32. When the 82C55 is reset, its I/O ports are all initialized as ____________.
33. What three modes of operation are available to the 82C55?
34. What is the purpose of the STB signal in strobed input operation of the 82C55?
35. Develop a time delay procedure for the 2.0 GHz Pentium 4 that waits for 80 μs.
36. Develop a time delay procedure for the 3.0 GHz Pentium 4 that waits for 12 ms.
37. Explain the operation of a simple four-coil stepper motor.
38. What sets the IBF pin in strobed input operation of the 82C55?
39. Write the software required to place a logic 1 on the PC7 pin of the 82C55 during strobed
input operation.
40. How is the interrupt request pin (INTR) enabled in the strobed input mode of operation of
the 82C55?
41. In strobed output operation of the 82C55, what is the purpose of the ACK signal?
42. What clears the OBF signal in strobed output operation of the 82C55?
43. Write the software required to decide whether PC4 is a logic 1 when the 82C55 is operated
in the strobed output mode.
44. Which group of pins is used during bidirectional operation of the 82C55?
45. Which pins are general-purpose I/O pins during mode 2 operation of the 82C55?
46. Describe how the display is cleared in the LCD display.
47. How is a display position selected in the LCD display?
48. Write a short procedure that places an ASCII null string in display position 6 on the LCD
display.
49. How is the busy flag tested in the LCD display?
50. What changes must be made to Figure 11–25 so that it functions with a keyboard matrix that
contains three rows and five columns?
51. What time is usually used to debounce a keyboard?
52. Develop the interface to a three- by four-key telephone-style keypad. You will need to use a
lookup table to convert to the proper key code.
53. The 8254 interval timer functions from DC to ____________ Hz.
54. Each counter in the 8254 functions in how many different modes?
55. Interface an 8254 to function at I/O port addresses XX10H, XX12H, XX14H, and XX16H.
56. Write the software that programs counter 2 to generate an 80 KHz square wave if the CLK
input to counter 2 is 8 MHz.
57. What number is programmed in an 8254 counter to count 300 events?
58. If a 16-bit count is programmed into the 8254, which byte of the count is programmed first?
59. Explain how the read-back control word functions in the 8254.
60. Program counter 1 of the 8254 so that it generates a continuous series of pulses that have a
high time of 100 μs and a low time of 1 μs. Make sure to indicate the CLK frequency
required for this task.
61. Why does a 50% duty cycle cause the motor to stand still in the motor speed and direction
control circuit presented in this chapter?
62. What is asynchronous serial data?
63. What is baud rate?
64. Program the 16550 for operation using six data bits, even parity, one stop bit, and a baud
rate of 19,200 using a 18.432 MHz clock. (Assume that the I/O ports are numbered 20H
and 22H.)
450 CHAPTER 11
65. If the 16550 is to generate a serial signal at a baud rate of 2400 baud and the baud rate divi-
sor is programmed for 16, what is the frequency of the signal?
66. Describe the following terms: simplex, half-duplex, and full-duplex.
67. How is the 16550 reset?
68. Write a procedure for the 16550 that transmits 16 bytes from a small buffer in the data
segment address (DS is loaded externally) by SI (SI is loaded externally).
69. The DAC0830 converts an 8-bit digital input to an analog output in approximately___________.
70. What is the step voltage at the output of the DAC0830 if the reference voltage is -2.55 V?
71. Interface a DAC0830 to the 8086 so that it operates at I/O port 400H.
72. Develop a program for the interface of question 71 so the DAC0830 generates a triangular
voltage wave-form. The frequency of this wave-form must be approximately 100 Hz.
73. The ADC080X requires approximately ____________ to convert an analog voltage into a
digital code.
74. What is the purpose of the INTR pin on the ADC080X?
75. The WR pin on the ADC080X is used for what purpose?
76. Interface an ADC080X at I/O port 0260H for data and 0270H to test the INTR pin.
77. Develop a program for the ADC080X in question 76 so that it reads an input voltage once
per 100 ms and stores the results in a memory array that is 100H bytes long.
78. Rewrite Example 11–29 using C++ with inline assembly code.
CHAPTER 12
Interrupts
12–1 INTRODUCTION
In this chapter, the coverage of basic I/O and programmable peripheral interfaces is expanded
by examining a technique called interrupt-processed I/O. An interrupt is a hardware-initiated
procedure that interrupts whatever program is currently executing. This chapter provides
examples and a detailed explanation of the interrupt structure of the entire Intel family of
microprocessors.
CHAPTER OBJECTIVES
Upon completion of this chapter, you will be able to:
1. Explain the interrupt structure of the Intel family of microprocessors.
2. Explain the operation of software interrupt instructions INT, INTO, INT 3, and BOUND.
3. Explain how the interrupt enable flag bit (IF) modifies the interrupt structure.
4. Describe the function of the trap interrupt flag bit (TF) and the operation of trap-generated
tracing.
5. Develop interrupt-service procedures that control lower-speed, external peripheral devices.
6. Expand the interrupt structure of the microprocessor by using the 82S9A programmable
interrupt controller and other techniques.
7. Explain the purpose and operation of a real-time clock.
BASIC INTERRUPT PROCESSING
In this section, we discuss the function of an interrupt in a microprocessor-based system, and the
structure and features of interrupts available to the Intel family of microprocessors.
The Purpose of Interrupts
Interrupts are particularly useful when interfacing I/O devices that provide or require data at rel-
atively low data transfer rates. In Chapter 11, for instance, we showed a keyboard example using
strobed input operation of the 82C55. In that example, software polled the 82C55 and its IBF bit
to decide whether data were available from the keyboard. If the person using the keyboard typed
451
452 CHAPTER 12
FIGURE 12–1 A time line
that indicates interrupt usage
in a typical system.
one character per second, the software for the 82C55 waited an entire second between each key-
stroke for the person to type another key. This process was such a tremendous waste of time that
designers developed another process, interrupt processing, to handle this situation.
Unlike the polling technique, interrupt processing allows the microprocessor to execute
other software while the keyboard operator is thinking about what key to type next. As soon as a
key is pressed, the keyboard encoder debounces the switch and puts out one pulse that interrupts
the microprocessor. The microprocessor executes other software until the key is actually pressed,
when it reads a key and returns to the program that was interrupted. As a result, the micro-
processor can print reports or complete any other task while the operator is typing a document
and thinking about what to type next.
Figure 12–1 shows a time line that indicates a typist typing data on a keyboard, a printer
removing data from the memory, and a program executing. The program is the main program
that is interrupted for each keystroke and each character that is to print on the printer. Note that
the keyboard interrupt service procedure, called by the keyboard interrupt, and the printer inter-
rupt service procedure each take little time to execute.
Interrupts
The interrupts of the entire Intel family of microprocessors include two hardware pins that
request interrupts (INTR and NMI), and one hardware pin (INTA) that acknowledges the inter-
rupt requested through INTR. In addition to the pins, the microprocessor also has software inter-
rupts INT, INTO, INT 3, and BOUND. Two flag bits, IF (interrupt flag) and TF (trap flag), are
also used with the interrupt structure and a special return instruction, IRET (or IRETD in the
80386, 80486, or Pentium–Pentium 4).
Interrupt Vectors. The interrupt vectors and vector table are crucial to an understanding of
hardware and software interrupts. The interrupt vector table is located in the first 1024 bytes of
memory at addresses 000000H–0003FFH. It contains 256 different four-byte interrupt vectors.
An interrupt vector contains the address (segment and offset) of the interrupt service procedure.
Figure 12–2 illustrates the interrupt vector table for the microprocessor. The first five inter-
rupt vectors are identical in all Intel microprocessor family members, from the 8086 to the
Pentium. Other interrupt vectors exist for the 80286 that are upward-compatible to the 80386,
80486, and Pentium–Core2, but not downward-compatible to the 8086 or 8088. Intel reserves the
first 32 interrupt vectors for their use in various microprocessor family members. The last 224
vectors are available as user interrupt vectors. Each vector is four bytes long in the real mode and
contains the starting address of the interrupt service procedure. The first two bytes of the vector
contain the offset address and the last two bytes contain the segment address.
The following list describes the function of each dedicated interrupt in the microprocessor:
TYPE 0 The divide error whenever the result from a division overflows or an attempt is
TYPE 1 made to divide by zero.
Single-step or trap occurs after the execution of each instruction if the trap (TF)
flag bit is set. Upon accepting this interrupt, the TF bit is cleared so that the
INTERRUPTS 453
FIGURE 12–2 (a) The inter- Type 32 255
rupt vector table for the micro- User interrupt vectors
processor and (b) the con-
tents of an interrupt Type 14 31
vector. Reserved
080H
Type 16
040H Coprocessor error
Type 15
03CH Unassigned
Type 14
038H Page fault
Type 13
034H General protection
Type 12
030H Stack segment overrun
Type 11
02CH Segment not present
Type 10
028H Invalid task state segment
Type 9
024H Coprocessor segment overrun
Type 8
020H Double fault
Type 7
01CH Coprocessor not available
Type 6
018H Undefined opcode
Type 5
014H BOUND
Type 4
010H Overflow (INTO)
Type 3
00CH 1-byte breakpoint
Type 2 Any interrupt vector
3 Segment (high)
008H NMI pin 2 Segment (low)
1 Offset (high)
Type 1 0 Offset (low)
004H Single-step (b)
Type 0
000H Divide error
(a)
TYPE 2 interrupt service procedure executes at full speed. (More detail is provided about
this interrupt later in this section of the chapter.)
The non-maskable interrupt occurs when a logic 1 is placed on the NMI input
pin to the microprocessor. This input is non-maskable, which means that it
cannot be disabled.
454 CHAPTER 12
TYPE 3 A special one-byte instruction (INT 3) that uses this vector to access its interrupt-
TYPE 4 service procedure. The INT 3 instruction is often used to store a breakpoint in a
TYPE 5 program for debugging.
TYPE 6 Overflow is a special vector used with the INTO instruction. The INTO
TYPE 7 instruction interrupts the program if an overflow condition exists, as reflected
TYPE 8 by the overflow flag (OF).
TYPE 9
TYPE 10 The BOUND instruction compares a register with boundaries stored in the
TYPE 11 memory. If the contents of the register are greater than or equal to the first word
TYPE 12 in memory and less than or equal to the second word, no interrupt occurs because
TYPE 13 the contents of the register are within bounds. If the contents of the register are
out of bounds, a type 5 interrupt ensues.
TYPE 14
TYPE 16 An invalid opcode interrupt occurs whenever an undefined opcode is encountered
in a program.
The coprocessor not available interrupt occurs when a coprocessor is not found
in the system, as dictated by the machine status word (MSW or CR0)
coprocessor control bits. If an ESC or WAIT instruction executes and the
coprocessor is not found, a type 7 exception or interrupt occurs.
A double fault interrupt is activated whenever two separate interrupts occur
during the same instruction.
The coprocessor segment overrun occurs if the ESC instruction (coprocessor
opcode) memory operand extends beyond offset address FFFFH in real mode.
An invalid task state segment interrupt occurs in the protected mode if the TSS
is invalid because the segment limit field is not 002BH or higher. In most cases,
this is caused because the TSS is not initialized.
The segment not present interrupt occurs when the protected mode P bit (P = 0)
in a descriptor indicates that the segment is not present or not valid.
A stack segment overrun occurs if the stack segment is not present (P = 0) in
the protected mode or if the limit of the stack segment is exceeded.
The general protection fault occurs for most protection violations in the
80286–Core2 protected mode system. (These errors occur in Windows as general
protection faults.) A list of these protection violations follows:
(a) Descriptor table limit exceeded
(b) Privilege rules violated
(c) Invalid descriptor segment type loaded
(d) Write to code segment that is protected
(e) Read from execute-only code segment
(f) Write to read-only data segment
(g) Segment limit exceeded
(h) CPL = IOPL when executing CTS, HLT, LGDT, LIDT, LLDT, LMSW,
or LTR
(i) CPL > IOPL when executing CLI, IN, INS, LOCK, OUT, OUTS,
and STI
Page fault interrupts occur for any page fault memory or code access in the
80386, 80486, and Pentium–Core2 microprocessors.
Coprocessor error takes effect whenever a coprocessor error (ERROR = 0)
occurs for the ESCape or WAIT instructions for the 80386, 80486, and
Pentium–Core2 microprocessors only.
INTERRUPTS 455
TYPE 17 Alignment checks indicate that word and doubleword data are addressed at an
TYPE 18 odd memory location (or an incorrect location, in the case of a doubleword). This
interrupt is active in the 80486 and Pentium–Core2 microprocessors.
A machine check activates a system memory management mode interrupt in the
Pentium–Core2 microprocessors.
Interrupt Instructions: BOUND, INTO, INT, INT 3, and IRET
Of the five software interrupt instructions available to the microprocessor, INT and INT 3 are very
similar, BOUND and INTO are conditional, and IRET is a special interrupt return instruction.
The BOUND instruction, which has two operands, compares a register with two words of
memory data. For example, if the instruction BOUND AX,DATA is executed, AX is compared
with the contents of DATA and DATA+1 and also with DATA+2 and DATA+3. If AX is less than
the contents of DATA and DATA+1, a type 5 interrupt occurs. If AX is greater than DATA+2 and
DATA+3, a type 5 interrupt occurs. If AX is within the bounds of these two memory words, no
interrupt occurs.
The INTO instruction checks or tests the overflow flag (O). If O = 1, the INTO instruction
calls the procedure whose address is stored in interrupt vector type number 4. If O = 0, then the
INTO instruction performs no operation and the next sequential instruction in the program executes.
The INT n instruction calls the interrupt service procedure that begins at the address repre-
sented in vector number n. For example, an INT 80H or INT 128 calls the interrupt service pro-
cedure whose address is stored in vector type number 80H (000200H–00203H). To determine
the vector address, just multiply the vector type number (n) by 4, which gives the beginning
address of the four-byte long interrupt vector. For example, INT 5 = 4 × 5 or 20 (14H). The vec-
tor for INT 5 begins at address 0014H and continues to 0017H. Each INT instruction is stored in
two bytes of memory: The first byte contains the opcode, and the second byte contains the inter-
rupt type number. The only exception to this is the INT 3 instruction, a one-byte instruction. The
INT 3 instruction is often used as a breakpoint-interrupt because it is easy to insert a one-byte
instruction into a program. Breakpoints are often used to debug faulty software.
The IRET instruction is a special return instruction used to return for both software and
hardware interrupts. The IRET instruction is much like a far RET, because it retrieves the return
address from the stack. It is unlike the near return because it also retrieves a copy of the flag reg-
ister from the stack. An IRET instruction removes six bytes from the stack: two for the IP, two
for the CS, and two for the flags.
In the 80386–Core2, there is also an IRETD instruction because these microprocessors can
push the EFLAG register (32 bits) on the stack, as well as the 32-bit EIP in the protected mode
and 16-bit code segment register. If operated in the real mode, we use the IRET instruction with
the 80386–Core2 microprocessors. If the Pentium 4 operates in 64-bit mode, an IRETQ instruc-
tion is used to return from an interrupt. The IRETQ instruction pops the EFLAG register into
RFLAGS and also the 64-bit return address is placed into the RIP register.
The Operation of a Real Mode Interrupt
When the microprocessor completes executing the current instruction, it determines whether an
interrupt is active by checking (1) instruction executions, (2) single-step, (3) NMI, (4) coproces-
sor segment overrun, (5) INTR, and (6) INT instructions in the order presented. If one or more of
these interrupt conditions are present, the following sequence of events occurs:
1. The contents of the flag register are pushed onto the stack.
2. Both the interrupt (IF) and trap (TF) flags are cleared. This disables the INTR pin and the
trap or single-step feature.
3. The contents of the code segment register (CS) are pushed onto the stack.
456 CHAPTER 12
4. The contents of the instruction pointer (IP) are pushed onto the stack.
5. The interrupt vector contents are fetched, and then placed into both IP and CS so that the
next instruction executes at the interrupt service procedure addressed by the vector.
Whenever an interrupt is accepted, the microprocessor stacks the contents of the flag reg-
ister, CS and IP; clears both IF and TF; and jumps to the procedure addressed by the interrupt
vector. After the flags are pushed onto the stack, IF and TF are cleared. These flags are returned
to the state prior to the interrupt when the IRET instruction is encountered at the end of the inter-
rupt service procedure. Therefore, if interrupts were enabled prior to the interrupt service proce-
dure, they are automatically re-enabled by the IRET instruction at the end of the procedure.
The return address (in CS and IP) is pushed onto the stack during the interrupt. Sometimes
the return address points to the next instruction in the program; sometimes it points to the
instruction or point in the program where the interrupt occurred. Interrupt type numbers 0, 5, 6,
7, 8, 10, 11, 12, and 13 push a return address that points to the offending instruction, instead of
to the next instruction in the program. This allows the interrupt service procedure to possibly
retry the instruction in certain error cases.
Some of the protected mode interrupts (types 8, 10, 11, 12, and 13) place an error code on
the stack following the return address. The error code identifies the selector that caused the inter-
rupt. In cases where no selector is involved, the error code is a 0.
Operation of a Protected Mode Interrupt
In the protected mode, interrupts have exactly the same assignments as in the real mode, but the
interrupt vector table is different. In place of interrupt vectors, protected mode uses a set of 256
interrupt descriptors that are stored in an interrupt descriptor table (IDT). The interrupt descrip-
tor table is 256 × 8 (2K) bytes long, with each descriptor containing eight bytes. The interrupt
descriptor table is located at any memory location in the system by the interrupt descriptor table
address register (IDTR).
Each entry in the IDT contains the address of the interrupt service procedure in the form of
a segment selector and a 32-bit offset address. It also contains the P bit (present) and DPL bits to
describe the privilege level of the interrupt. Figure 12–3 shows the contents of the interrupt
descriptor.
Real mode interrupt vectors can be converted into protected mode interrupts by copying
the interrupt procedure addresses from the interrupt vector table and converting them to 32-bit
offset addresses that are stored in the interrupt descriptors. A single selector and segment
descriptor can be placed in the global descriptor table that identifies the first 1M byte of memory
as the interrupt segment.
Other than the IDT and interrupt descriptors, the protected mode interrupt functions like
the real mode interrupt. We return from both interrupts by using the IRET or IRETD instruction.
The only difference is that in protected mode the microprocessor accesses the IDT instead of the
FIGURE 12–3 The pro- 7 Offset (A31–A16) 6
tected mode interrupt 4
descriptor.
5 P DPL 0 1 1 1 0 00H
3 Segment selector 2
1 Offset (A15–A0) 0
INTERRUPTS 457
FIGURE 12–4 The flag
register. (Courtesy of Intel
Corporation.)
interrupt vector table. In the 64-bit mode of the Pentium 4 and Core2, an IRETQ must be used to
return from an interrupt. This is one reason why there are different drivers and operating systems
for the 64-bit mode.
Interrupt Flag Bits
The interrupt flag (IF) and the trap flag (TF) are both cleared after the contents of the flag regis-
ter are stacked during an interrupt. Figure 12–4 illustrates the contents of the flag register and the
location of IF and TF. When the IF bit is set, it allows the INTR pin to cause an interrupt; when
the IF bit is cleared, it prevents the INTR pin from causing an interrupt. When TF = 1, it causes
a trap interrupt (type number 1) to occur after each instruction executes. This is why we often
call trap a single-step. When TF = 0, normal program execution occurs. This flag bit allows
debugging, as explained in Chapters 17 through 19, which detail the 80386–Core2.
The interrupt flag is set and cleared by the STI and CLI instructions, respectively. There
are no special instructions that set or clear the trap flag. Example 12–1 shows an interrupt service
procedure that turns tracing on by setting the trap flag bit on the stack from inside the procedure.
Example 12–2 shows an interrupt service procedure that turns tracing off by clearing the trap flag
on the stack from within the procedure.
EXAMPLE 12–1
;A procedure that sets the TRAP flag bit to enable trapping
TRON PROC FAR USES AX BP
MOV BP,SP ;get SP
MOV AX[BP+8] ;retrieve flags from stack
OR AH,1 ;set trap flag
MOV [BP+8],AX
IRET
TRON ENDP
EXAMPLE 12–2
;A procedure that clears the TRAP flag to disable trapping
TROFF PROC FAR USES AX BP
MOV BP,SP ;get SP
MOV AX,[BP+8] ;retrieve flags from stack
AND AH,0FEH ;clear trap flag
MOV [BP+8],AX
IRET
TROFF ENDP
In both examples, the flag register is retrieved from the stack by using the BP register,
which, by default, addresses the stack segment. After the flags are retrieved, the TF bit is either
set (TRON) or clears (TROFF) before returning from the interrupt service procedure. The IRET
instruction restores the flag register with the new state of the trap flag.
Trace Procedure. Assuming that TRON is accessed by an INT 40H instruction and TROFF is
accessed by an INT 41H instruction, Example 12–3 traces through a program immediately fol-
lowing the INT 40H instruction. The interrupt service procedure illustrated in Example 12–3
458 CHAPTER 12
responds to interrupt type number 1 or a trap interrupt. Each time that a trap occurs—after each
instruction executes following INT 40H—the TRACE procedure stores the contents of all the
32-bit microprocessor registers in an array called REGS. This provides a register trace of all the
instructions between the INT 40H (TRON) and INT 41H (TROFF) if the contents of the registers
stored in the array are saved.
EXAMPLE 12–3 ;space for registers
REGS DD 8 DUP(?)
TRACE PROC FAR USES EBX
MOV EBX,OFFSET REGS
MOV [EBX],EAX ;save EAX
POP EAX
PUSH EAX
MOV [EBX+4],EAX ;save EBX
MOV [EBX+8],ECX ;save ECX
MOV [EBX+12],EDX ;save EDX
MOV [EBX+16],ESP ;save ESP
MOV [EBX+20],EBP ;save EBP
MOV [EBX+24],ESI ;save ESI
MOV [EBX+28],EDI ;save EDI
IRET
TRACE ENDP
Storing an Interrupt Vector in the Vector Table
In order to install an interrupt vector—sometimes called a hook—the assembler must address
absolute memory. Example 12–4 shows how a new vector is added to the interrupt vector table
by using the assembler and a DOS function call. Here, the vector for INT 40H, for interrupt pro-
cedure NEW40, is installed in memory at real mode vector location 100H–103H. The first thing
accomplished by the procedure is that the old interrupt vector contents are saved in case we need
to uninstall the vector. This step can be skipped if there is no need to uninstall the interrupt.
The function AX = 3100H for INT 21H, the DOS access function, installs the NEW40 pro-
cedure in memory until the computer is shut off. The number in DX is the length of the software
in paragraphs (16-byte chunks). Refer to Appendix A for more detail about this DOS function.
Notice that the INT40 function has an IRET instruction before ENDP. This is required
because the assembler has no way of determining if the FAR procedure is an interrupt procedure.
Normal FAR procedures do not need a return instruction, but an interrupt procedure does need an
IRET. Interrupts must always be defined as FAR.
EXAMPLE 12–4
.MODEL TINY START
.CODE ? ;space for old vector
.STARTUP
JMP
OLD DD
NEW40 PROC FAR ;must be FAR
;
;Interrupt software for INT 40H
;
IRET ;must have an IRET
NEW40 ENDP
INTERRUPTS 459
;start installation
START:
MOV AX,0 ;address segment 0000H
MOV
MOV DS,AX
MOV
MOV AX,DS:[100H] ;get INT 40H offset
MOV
MOV WORD PTR CS:OLD,AX ;save it
MOV
MOV AX,DS:[102H] ;get INT 40H segment
SHR
INC WORD PTR CS:OLD+2,AX ;save it
MOV
INT DS:[100H],OFFSET NEW40 ;save offset
DS:[102H],CS ;save segment
DX,OFFSET START
DX,4
DX
AX,3100H ;make NEW40 resident
21H
END
12–2 HARDWARE INTERRUPTS
The microprocessor has two hardware interrupt inputs: non-maskable interrupt (NMI) and inter-
rupt request (INTR). Whenever the NMI input is activated, a type 2 interrupt occurs because
NMI is internally decoded. The INTR input must be externally decoded to select a vector. Any
interrupt vector can be chosen for the INTR pin, but we usually use an interrupt type number
between 20H and FFH. Intel has reserved interrupts 00H through 1FH for internal and future
expansion. The INTA signal is also an interrupt pin on the microprocessor, but it is an output that
is used in response to the INTR input to apply a vector type number to the data bus connections
D7–D0. Figure 12–5 shows the three user interrupt connections on the microprocessor.
The non-maskable interrupt (NMI) is an edge-triggered input that requests an interrupt
on the positive edge (0-to-1 transition). After a positive edge, the NMI pin must remain a logic 1
until it is recognized by the microprocessor. Note that before the positive edge is recognized, the
NMI pin must be a logic 0 for at least two clocking periods.
The NMI input is often used for parity errors and other major system faults, such as power
failures. Power failures are easily detected by monitoring the AC power line and causing an NMI
interrupt whenever AC power drops out. In response to this type of interrupt, the microprocessor
stores all of the internal register in a battery-backed-up memory or an EEPROM. Figure 12–6
shows a power failure detection circuit that provides a logic 1 to the NMI input whenever AC
power is interrupted.
FIGURE 12–5 The interrupt
pins on all versions of the
Intel microprocessor.
460 CHAPTER 12
FIGURE 12–6 A power failure detection circuit.
In this circuit, an optical isolator provides isolation from the AC power line. The output of
the isolator is shaped by a Schmitt-trigger inverter that provides a 60 Hz pulse to the trigger input
of the 74LS122 retriggerable, monostable multivibrator. The values of R and C are chosen so
that the 74LS122 has an active pulse width of 33 ms or 2 AC input periods. Because the 74LS122
is retriggerable, as long as AC power is applied, the Q output remains triggered at a logic 1 and
Q remains a logic 0.
If the AC power fails, the 74LS122 no longer receives trigger pulses from the 74ALS14, which
means that Q becomes a logic 0 and Q becomes a logic 1, interrupting the microprocessor through the
NMI pin. The interrupt service procedure, not shown here, stores the contents of all internal registers
and other data into a battery-backed-up memory. This system assumes that the system power supply
has a large enough filter capacitor to provide energy for at least 75 ms after the AC power ceases.
Figure 12–7 shows a circuit that supplies power to a memory after the DC power fails.
Here, diodes are used to switch supply voltages from the DC power supply to the battery. The
diodes used are standard silicon diodes because the power supply to this memory circuit is ele-
vated above +5.0 V to +5.7 V. The resistor is used to trickle-charge the battery, which is either
NiCAD, lithium, or a gel cell.
When DC power fails, the battery provides a reduced voltage to the VCC connection on the
memory device. Most memory devices will retain data with VCC voltages as low as 1.5 V, so the
battery voltage does not need to be +5.0 V. The WR pin is pulled to VCC during a power outage,
so no data will be written to the memory.
FIGURE 12–7 A battery-
backed-up memory system
using a NiCad, lithium, or
gel cell.
INTERRUPTS 461
INTR
INTA
LOCK
INTA
D7 – D0
* Vector number
FIGURE 12–8 The timing of the INTR input and INTA output. *This portion of the data bus
is ignored and usually contains the vector number.
INTR and INTA
The interrupt request input (INTR) is level-sensitive, which means that it must be held at a logic
1 level until it is recognized. The INTR pin is set by an external event and cleared inside the
interrupt service procedure. This input is automatically disabled once it is accepted by the micro-
processor and re-enabled by the IRET instruction at the end of the interrupt service procedure.
The 80386–Core2 use the IRETD instruction in the protected mode of operation. In the 64-bit
mode, an IRETQ is used in protected mode.
The microprocessor responds to the INTR input by pulsing the INTA output in anticipation
of receiving an interrupt vector type number on data bus connections D7–D0. Figure 12–8 shows
the timing diagram for the INTR and INTA pins of the microprocessor. There are two INTA
pulses generated by the system that are used to insert the vector type number on the data bus.
Figure 12–9 illustrates a simple circuit that applies interrupt vector type number FFH to
the data bus in response to an INTR. Notice that the INTA pin is not connected in this circuit.
FIGURE 12–9 A simple
method for generating inter-
rupt vector type number FFH
in response to INTR.
462 CHAPTER 12
FIGURE 12–10 A circuit
that applies any interrupt vec-
tor type number in response
to INTA. Here the circuit is
applying type number 80H.
Because resistors are used to pull the data bus connections (D0–D7) high, the microprocessor
automatically sees vector type number FFH in response to the INTR input. This is the least
expensive way to implement the INTR pin on the microprocessor.
Using a Three-State Buffer for INTA. Figure 12–10 shows how interrupt vector type number 80H
is applied to the data bus (D0–D7) in response to an INTR. In response to the INTR, the micro-
processor outputs the INTA that is used to enable a 74ALS244 three-state octal buffer. The octal
buffer applies the interrupt vector type number to the data bus in response to the INTA pulse. The
vector type number is easily changed with the DIP switches that are shown in this illustration.
Making the INTR Input Edge-Triggered. Often, we need an edge-triggered input instead of a
level-sensitive input. The INTR input can be converted to an edge-triggered input by using a
D-type flip-flop, as illustrated in Figure 12–11. Here, the clock input becomes an edge-triggered
interrupt request input, and the clear input is used to clear the request when the INTA signal is
output by the microprocessor. The RESET signal initially clears the flip-flop so that no interrupt
is requested when the system is first powered.
The 82C55 Keyboard Interrupt
The keyboard example presented in Chapter 11 provides a simple example of the operation of the
INTR input and an interrupt. Figure 12–12 illustrates the interconnection of the 82C55 with the
microprocessor and the keyboard. It also shows how a 74ALS244 octal buffer is used to provide
FIGURE 12–11 Converting
INTR into an edge-triggered
interrupt request input.
FIGURE 12–12 An 82C55 interfaced to a keyboard from the microprocessor system using interrupt vector 40H.
463
464 CHAPTER 12
the microprocessor with interrupt vector type number 40H in response to the keyboard interrupt
during the INTA pulse.
The 82C55 is decoded at 80386SX I/O port address 0500H, 0502H, 0504H, and 0506H by
a PLD (the program is not illustrated). The 82C55 is operated in mode 1 (strobed input mode), so
whenever a key is typed, the INTR output (PC3) becomes a logic 1 and requests an interrupt
through the INTR pin on the microprocessor. The INTR pin remains high until the ASCII data
are read from port A. In other words, every time a key is typed, the 82C55 requests a type 40H
interrupt through the INTR pin. The DAV signal from the keyboard causes data to be latched
into port A and causes INTR to become a logic 1.
Example 12–5 illustrates the interrupt service procedure for the keyboard. It is very impor-
tant that all registers affected by an interrupt are saved before they are used. In the software
required to initialize the 82C55 (not shown here), the FIFO is initialized so that both pointers are
equal, the INTR request pin is enabled through the INTE bit inside the 82C55, and the mode of
operation is programmed.
EXAMPLE 12–5
;An interrupt service procedure that reads a key from
;the keyboard depicted in Figure 12-12.
PORTA EQU 500H
CNTR EQU 506H
FIFO DB 256 DUP(?) ;queue
INP DD FIFO ;input pointer
OUTP DD FIFO ;output pointer
KEY PROC FAR USES EAX EBX EDX EDI
MOV EBX,CS:INP ;get pointers
MOV EDI,CS:OUTP
INC BL ;if full
.IF BX == DI
;disable 82C55 interrupt
MOV AL,8 ;if not full
MOV DX,CNTR
OUT DX,AL ;read key code
.ELSE ;save in queue
DEC BL
MOV DX,PORTA
IN AL,DX
MOV CS:[BX]
INC BYTE PTR CS:INP
.ENDIF
IRET
KEY ENDP
The procedure is short because the microprocessor already knows that keyboard data are
available when the procedure is called. Data are input from the keyboard and then stored in the
FIFO (first-in, first-out) buffer or queue. Most keyboard interfaces contain an FIFO that is at
least 16 bytes in depth. The FIFO in this example is 256 bytes, which is more than adequate for
a keyboard interface. Note how the INC BYTE PTR CX:INP is used to add 1 to the input pointer
and also make sure that it always addresses data in the queue.
This procedure first checks to see whether the FIFO is full. A full condition is indicated
when the input pointer (INP) is one byte below the output pointer (OUTP). If the FIFO is full, the
interrupt is disabled with a bit set/reset command to the 82C55, and a return from the interrupt
occurs. If the FIFO is not full, the data are input from port A, and the input pointer is incremented
before a return occurs.
INTERRUPTS 465
Example 12–6 shows the procedure that removes data from the FIFO. This procedure first
determines whether the FIFO is empty by comparing the two pointers. If the pointers are equal,
the FIFO is empty, and the software waits at the EMPTY loop where it continuously tests the
pointers. The EMPTY loop is interrupted by the keyboard interrupt, which stores data into the
FIFO so that it is no longer empty. This procedure returns with the character in register AH.
EXAMPLE 12–6
;A procedure that reads data from the queue of Example 12-5
;and returns it in AH;
READQ PROC FAR USES EBX EDI EDX
.REPEAT ;get pointers
MOV EBX,CS:INP ;while empty
NOV EDI,CS:OUTP
.UNTIL EBX == EDI
MOV AH,CS:[EDI] ;get data
MOV AL,9 ;enable 52C55 interrupt
MOV DX,CNTR
OUT DX,AL
INC BYTE PTR CS:OUTP
RET
READQ ENDP
12–3 EXPANDING THE INTERRUPT STRUCTURE
This text covers three of the more common methods of expanding the interrupt structure of the
microprocessor. In this section, we explain how, with software and some hardware modification
of the circuit shown in Figure 12–10, it is possible to expand the INTR input so that it accepts
seven interrupt inputs. We also explain how to “daisy-chain” interrupts by software polling. In
the next section, we describe a third technique in which up to 63 interrupting inputs can be added
by means of the 8259A programmable interrupt controller.
Using the 74ALS244 to Expand Interrupts
The modification shown in Figure 12–13 allows the circuit of Figure 12–10 to accommodate up
to seven additional interrupt inputs. The only hardware change is the addition of an eight-input
NAND gate, which provides the INTR signal to the microprocessor when any of the IR inputs
becomes active.
Operation. If any of the IR inputs becomes a logic 0, then the output of the NAND gate goes to
a logic 1 and requests an interrupt through the INTR input. The interrupt vector that is fetched
during the INTA pulse depends on which interrupt request line becomes active. Table 12–1
shows the interrupt vectors used by a single interrupt request input.
If two or more interrupt request inputs are simultaneously active, a new interrupt vector is
generated. For example, if IR1 and IR0 are both active, the interrupt vector generated is FCH
(252). Priority is resolved at this location. If the IR0 input is to have the higher priority, the vec-
tor address for IR0 is stored at vector location FCH. The entire top half of the vector table and its
128 interrupt vectors must be used to accommodate all possible conditions of these seven inter-
rupt request inputs. This seems wasteful, but in many dedicated applications it is a cost-effective
approach to interrupt expansion.
466 CHAPTER 12
FIGURE 12–13 Expanding the INTR input from one to seven interrupt request lines.
TABLE 12–1 Single inter- IR6 IR5 IR4 IR3 IR2 IR1 IR0 Vector
rupt requests for Figure
12–13. 1 1 1 1 1 1 0 FEH
1 1 1 1 1 0 1 FDH
1 1 1 1 0 1 1 FBH
1 1 1 0 1 1 1 F7H
1 1 0 1 1 1 1 EFH
1 0 1 1 1 1 1 DFH
0 1 1 1 1 1 1 BFH
Daisy-Chained Interrupt
Expansion by means of a daisy-chained interrupt is in many ways better than using the
74ALS244 because it requires only one interrupt vector. The task of determining priority is left
to the interrupt service procedure. Setting priority for a daisy-chain does require additional soft-
ware execution time, but in general this is a much better approach to expanding the interrupt
structure of the microprocessor.
Figure 12–14 illustrates a set of two 82C55 peripheral interfaces with their four INTR out-
puts daisy-chained and connected to the single INTR input of the microprocessor. If any interrupt
output becomes a logic 1, so does the INTR input to the microprocessor causing an interrupt.
When a daisy-chain is used to request an interrupt, it is better to pull the data bus connec-
tions (D0–D7) high by using pull-up resistors so interrupt vector FFH is used for the chain. Any
INTERRUPTS 467
FIGURE 12–14 Two 82C55
PIAs connected to the INTR
outputs are daisy-chained to
produce an INTR signal.
interrupt vector can be used to respond to a daisy-chain. In the circuit, any of the four INTR out-
puts from the two 82C55s will cause the INTR pin on the microprocessor to go high, requesting
an interrupt.
When the INTR pin does go high with a daisy-chain, the hardware gives no direct indica-
tion as to which 82C55 or which INTR output caused the interrupt. The task of locating which
INTR output became active is up to the interrupt service procedure, which must poll the 82C55s
to determine which output caused the interrupt.
Example 12–7 illustrates the interrupt service procedure that responds to the daisy-chain
interrupt request. The procedure polls each 82C55 and each INTR output to decide which inter-
rupt service procedure to utilize.
EXAMPLE 12–7
;A procedure that services the daisy-chain interrupt
;of Figure 12-14.
468 CHAPTER 12
12–4 C1 EQU 504H ;first 82C55
C2 EQU 604H ;second 82C55
MASK1 EQU 1 ;INTRB
MASK2 EQU 8 ;INTRA
POLL PROC FAR USES EAX EDX
MOV DX,C1 ;address first 82C55
IN AL,DX ;test INTRB
TEST AL,MASK1
.IF !ZERO?
;LEVEL 1 interrupt software here
.ENDIF
TEST AL,MASK2 ;test INTRA
.IF !ZERO?
;LEVEL 2 interrupt software here
.ENDIF ;address second 82C55
MOV DX,C2 ;test INTRB
TEST AL,MASK1
.IF !ZERO?
;LEVEL 3 interrupt software here
.ENDIF
;LEVEL 4 interrupt software here
POLL ENDP
8259A PROGRAMMABLE INTERRUPT CONTROLLER
The 8259A programmable interrupt controller (PIC) adds eight vectored priority encoded inter-
rupts to the microprocessor. This controller can be expanded, without additional hardware, to
accept up to 64 interrupt requests. This expansion requires a master 8259A and eight 8259A
slaves. A pair of these controllers still resides and is programmed as explained here in the latest
chip sets from Intel and other manufacturers.
General Description of the 8259A
Figure 12–15 shows the pin-out of the 8259A. The 8259A is easy to connect to the microproces-
sor because all of its pins are direct connections except the CS pin, which must be decoded, and
FIGURE 12–15 The pin-out
of the 8259A programmable
interrupt controller (PIC).
INTERRUPTS 469
the WR pin, which must have an I/O bank write pulse. Following is a description of each pin on
the 8259A:
D0–D7 The bidirectional data connections are normally connected to the data bus
IR0–IR7 on the microprocessor.
WR
RD Interrupt request inputs are used to request an interrupt and to connect to
INT a slave in a system with multiple 8259As.
INTA
The write input connects to write strobe signal (IOWC) on the
A0 microprocessor.
CS
SP>EN The read input connects to the IORC signal.
CAS0–CAS2 The interrupt output connects to the INTR pin on the microprocessor from
the master and is connected to a master IR pin on a slave.
Interrupt acknowledge is an input that connects to the INTA signal on the
system. In a system with a master and slaves, only the master INTA signal
is connected.
The A0 address input selects different command words within the 8259A.
Chip select enables the 8259A for programming and control.
Slave program/enable buffer is a dual-function pin. When the 8259A is in
buffered mode, this is an output that controls the data bus transceivers in a
large microprocessor-based system. When the 8259A is not in the buffered
mode, this pin programs the device as a master (1) or a slave (0).
The cascade lines are used as outputs from the master to the slaves for
cascading multiple 8259As in a system.
Connecting a Single 8259A
Figure 12–16 shows a single 8259A connected to the microprocessor. Here the SP>EN pin is
pulled high to indicate that it is a master. The 8259A is decoded at I/O ports 0400H and 0401H
by the PLD (no program shown). Like other peripherals discussed in Chapter 11, the 8259A
requires four wait states for it to function properly with a 16 MHz 80386SX and more for some
other versions of the Intel microprocessor family.
Cascading Multiple 8259As
Figure 12–17 shows two 8259As connected to the microprocessor in a way that is often found in
the ATX-style computer, which has two 8259As for interrupts. The XT- or PC-style computers
use a single 8259A controller at interrupt vectors 08H–0FH. The ATX-style computer uses inter-
rupt vector 0AH as a cascade input from a second 8259A located at vectors 70H through 77H.
Appendix A contains a table that lists the functions of all the interrupt vectors used.
This circuit uses vectors 08H–0FH and I/O ports 0300H and 0302H for U1, the master;
and vectors 70H–77H and I/O ports 0304H and 0306H for U2, the slave. Notice that we also
include data bus buffers to illustrate the use of the SP>EN pin on the 8259A. These buffers are
used only in very large systems that have many devices connected to their data bus connections.
In practice, we seldom find these buffers.
Programming the 8259A
The 8259A is programmed by initialization and operation command words. Initialization com-
mand words (ICWs) are programmed before the 8259A is able to function in the system and
dictate the basic operation of the 8259A. Operation command words (OCWs) are programmed
during the normal course of operation. The OCWs control the operation of the 8259A.
470 CHAPTER 12 VCC
FIGURE 12–16 An 8259A 10K
interfaced to the 8086
microprocessor.
U2
D0 11 D0 IR0 18 Interrupt inputs
D1 10 D1 IR1 19
D2 D2 IR2 20
D3 9 IR3 21
D4 8 D3 IR4 22
D5 D4 IR5 23
D6 7 IR6 24
D7 6 D5 IR7 25
A1 5 D6
4
RD D7
INTR WR 27 A0 12
INTA 13
1 CS CAS0 15
WAIT2 RD CAS1
3 WR CAS2
2
16 SP/EN
17
26 INT
INTA
8259A
U1
M/IO 1 I1 O1 19
A0 2 I2 O2 18
A2
A3 3 I3 O3 17
A4 4 I4 O4 16
A5 15
A6 5 I5 O5
A7 6 I6 14
A8 I7 O6 13
A9 7 I8 12
8 I9 O7
A10 9 I10 O8
A11 11
A12
A13 16L8
A14
A15
Initialization Command Words. There are four initialization command words (ICWs) for the
8259A that are selected when the A0 pin is a logic 1. When the 8259A is first powered up, it must
be sent ICW1, ICW2, and ICW4. If the 8259A is programmed in cascade mode by ICW1, then we
also must program ICW3. So if a single 8259A is used in a system, ICW1, ICW2, and ICW4 must
be programmed. If cascade mode is used in a system, then all four ICWs must be programmed.
Refer to Figure 12–18 for the format of all four ICWs. The following is a description of
each ICW:
ICW1 Programs the basic operation of the 8259A. To program this ICW for
8086–Pentium 4 operation, place a logic 1 in bit IC4. Bits AD1, A7, A6,
and A5 are don’t cares for microprocessor operation and only apply to the
8259A when used with an 8-bit 8085 microprocessor (not covered in this
textbook). This ICW selects single or cascade operation by programming
the SNGL bit. If cascade operation is selected, we must also program
ICW3. The LTIM bit determines whether the interrupt request inputs are
positive edge-triggered or level-triggered.
ICW2 Selects the vector number used with the interrupt request inputs. For
example, if we decide to program the 8259A so it functions at vector
locations 08H–0FH, we place 08H into this command word. Likewise, if
we decide to program the 8259A for vectors 70H–77H, we place 70H in this ICW.
ICW3 Only used when ICW1 indicates that the system is operated in cascade
mode. This ICW indicates where the slave is connected to the master. For
example, in Figure 12–18 we connected a slave to IR2. To program ICW3