![]() |
![]() |
![]() |
The C Programmer’s Guide to the QVGA ControllerTable of ContentsPART 1 GETTING STARTED Introduction. How to Use This Manual Chapter 1: Getting to Know Your QVGA PART 2 PROGRAMMING THE QVGA CONTROLLER Chapter 3: The IDE: Writing, Compiling, Downloading and Debugging Programs Chapter 4: Making Effective Use of Memory Chapter 5: Programming the Graphical User Interface Chapter 6: Real Time Programming Chapter 7: Failure and Run-Time Error Recovery PART 3 COMMUNICATIONS, MEASUREMENT, AND CONTROL Chapter 8: Digital and Timer-Controlled I/O Overview of Available Digital I/O Using the Digital I/O Ports on the 68HC11 Chip Using the High Current Drivers Connecting Hardware to the Digital Outputs The Processor’s Output Compare Functions Pulse and PWM Generation Techniques Chapter 9: Data Acquisition Using the QVGA Controller Chapter 10: Outputting Voltages with Digital to Analog Conversion
Chapter 11: Serial Communications Chapter 12: The Battery-Backed Real Time Clock PART 4: PUTTING IT ALL TOGETHER Chapter 13: A Turnkeyed Application PART 5: REFERENCE DATA Appendix A: QVGA Electrical Specifications |
Chapter 8 Chapter 8: Digital and Timer-Controlled I/OOverview of Available Digital I/OThe QVGA Controller provides 30 digital I/O lines, 24 analog I/O lines, and three communications channels. The digital I/O lines originate in four ports on the CPU (68HC11), designated PORTA, PORTB, PORTC, and PORTD, and three additional ports provided by a peripheral interface adapter (PIA) chip (82C55A), designated PPA, PPB and PPB. Table 8‑1 summarizes the digital I/O available, its alternate uses, and port assignments. Table 8‑1 The QVGA Controller’s Digital I/O
There are a total of 30 fully uncommitted digital I/O lines for your use. After initialization or reset these are configured as 21 digital inputs and 9 digital outputs, but as Figure 8‑1 shows many of these I/O lines are reconfigurable. Up to 21 of these I/O lines can be configured as inputs, all can be configured as outputs. In addition to these I/O lines there are several committed to other services on the controller; these are summarized in Table 8‑2. Table 8‑2 Committed I/O pins
For applications requiring even more digital I/O, I/O lines usually committed to the 8-bit A/D, the RS485 port, the secondary serial port or the SPI may be redirected as general purpose digital I/O if these other services are not needed, providing up to 15 additional digital I/O lines. Table 8‑3 summarizes the digital I/O lines gained if other services are not used. The services uses are ordered from the least-used (the RS485) to the most frequently used (the SPI). Note that the SPI is required to use the 12-bit A/D and any Wildcard I/O expansion modules. The five of the 9 output lines that originate on PPB (PPB 0-4) may be converted to input lines if the high current drivers are not needed. In that case, PPB can be reconfigured as all inputs, 9 outputs can be traded for 5 inputs, for a loss of 4 total lines but a gain of 5 more inputs. Table 8‑3 Additional digital I/O lines made available if other services are forfeited and their committed I/O pins freed.
Many of these 57 I/O lines are digital inputs and outputs. Including the high current drivers the maximum number of digital inputs and outputs is 41 (up to 32 can be configured as inputs, up to 29 as outputs) if none are used for the 8-bit A/D, the RS485, or the secondary serial port. Table 8‑1 summarizes the digital I/O and alternate use of some of the I/O pins. Digital inputs and outputs are very useful in data acquisition, monitoring, instrumentation and control applications. A low voltage (approximately 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 (approximately 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 QVGA Controller with a wide variety of digital accessories. 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. In addition, there are four high current drivers available. These N-channel MOSFET outputs can sink 150 mA continuously, and up to 1 amp on an intermittent basis. Onboard snubber diodes allow control of inductive loads. They are particularly useful for driving relays, solenoids, and low power stepper motors. Using digital I/O is very easy: simply configure the output port as input or output as explained below, and then use functions or assignment statements to read from or write to the port. The names of the data and direction registers and all required initialization routines are pre-defined in the header files so you don’t have to worry about hexadecimal register addresses in your code. The following sections describe the available digital I/O ports and how to use them. The digital I/O signals on the QVGA Controller originate from a Motorolla 68HC11 processor chip and an 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. Table 8‑4 summarizes the digital input/output available on the QVGA Controller 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 final column lists alternate uses (other than standard digital I/O), the signal pins and the number of signals associated with the alternate uses. Note that a fourth High Current driver output is controlled by the onboard PAL. Table 8‑4 Digital I/O Port Addresses and Configurability.
Table 8‑5 specifies the named data direction register which controls the input/output direction, or specifies the functions that configure each digital I/O port. Table 8‑5 Digital I/O port data direction registers and configuration functions.
Using the Digital I/O Ports on the 68HC11 ChipThis section describes how to configure and access the PORTA and PORTE digital ports in the 68HC11 chip on the QED Board. As you work through the examples in the remaining sections of the chapter, you can use a voltmeter to verify that the outputs are behaving as you expect. You can also connect the input signals through a 1 kOhm resistor to +5V or GND to verify that you can digitally read their values. (The 1 kOhm resistor is just a safety precaution to minimize the chance that you’ll “blow out” a port bit by mistakenly connecting an output bit to a supply voltage; even if you make this mistake, the resistor would limit the current to safe levels.) 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 QVGA Controller 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.
in the
can be used to access the ports. For example, the command
executes more rapidly than
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
PORTAPORTA is configurable as input or output on a bit-by-bit basis. To configure PORTA, use an assignment statement to write to the DDRA (Data Direction Register A) register. DDRA and all 68HC11 register names are defined in the QEDREGS.H file in the \FABIUS\INCLUDE\MOSAIC directory. Writing a 1 to a bit position in DDRA configures the corresponding port bit as an output, and writing a 0 to a bit position configures the corresponding bit as an input. For example, the following C statement configures PORTA as all outputs:
DDRA = 0xFF; To configure PORTA as all inputs, use the statement:
DDRA = 0x00; If we want to configure bits 0-6 as inputs, and bit 7 as output, we can execute:
DDRA = 0x80; To change the state of an output bit on PORTA of the 68HC11 chip, use an assignment statement with PORTA on the left hand side to write to the port’s data register named PORTA. For example, if PORTA is configured as all outputs, the following C statement sets all PORTA bits high:
PORTA = 0xFF; To read the state of PORTA, use an assignment statement with PORTA on the right hand side to read the port’s data register. For example, the following code fragment reads PORTA and places the results in the variable named latest_porta_state:
static unsigned char latest_porta_state; latest_porta_state = PORTA; PORTEPORTE (named in the QEDREGS.H file) is an 8 bit analog or digital input port. PORTE is configured as a digital input after a reset or restart, and is read in the same way that PORTA is read: simply use it as the right hand side of an assignment statement. For example, to read the digital state of PORTE, your program could execute the statements:
static unsigned char latest_porte_state; latest_porte_state= PORTE; To configure PORTE for analog input, use the function:
AD8On() To turn off the 8 bit A/D and revert to a digital input port, use:
AD8Off() (For experts and the curious: AD8Off() turns the 8 bit analog converter off by clearing the A/D power up bit named ADPU in the OPTION register; AD8On() sets the ADPU bit.) Using the PIAThis section describes how to configure and access the available I/O ports of the Peripheral Interface Adapter (PIA) on the QED Board. PIA Initialization
The function
void InitPIA( int ppa_output_flag, int upper_ppc_output_flag) writes to the PIA configuration register to set the data direction for PPA and the upper 4 bits of PPC. If ppa_output_flag is true (non-zero), InitPIA() configures PPA as output, and if ppa_output_flag is false (zero), it configures PPA as input. Likewise, if upper_ppc_output_flag is true, InitPIA() configures the upper four bits of PPC as output, and if upper_ppc_output_flag is false, it configures upper PPC as input. InitPIA() sets the direction of PPB as output and lower PPC as input to ensure compatibility with the built-in keypad and high current driver interfaces. It clears bits 5, 6 and 7 of PPB which control high current driver outputs HC1, HC2, and HC3. Warning! There may be a short transient ON condition on the three high current outputs during power-up and reset. The state of the PIA chip can not be controlled when it is initially turned on or reset. A consequence of this is that in the interval of time between power-up and the operating system’s initialization of the output to an OFF condition, there may be a short transient ON. You may need to take appropriate precautions in critical applications. Additionally, if the specified PIA configuration is different than the prior configuration, InitPIA() writes to the PIA’s configuration register and this automatically zeros any outputs in PPA or upper PPC, even if the direction of PPA or PPC was not changed! If the specified input/output configuration of the PIA is the same as the prior configuration, InitPIA() does not modify the PIA configuration register, and thus does not change the state of any output pins in PPA or upper PPC. But, if the specified PIA configuration is different than the prior configuration, InitPIA() writes to the PIA’s configuration register and this automatically zeros any outputs in PPA or upper PPC, even if the direction of PPA or PPC was not changed! Consequently, InitPIA() may disrupt in-progress operations involving the 12 bit A/D, keypad, or display. Consult the PIA data sheet for details of the PIA operation. 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:
Accessing PIA Ports PPA, PPB and PPC
Because the timing of the PIA chip are slightly too slow for simple assignment-statement accesses to be “guaranteed by design” at a 16 MHz clock speed, a set of access functions has been defined that inserts a wait state while the PIA is being accessed. This guarantees reliable performance over all device variations and temperature extremes. To access the ports of the PIA (Peripheral Interface Adapter) chip, use the following functions defined in the PIA.H file and described in the Control-C Glossary:
void PIAStore( uchar c, xaddr address ) uchar PIAFetch( xaddr address ) void PIAChangeBits( uchar data, uchar mask, xaddr address ) void PIAClearBits( uchar mask, xaddr address ) void PIASetBits( uchar mask, xaddr address ) void PIAToggleBits( uchar mask, xaddr address ) The three PIA port addresses are also defined as macros in the PIA.H file:
#define PPA_ADDRESS ((xaddr) 0x8080) #define PPB_ADDRESS ((xaddr) 0x8081) #define PPC_ADDRESS ((xaddr) 0x8082) where “xaddr” is a 32-bit extended address type specifier defined in the TYPES.H file. These functions are easy to use, as illustrated by the following brief examples. If your program has called InitPIA() to configure PPA as an output port, it can store the value 0x55 to the port by executing the C statement:
PIAStore(0x55, PPA_ADDRESS); You can set the least significant bit in PPA by calling:
PIASetBits(0x01, PPA_ADDRESS); where 0x01 is a mask; the 1’s in the mask specify which bits are to be set. Your program can invert the state of the lower 4 output bits in PPA using the statement:
PIAToggleBits(0x0F, PPA_ADDRESS); Again, 0x0F is a mask; the 1’s in the mask specify which bits are to be toggled, and the 0’s in the mask specify bits that are to be left unchanged. If you’ve configured upper PPC as an input port, you can read its value with the statements:
static unsigned char nibble_contents; nibble_contents = PIAFetch(PPC_ADDRESS); The upper 4 bits of nibble_contents will then contain the upper PPC input values. Characteristics of the PIA’s I/O PortsThe 82C55A peripheral interface adapter (PIA) chip is the industry standard part for providing digital I/O ports. 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 InitPIA() described earlier 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. InitPIA() configures PPB as an output and the lower half of PPC as an input. 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 InitPIA() 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. Using the High Current DriversFour N-channel MOSFET high current drivers are available at the Supplementary I/O connector. Each driver can sink up to 150 mA continuously, or up to 1 amp on an intermittent basis at voltages as great as 60 V. Onboard snubber diodes suppress inductive kickback, so the drivers can be used to control solenoids, motors, and other inductive loads. Figure 8‑1 shows how to connect a DC load (a DC motor is shown) to the MOSFETs.
Figure 8‑1 Connecting a DC load (for example, a DC motor) to the high current drivers using onboard power (left) and using external power (right). HC0 is controlled by a PAL signal and HC1 - HC3 are controlled by the PIA port bits PPB5 - PPB7 respectively. NOTE: Upon power-up and reset, the high current MOSFETs, HC1 - HC3, may momentarily sink current until the QED-Forth startup software initializes them. The PAL-controlled HC0 output does not exhibit this transient turn-on behavior at startup. Two simple functions control these four high current drivers:
void ClearHighCurrent( uchar mask ) void SetHighCurrent( uchar mask ) SetHighCurrent() accepts a 4-bit mask and turns on the drivers that correspond to "1"s in the mask. ClearHighCurrent() accepts a 4-bit mask and turns off the drivers that correspond to "1"s in the mask. Note that "turning on" a driver allows it to sink current, thereby pulling the voltage at the output pin towards ground. "Turning off" a driver prevents it from sinking current. For example, to turn on all four high current drivers, execute
SetHighCurrent( 0x0F )
Then, if you execute
ClearHighCurrent( 0x01 )
you will turn off driver number 0 while leaving the state of the other three drivers unchanged.
You can verify the operation of the high current outputs by connecting a pullup resistor (say, 1 kOhm) from the output to +5V and measuring the output voltage with a voltmeter. Note that the output voltage goes LOW when the output is ON (sinking current to ground), and the voltage goes HIGH when the output is OFF (no current flowing in the load resistor). Using Uninterruptable OperatorsThe Importance of Uninterruptable Operators
| ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||