Chapter 2 - General Purpose Digital Input/Output
Digital inputs and outputs are very useful in data acquisition, monitoring, instrumentation and control applications. A low voltage (near 0 Volts) is established on a digital output pin when the processor writes a logical 0 to the corresponding bit in a data register associated with the digital output port. A high voltage (near 5 Volts) is established on the digital output pin when the processor writes a 1 to a corresponding bit in the port's data register. This allows software to control external events and processes. For example, an application program can use digital outputs to activate solenoids and turn switches and lights on and off, or to interface the QED Board with a wide variety of digital accessories such as D/A converters, displays, etc.
A digital input allows the processor to monitor the logical state of an external voltage by reading a data register associated with the port. External voltages near 0 Volts connected to a digital input cause the corresponding bit in the port's data register to be read as a logical 0, and external voltages near 5 Volts connected to a digital input are read as a logical 1. Application programs can use digital inputs to read switches and keypads or to interface to digital devices such as A/D converters and real-time clocks.
Using digital I/O is very easy:
- Configure the direction of the digital I/O port. This is accomplished by writing to a named data direction port (in the case of PORTA and PORTD) to set the directions of individual bits within a port, or by executing an initialization routine such as INIT.PIA.
- To change the state of an output port, write to the port's data register (whose address is left on the stack by simply stating the name of the port) using C!, SET.BITS, CLEAR.BITS, or other pre-defined operators.
- To read the state of an input port, read the port's data register with a C@ command; the result is left on the data stack.
The names of the data and direction registers and all required initialization routines are pre-defined in the QED-Forth kernel so you don't have to hassle with hexadecimal register addresses in your code. The following sections describe the available digital I/O ports and how to use them.
Overview of Available Digital I/O
The QED Board provides up to 44 lines of digital I/O. Many of these lines have alternate uses. Figure 2.1 summarizes the available digital I/O ports and their functions.
Port | Address | No. | Configurable | Configured | Alternate Use |
---|---|---|---|---|---|
Name | (hex) | lines | as | by | (#Signals Used) |
68HC11: | |||||
PORTA | 8000 | 8 | Bitwise I/O | PORTA.DIRECTION | Serial2 (2) Pulse accumulator (1) Timed inputs (3 or 4) Timed inputs (4 or 5) |
PORTD | 8008 | 4 | Bitwise I/O | SPI.OFF. PORTD.DIRECTION | SPI (4) |
PORTE | 800A | 8 | Bytewise digital/\\analog input | A/D8.OFF | 8 bit A/D (8) |
PIA: | |||||
PPA | 8080 | 8 | Bytewise I/O | INIT.PIA | -- |
PPB | 8081 | 8 | Bytewise I/O | INIT.PIA | Display/keypad (7) A/D12 chip select (1) |
PPC lower | 8082 | 4 | Nibblewise I/O | INIT.PIA | Keypad (4) |
PPC upper | 8082 | 4 | Nibblewise I/O | INIT.PIA | RS485 (1) |
Figure 2.1 - Summary of digital input/output on the QED Board including the names, addresses, and number of signals associated with the digital ports on the 68HC11 and PIA. The "configurable as" column specifies whether the direction of the port may be changed on a bit-by-bit, nibble-by-nibble, or byte basis (or in the case of PORTE, configured as digital or analog input). The "configured by" column specifies the named data direction register which controls the input/output direction, or specifies the QED-Forth routine that configures the port. The final column lists alternate uses (other than standard digital I/O) and the number of signals that may be dedicated to the alternate uses.
The digital I/O signals on the QED Board originate from the 68HC11 processor chip and the 82C55A peripheral interface adapter (PIA) chip. The 68HC11 provides two 8 bit ports named PORTA and PORTE, and 4 available bits on PORTD (PD2 through PD5). The PIA supplies three 8 bit digital I/O ports named PPA, PPB, and PPC.
QED-Forth Provides Named Registers and Pre-coded Configuration Routines
The ports are addressed in common memory at the hex addresses shown in Figure 2.1. The 68HC11 ports are associated with data and direction registers in the processor's 96 byte block of "Control and Status Registers" located at 8000H-805FH; Appendix B summarizes the contents of all of these registers. The PIA ports are associated with data registers addressed at 8080H-8082H and a control register at address 8083H.
QED-Forth names the digital I/O ports, and when the name is executed the 32 bit extended address of the port's data register is left on the stack. This makes it easy to access the port; simply state the port's name and use the standard byte fetch and store operations C@ and C! to read or write to the port. Individual bits in the digital ports can also be modified with operators such as SET.BITS, CLEAR.BITS, TOGGLE.BITS, and CHANGE.BITS.
The names of the digital I/O ports and the respective hexadecimal addresses left on the stack are as follows:
PORTA | ( -- 8000\0 ) |
---|---|
PORTD | ( -- 8008\0 ) |
PORTE | ( -- 800A\0 ) |
PPA | ( -- 8080\0 ) |
PPB | ( -- 8081\0 ) |
PPC | ( -- 8082\0 ) |
QED-Forth also makes it easy to configure the data direction (input or output) of the I/O ports. The directions of the individual bits in PORTA and PORTD are controlled by direction registers which are named in QED-Forth. The direction register names and the respective hexadecimal addresses left on the stack are as follows:
PORTA.DIRECTION ( %%--%% 8001\0 ) PORTD.DIRECTION ( %%--%% 8009\0 )
Writing a 1 to a bit in the data direction register sets the corresponding port bit to an output, and writing a 0 configures the bit as an input. The commands C!, SET.BITS, or CLEAR.BITS can be used to modify the contents of the data direction registers. Any combination of input and output bits may be specified for these ports.
The data direction of the PIA ports are set by the routine INIT.PIA which is described later in this chapter and in the glossary.
PORTE on the 68HC11 can be configured as an 8 channel 8 bit analog to digital converter by executing A/D8.ON, and it reverts to its default condition as an 8 channel digital input port after execution of A/D8.OFF.
Alternate Uses of the Digital I/O Ports
Many of these port signals have alternative uses as summarized in Figure 2.1. The 68HC11's I/O ports can serve these multiple functions:
PORTA may be used as bit-configurable digital input/output. The data direction (input or output) of PORTA is determined by writing to the PORTA.DIRECTION register as described below. If any bits in PORTA are not being used for digital I/O, they may be used to implement a variety of counting and timing functions including input captures, output compares, and pulse accumulation as described in Chapter 4. In addition, QED-Forth provides an optional software UART that supports a secondary RS232 serial port (called Serial2) using pins 3 and 4 of PORTA (see Chapter 11).
PORTD is a 6 bit port. Bits 2-5 of may be used as bit-configurable digital I/O. The data direction (input or output) of PORTD is determined by writing to the PORTD.DIRECTION register as described below. The two least significant bits of PORTD (PD0 and PD1) are the receive and transmit lines for the serial communications interface. Changing the data direction bits for these two signals has no effect unless you have disabled serial communications.
If PD2 through PD5 are not being used for general purpose digital I/O they may implement the SPI (serial peripheral interface). The SPI is a fast synchronous serial link which is used to communicate with the optional onboard 12 bit analog to digital converter (A/D12) and 8 bit digital to analog converter (DAC). The SPI is turned on by executing INIT.SPI and is turned off by executing SPI.OFF. The SPI is initially off after a reset or restart; see Chapter 5 for a detailed description of this versatile serial link.
PORTE provides 8 input lines. They may be used as the analog inputs to the 68HC11's built-in 8 bit A/D converter, or they may be used as general purpose digital inputs if the 8 bit A/D converter is turned off. The command A/D8.ON turns the 8 bit A/D on, and the command A/D8.OFF turns it off. The 8 bit A/D is initially off after a reset or restart; see Chapter 6 for more details.
The PIA's three ports serve the following functions:
PPA has no alternate functions and is always available as a digital input or output port.
The upper 4 bits of PPC are available as digital input or output if RS485 communications are not being used. If RS485 communications are used, bit 4 of PPC (that is, the lowest bit in the upper nibble of PPC) controls the direction of the RS485 transceiver, and the upper half of PPC must be configured as an output (see Chapter 11 and the glossary entry for INIT.RS485).
PPB and the lower nibble of PPC are dedicated to the keypad/display interface, and the top bit (bit 7) of PPB is used as the chip select signal of the 12 bit A/D converter.
While it is possible to use 7 bits of PPB and the lower 4 bits of PPC as general purpose digital I/O if the keypad/display interface is not used, there are some challenges involved. These ports are not brought out to the digital I/O connector. PPB0-6 and PPC0-3 are brought out to the 34 pin keypad/display connector in a "scrambled" order that facilitates direct connection of a keypad and display. The PPC0-3 inputs are pulled up to +5 Volts with 15.8 K-ohm resistors as required by the keypad interface. After every reset and restart the data direction of PPB is automatically initialized to output and the direction of lower PPC is set to input to ensure compatibility with the keypad/display interface. Programmers who wish to use these signals for digital input/output instead of the keypad/display interface must work within these constraints.
Digital I/O Connections
Figure 2.2 summarizes the pinouts of the 40 pin Digital I/O connector and the 40 pin Analog I/O connector on the QED Board. The signals of PORTA, PORTD, PPA, and the upper nibble of PPC are available on the Digtial I/O connector. The PORTE signals which can be configured as either analog or digital inputs are available on the Analog I/O connector.
Digital I/O Connector | Analog I/O Connector | |||||||
---|---|---|---|---|---|---|---|---|
GND | – 1 | 2 – | +5V | Vrl | – 1 | 2 – | Vrh | |
PA7 | – 3 | 4 – | PA6 | PE7/AN7 | – 3 | 4 – | PE6/AN6 | |
PA5 | – 5 | 6 – | PA4 | PE5/AN5 | – 5 | 6 – | PE4/AN4 | |
PA3 | – 7 | 8 – | PA2 | PE3/AN3 | – 7 | 8 – | PE2/AN2 | |
PA1 | – 9 | 10 – | PA0 | PE1/AN1 | – 9 | 10 – | PE0/AN0 | |
PD5//SS | – 11 | 12 – | PD4/SCK | 12AN7 | – 11 | 12 – | 12AN6 | |
PD3/MOSI | – 13 | 14 – | PD2/MISO | 12AN5 | – 13 | 14 – | 12AN4 | |
E | – 15 | 16 – | R//W | 12AN3 | – 15 | 16 – | 12AN2 | |
/OE | – 17 | 18 – | /WE | 12AN1 | – 17 | 18 – | 12AN0 | |
/XIRQ | – 19 | 20 – | /IRQ | AGND | – 19 | 20 – | +5VAN | |
/Power Fail | – 21 | 22– | 4xOut | Vin1 | – 21 | 22– | Vout1 | |
/Reset | – 23 | 24– | /Shutdown | Vin2 | – 23 | 24– | Vout2 | |
PPC7 | –25 | 26– | PPC6 | Vin3 | – 25 | 26– | Vout3 | |
PPC5 | – 27 | 28– | PPC4/RS485.XMIT | Vin4 | – 27 | 28– | Vout4 | |
PPA7 | – 29 | 30– | PPA6 | Vin5 | – 29 | 30– | Vout5 | |
PPA5 | – 31 | 32– | PPA4 | Vin6 | – 31 | 32– | Vout6 | |
PPA3 | – 33 | 34– | PPA2 | Vin7 | – 33 | 34– | Vout7 | |
PPA1 | – 35 | 36– | PPA0 | Vin8 | – 35 | 36– | Vout8 | |
AGND | – 37 | 38– | +5VAN | 1.5Vref | – 37 | 38– | +5V | |
DGND | – 39 | 40– | V+Raw | VRefLow | – 39 | 40– | V+Raw |
Figure 2.2. Pinouts of the Digital I/O connector and the Analog I/O Connector.
The 8 PORTA signals are labeled
PA0 PA1 PA2 PA3 PA4 PA5 PA6 PA7
These signals are brought out to pins 3 through 10 on the 40 pin Digital I/O connector.
The 4 PORTD signals are labeled
PD2/MISO PD3/MOSI PD4/SCK PD5//SS
The first part of each signal name conveys the position in PORTD, and the second part is the signal name of the shared SPI (serial peripheral interface) function. These signals are brought out to pins 11 through 14 on the 40 pin Digital I/O connector (see Figure 2.2). The SPI is discussed in detail in Chapter 5.
The 8 PORTE signals are labeled
PE0/AN0 PE1/AN1 PE2/AN2 PE3/AN3
PE4/AN4 PE5/AN5 PE6/AN6 PE7/AN7
The first part of the signal name indicates the position in PORTE, and the second part reflects each signal's shared function as an 8 bit A/D input. These signals are brought out to pins 3 through 10 on the 40 pin Analog I/O connector (see Figure 2.2). Chapter 6 provides more detail about the A/D converter.
The 8 PPA signals originating at the PIA are labeled
PPA0 PPA1 PPA2 PPA3 PPA4 PPA5 PPA6 PPA7
These signals are brought out to pins 29 through 36 on the 40 pin Digital I/O connector (see Figure 2.2). The 8 bit PPA port does not have any shared functions and is always available as general purpose digital input or output.
The upper 4 bits of PPC are labeled
PPC4/RS485.XMIT PPC5 PPC6 PPC7
and are brought out to pins 25 through 28 on the 40 pin Digital I/O connector (see Figure 2.2). If RS485 serial communications are used, PPC4/RS485.XMIT controls the direction of the data transfer, and the upper half of PPC must be configured as an output (see the glossary entry for INIT.RS485). If RS485 is not being used, upper PPC can be configured as input or output.
PPB and the lower nibble of PPC are used to implement the keypad/display interface, and are brought out to the 34 pin keypad/display connector. The port bits are brought out in a "scrambled" order that facilitates direct connection of a keypad and display.
Setting the Data Direction of the Digital I/O Ports
Setting the Data Direction of PORTA and PORTD
Two named registers control the direction of the bits in PORTA and PORTD, respectively:
PORTA.DIRECTION
PORTD.DIRECTION
Writing a 1 to a bit in the direction register sets the corresponding port bit as an output, and writing a 0 to a bit in the direction register sets the corresponding port bit as an input. A one-to-one correspondence exists between bits in the data direction register and its corresponding port. These two ports are configurable on a bit-by-bit basis, so any combination of inputs and outputs can be specified.
For example, to set PORTA as all input, execute
00 PORTA.DIRECTION C!
To set the lower 4 bits of PORTA as input and the upper 4 bits as outputs, execute
HEX F0 PORTA.DIRECTION C!
To set the least significant bit of PORTA as an input while leaving the direction of all other bits unchanged, execute
01 PORTA.DIRECTION CLEAR.BITS
which clears the least significant bit in PORTA.DIRECTION to 0.
The direction of PORTD is controlled in the same way. Recall that PORTD is a 6 bit port, and the two least significant bits are used by the primary serial channel. This leaves the four bits PD2 through PD5 available for digital I/O if they are not used for the SPI. For example, to set the four available bits PD2 through PD5 to all outputs, execute
HEX 3C PORTD.DIRECTION C!
The command
HEX FF PORTD.DIRECTION C!
has the exact same effect; the two least significant bits in PORTD are not affected by the PORTD.DIRECTION register, and the two most significant bits in PORTD do not exist.
Configuring PORTE as a Digital Input Port
PORTE is always an input port. After each reset and restart, it is configured as an 8 channel digital input port. Executing
A/D8.ON
turns on the 8 bit analog converter and configures PORTE as an 8 channel 8 bit analog input port (see Chapter 6). Executing
A/D8.OFF
turns off the 8 bit A/D and configures PORTE as an 8 channel digital input port.
(For experts and the curious: A/D8.OFF turns the 8 bit analog converter off by clearing the A/D power up bit named ADPU in the OPTION register; A/D8.ON sets the ADPU bit; see F1 p.6-4.)
PIA Initialization
The QED-Forth word
INIT.PIA ( flag1\flag2 -- | flag1 = ppa.output?, flag2 = upper.ppc.output?)
writes to the peripheral interface adapter (PIA) configuration register to set the data direction for PPA and the upper 4 bits of PPC. If flag1 is true, INIT.PIA configures PPA as output, and if flag 1 is false, it configures PPA as input. Likewise, if flag2 is true, INIT.PIA configures upper PPC as output, and if flag 2 is false, it configures upper PPC as input. INIT.PIA sets the direction of PPB as output and lower PPC as input to ensure compatibility with the built-in keypad and display interfaces. It clears bit 6 of PPB and sets bit 7 of PPB high so that the display.enable and 12 bit A/D chip select signals are inactive. If the specified input/output configuration of the PIA is the same as the prior configuration, INIT.PIA does not modify the PIA configuration register, and thus does not change the state of any output pins in PPA or upper PPC. If the specified PIA configuration is different than the prior configuration, INIT.PIA writes to the PIA's configuration register and this automatically zeros any outputs in PPA or upper PPC. Consult the PIA data sheet in Appendix C for details of the PIA operation.
INIT.PIA may disrupt in-progress operations involving the 12 bit A/D, keypad, or display. INIT.PIA is called by INIT.A/D12&DAC, INIT.DISPLAY, and INIT.RS485. When designing your application, the safest course is to perform all required initializations in an autostart routine as soon as the application program begins. This avoids the problem of a late initialization that disturbs an in-progress I/O operation.
Upon each reset or restart, the PIA is configured as follows:
Port | Direction |
---|---|
PPA | input |
PPB | output |
lower PPC | input |
upper PPC | input |
Accessing Digital I/O Ports
The three PIA ports are named in QED-Forth as PPA, PPB, and PPC (meaning peripheral port A, B, and C respectively). The available digital ports on the 68HC11 processor are also named; they are PORTA, PORTD, and PORTE. PORTA is a bitwise-configurable I/O port with associated counting and timing functions; it also supports the serial2 software UART on pins PA3 (input) and PA4 (output). PORTD pins PD2 to PD5 can be used as the serial peripheral interface (SPI) or as bitwise-configurable I/O. PORTE can be used as an octal 8 bit A/D, or as 8 bits of digital input if the A/D converter is turned off.
Digital ports with some or all of their bits configured as outputs can be written to using the standard C! (pronounced "C-store") operator. For example, if you first set PPA as an output by executing
TRUE FALSE INIT.PIA
then the command
HEX FF PPA C!
stores the value FFH into PPA in the peripheral interface adapter and sets all of its outputs high. Try measuring the PPA outputs with a voltmeter; the output voltage should be approximately 5 Volts.
Digital ports with some or all of their bits configured as inputs can be read using the standard C@ (pronounced "C-fetch") operator. For example, if PORTE is left in its default state configured as a digital (as opposed to analog) input port, the command
PORTE C@ ( --byte )
leaves the contents of the PORTE data register on the stack. The resulting byte left on the stack reports a 1 in the bit position corresponding to each pin of PORTE that senses a voltage higher than 3.5 Volts. Likewise, the byte will contain a 0 in the bit positions corresponding to all pins with a voltage lower than 1.0 Volts. Try connecting some PPA output pins to the PORTE inputs by wiring the appropriate pins on the 40 pin Digital I/O connector together (always be sure that you've identified the correct pins!) Now you can write to PPA and verify the results by reading PORTE.
Modifying Bits in an I/O Port and the Importance of Uninterruptable Operators
Sometimes it is necessary to set, clear, toggle, or change one or more bits in a port while leaving other bits unaffected. QED-Forth provides convenient read/modify/write routines called SET.BITS, CLEAR.BITS, TOGGLE.BITS, and CHANGE.BITS to accomplish these functions. The corresponding fast page-less operators named (SET.BITS), (CLEAR.BITS), (TOGGLE.BITS), and (CHANGE.BITS) can also be used to modify the contents of addresses in common memory. The glossary entries provide detailed descriptions of these operations.
For example, if upper PPC has been configured as an output using INIT.PIA, the top 4 bits in PPC can be cleared to zeros by executing
HEX F0 PPC CLEAR.BITS
F0 is a bit mask with the top 4 bits equal to ones; this tells CLEAR.BITS that only the top 4 bits should be cleared. The bottom 4 bits of PPC are unaffected.
SET.BITS, CLEAR.BITS, TOGGLE.BITS, and CHANGE.BITS (and the corresponding page-less operators) globally disable interrupts just before reading the memory contents and restore the prior state of the interrupt flag (enabled or disabled) after writing to the specified address. This makes these routines robust with respect to interrupts and timesliced multitasking when two or more concurrently executing routines are modifying bits in the same memory location.
The following scenario illustrates the importance of these uninterruptable operators when more than one task or interrupt routine is writing to a memory location. Let's assume that two different tasks are controlling the bits of the upper nibble of PPC. Assume that TASK1 is controlling the state of bit 4 in PPC (perhaps to set the direction of the RS485 transceiver), and TASK2 controls bit 7 in PPC. Let's assume that bit 4 is low when TASK2 tries to execute the following sequence:
HEX PPC C@ 80 OR PPC C!
TASK2 is merely trying to set the top bit in PPC to 1, but this sequence of commands may have unintended consequences. Assume that the timeslicer interrupt is serviced just after the OR instruction and transfers control to TASK1. TASK1 may change the state of bit 4 to a 1. When control is then transferred back to TASK2, the remaining command PPC C! is executed. Unfortunately, this C! command erroneously sets bit 4 back to the low state! TASK2 was interrupted after it read the state of PPC but before it had a chance to write the new contents, so it undoes the change that TASK1 made in the state of PPC bit 4.
The uninterruptable read/modify/write routines avoid this problem by disabling interrupts for ten to sixteen cycles (5 to 8 microseconds at an 8 MHz crystal speed). This prevents the corruption of the contents when different tasks or interrupts share access to a single location.
Similar problems can arise when one task writes to a floating point or other 4-byte variable, and a second task needs to read the saved value. The data that is read may be invalid if the read or the write is interrupted between the time of the writing/reading of the first 16 bits and the writing/reading of the second 16 bits. For this reason a set of uninterruptable operators denoted by the | ("bar") character are in the kernel. These are |2@|, |F@|, |X@|, |2!|, |F!|, and |X!|. Consult the "Multitasking" chapter in the Software Manual for a more detailed discussion of this topic.
For Experts: Fast Port Accesses
The following comments may help those who need maximum speed when accessing a port from within a Forth definition.
Because all of the named digital I/O ports are located in common memory, the fast page-less operator (C@) can be used to access the ports. For example, the command
PORTE DROP (C@) ( --byte )
returns the same result as the command PORTE C@. (C@) executes more rapidly than C@ because it does not change pages during the read operation. But this time savings is mostly offset by having PORTE place the full extended address including page on the data stack at runtime, and then calling DROP to remove the page from the stack. A more efficient method is to instruct the compiler to place only the 16 bit address on the stack at runtime, and then call (C@) to read the contents. The following definition shows how this can be accomplished:
: READ.PORTE ( -- ) [ PORTE DROP ] LITERAL (C@) \ this is a very fast fetch CR ." The contents of PORTE = " . \ display the result
The [ is an immediate word that invokes the execution mode. PORTE DROP places the 16 bit address of the port on the data stack, and ] re-enters the compilation mode. LITERAL removes the 16 bit address of the port from the data stack and compiles it as a literal that will be placed on the stack at runtime so that (C@) may fetch its contents. The rest of the definition prints the result. This same technique may be used to read, modify, or write to any location in common memory. A wide variety of fast page-less operators are available in the kernel, including (@), (!), (F@), (F!), (SET.BITS), (CLEAR.BITS), (TOGGLE.BITS), and (CHANGE.BITS).
Of course, the fastest way to access the contents of a port in common memory is to use assembly code. The following routine leaves the contents of PORTE on the data stack:
CODE FETCH.PORTE.CONTENTS ( -- byte ) PORTE DROP EXT LDAB \ B gets contents of portE CLRA \ zero upper byte of double accumulator DEY DEY \ make room on data stack 0 IND,Y STD \ put result on data stack RTS END.CODE
Because all of the named port addresses are located in the common memory, it is safe to DROP the page and use an assembly coded "load" operation such as LDAB to fetch the contents of the port. Note that when assembly coding accesses to locations that are not in common memory, it is best to call the pre-coded memory access routines in the QED-Forth kernel (such as C@) which properly handle the page changes.
Electrical Characteristics of Digital I/O Signals
Characteristics of the 68HC11's I/O Ports
The electrical characteristics of the 68HC11F1's digital I/O signals are specified in detail in section 13.4 of the F1 technical data book. This table lists the "DC Electrical Characteristics" of the processor.
Pins on the 68HC11 configured as digital inputs report a logical "high" if the input voltage is greater than 0.7 times the supply voltage, or 3.5 Volts. They report a logical "low" if the input voltage is less than 0.2 times the supply voltage, or 1.0 Volt. Input voltages between 1.0 and 3.5 Volts may be read as either high or low.
Pins on the 68HC11 configured as digital outputs in the "high" state can maintain the output voltage within 0.8 Volts of the positive supply if 0.8 mA or less is being drawn from the pin. If less than 10 microamps is being drawn, the output high voltage is within 0.1 Volt of the positive supply. In the low state, the digital outputs can keep the voltage below 0.4 Volts while sinking up to 1.6 mA of current. Load circuitry that requires significant current to be sourced or sunk by the digital output should include external resistors to ensure that the absolute maximum rating of 25 mA per output pin is never exceeded.
The PORTA bits PA0 through PA7 are configured as inputs after a reset or restart, unless the serial2 port is specified as the default startup port (consult the chapter titled "The User Interface: LCD Display, Keypad, and Serial Ports" in the QED Software Manual, and see the glossary entry for SERIAL2.AT.STARTUP). If the secondary serial port is automatically initialized at startup, then PA4 is initialized as the serial output and PA3 is configured as the serial input. The remaining PORTA pins are configured as digital inputs after the reset or restart.
PORTD bits PD2 through PD5 are configured as digital inputs after a reset or restart. PORTE bits PE0 through PE7 are configured as digital inputs after a reset or restart; the default state of the 8 bit A/D converter is OFF.
Characteristics of the PIA's I/O Ports
The 82C55A peripheral interface adapter (PIA) chip is the industry standard part for providing digital I/O ports. Its data sheet is presented in Appendix C. This brief summary is intended to clarify some of the features of this chip.
The PIA is configured by writing to a control register at address 8083H. The pre-defined routine INIT.PIA described earlier in the chapter writes to this register. It configures the PIA for simple digital I/O ("mode 0") and sets the data direction of ports PPA and upper PPC according to user-supplied flags. INIT.PIA configures PPB as an output and the lower half of PPC as an input to maintain compatibility with the built-in keypad and display interfaces.
Whenever the PIA is configured by writing to the control register, all outputs are set to the logic low state. This is true whether or not the new configuration is different from the prior configuration. The INIT.PIA routine tries to minimize the impact of this (often undesirable) "feature" by checking the control register before writing to it. If the PIA configuration requested by the programmer is the same as the existing configuration, the PIA's control register is not modified. In general, it is best to use a static configuration for the PIA; dynamically changing the direction of PIA ports while the application is running can cause troublesome glitches on the PIA output pins.
The PIA has another unusual "feature" called "bus hold circuitry". The PIA tries to maintain specified logic levels on pins that are configured as inputs (rather than the standard approach of leaving the input pins in a "floating" high impedance state). After a reset or change in configuration, the PIA holds all inputs high by sourcing between 50 and 400 microamps into the external load attached to the input pin. If your design requires that the inputs settle to a voltage near ground, you will need to pull the pins low with external pull-down resistors that connect each input pin to ground. The resistors should have a value less than 1 K-ohm; the manufacturer suggests that the pull-down should be 640 ohms to ensure a logical 0 under worst-case conditions. Port PPA also has bus hold circuitry that can hold an input in the low condition. If your design requires that PPA inputs be held at a logical high state, install external pull-up resistors of less than 3 K-ohms from the PPA input pins to the +5 Volt supply.
PIA output pins have good current drive capabilities. The data sheet states that the chip can maintain an output high voltage of at least 3.0 Volts while sourcing up to 2.5 mA. The manufacturer's technical support staff claims that the typical performance is much better; they say that a typical chip can maintain 3.0 Volts or higher while sourcing up to 20 mA. In the worst case the PIA outputs can sink up to 2 mA while maintaining the output voltage below 0.4 Volts. There is no internal current limiting on the outputs, so your custom circuitry should include current-limiting resistors if significant current will be required from the output pins.
Summary
This chapter describes how to configure and access the 68HC11 digital I/O ports A, D and E and the PIA ports PPA, PPB, and PPC. Figure 2.1 summarizes the available I/O and the alternate functions associated with the I/O pins. To use the digital I/O ports, follow these three simple steps.
- Configure the direction of the digital I/O port.
- To configure PORTA, write to the PORTA.DIRECTION register using C! or a bit manipulation routine such as SET.BITS or CLEAR.BITS. Writing a 1 to a bit position in PORTA.DIRECTION configures the corresponding port bit as an output, and writing a 0 to a bit position configures the corresponding bit as an input. PORTA is configurable on a bit-by-bit basis.
- To configure PORTD, write to the PORTD.DIRECTION register. PORTD is a 6 bit port, and the two least significant bits are used by the primary serial channel. This leaves the four bits PD2 through PD5 available for digital I/O if they are not used for the SPI. The available PORTD pins are configurable on a bit-by-bit basis.
- To configure PORTE for analog input, execute A/D8.ON. To configure PORTE for digital input, execute A/D8.OFF. PORTE is configured as a digital input after a reset or restart.
- To configure the PIA, place two flags on the stack and execute INIT.PIA. The first flag specifies the direction of PPA, and the second flag (top flag on the stack) specifies the direction of the upper nibble of PPC. A true flag specifies output and a FALSE flag specifies input. INIT.PIA configures PPB as an output and lower PPC as an input to ensure compatibility with the keypad/display drivers.
- To change the state of an output port, write to the port's data register (whose address is left on the stack by simply stating the name of the port) using C!, SET.BITS, CLEAR.BITS, or other pre-defined operators.
- To read the state of an input port, read the port's data register with a C@ command; the result is left on the data stack.