Link here

Digital and Timer-Controlled I/O

Overview of available digital I/O

The 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. The following table summarizes the digital I/O available, its alternate uses, and port assignments.

The QVGA Controller’s Digital I/O
I/O Lines Type Port Address Comments / Alternate Uses
8 Configurable either as all digital inputs or outputs PPA 0-7 Initialized on start-up and resets as inputs.
5 Digital outputs PPB 0-4 Initialized as outputs, but if the high-current drivers that use PPB 5-7 are not needed, PPB may be software reconfigured to all inputs.
4 Open-drain high-current outputs PPB 5-7 and PAL bit
4 Digital inputs PPC 0-3 Initialized on start-up and resets as inputs, but may be reconfigured as all outputs.
3 Configurable either as all digital inputs or outputs PPC 5-7 Initialized as inputs but if RS485 is used PPC5-7 must be reconfigured as outputs.
6 Timer-controlled inputs or outputs including 3 input-capture, 3 output-compare, and pulse accumulator PA 0-2, 5-7 Bit-by-bit configured by the application as inputs or outputs, including:
Timed inputs: PA 0-2
Timed outputs: PA 5-7
Pulse accumulator: PA 7
30 Digital I/O lines

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 the following that are committed to other services on the controller:

Committed I/O pins
Service Port Pins
RS-485 PIA PPC PPC 4
8-bit A/D CPU PORTE PE 0-7
Serial 2 CPU PORTA PA 3-4
SPI CPU PORTD PD 2-5

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. The following table 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.

Additional digital I/O lines made available if other services are forfeited
Services Used Digital I/O Available
Inputs Outputs Total
RS485 8-bit A/D Serial 2 SPI Initial Max Initial Max
Yes Yes Yes Yes 21 21 9 30 30
No Yes Yes Yes 22 22 9 31 31
No No Yes Yes 30 30 9 39 39
No No No Yes 32 32 9 41 41
No No No No 36 36 9 45 45

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. The above table 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.

The following table 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.

Digital I/O Port Addresses and Configurability
Port Name Address (HEX) I/O Line Configurable As Alternate Use (Signals Used)
68HC11:
PORTA 8000 8 Bitwise I/O Serial2:   PA3 & PA4 (2)
Pulse accumulator:  PA7 (1)
Timed inputs: PA0-3 (3 or 4)
Timed outputs: PA3-7 (4 or 5 )
PORTD 8008 4 Bitwise I/O SPI controls AD12 & DAC (4)
PORTE 800A 8 Bytewise digital or analog input 8 bit A/D: PE0-7 (8)
PIA:
PPA 8080 8 Bytewise I/O
PPB 8081 8 Bytewise I/O High Current Outs: PPA5-7 (3)
PPC lower 8082 4 Nibblewise I/O Keypad Inputs: PPC0-3 (4)
PPC upper 8082 4 Nibblewise I/O RS485: PPC4 (1)

The following table specifies the named data direction register which controls the input/output direction, or specifies the functions that configure each digital I/O port.

Digital I/O port data direction registers and configuration functions
Port Name Configured By
68HC11:
PORTA DDRA
PORTD DDRD
PORTE AD8On()
AD8Off()
PIA:
PPA InitPIA()
PPB InitPIA()
PPC lower InitPIA()
PPC upper InitPIA()
 

Using the digital I/O ports on the 68HC11 chip

This 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.

 

PORTA

PORTA 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;
 

PORTE

PORTE (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 PIA

This 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[pkc4]. 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:

Port Direction
PPA input
PPB output
lower PPC input
upper PPC input
 

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 ports

The 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 drivers

Four 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.

The following fibure shows how to connect a DC load (a DC motor is shown) to the MOSFETs.
dc motor control

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 operators

Why use uninterruptable operators?

Care must be taken when performing "read/modify/write" operations in applications that use interrupts or multitasking. Operations such as setting or clearing individual bits in a byte while leaving other bits unchanged are called "read/modify/write" operations because they involve reading the port, modifying the read contents, and writing the result back to the port. Unpredictable results can occur if more than one interrupt service routine or task tries to access a single port or memory location at the same time using a read/modify/write sequence. The simplest solution to this problem is to access the memory location or port using an "uninterruptable" read/modify/write operator.

The following scenario illustrates the importance of 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 PORTA. Assume that TASK1 is controlling the state of bit 4, and TASK2 controls bit 7. Let’s assume that bit 4 is low when TASK2 tries to execute the following code:

static unsigned char mask = 0x80;
PORTA |= mask;

TASK2 is merely trying to set the top bit in PORTA to 1, but this statement may have unintended consequences. The compiler generates code that reads the contents of PORTA, performs a bitwise OR with the contents of mask, and stores the result back into PORTA. 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 final store to PORTA is executed. Unfortunately, this store command erroneously sets bit 4 back to the low state! TASK2 was interrupted after it read the state of PORTA but before it had a chance to write the new contents, so it undoes the change that TASK1 made in the state of PORTA bit 4! This can indeed cause problems in an application program.

 

Pre-coded read/modify/write functions

The pre-coded PIA and High Current Driver read/modify/write functions described earlier in this chapter avoid this problem by disabling interrupts for ten to sixteen cycles (2.5 to 4 microseconds at a 16 MHz crystal speed). This prevents the corruption of the contents when different tasks or interrupts share access to a single location. The following functions are uninterruptable:

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 )
void  ClearHighCurrent( uchar mask )
void  SetHighCurrent( uchar mask )

Additional uninterruptable operators are declared in the XMEM.H header file in the \MOSAIC\FABIUS\INCLUDE\MOSAIC directory; these routines are described in detail in the Control-C Glossary.

 

Create your own uninterruptable functions

It is easy to create your own uninterruptable functions using the _protect keyword. For example, the following uninterruptable function sets specified bits in a port or memory byte:

void _protect  SetBitsUninterrupted( uchar mask, char* address )
{  *address |= mask;
}

In response to the _protect keyword, the compiler ensures that interrupts are temporarily disabled while SetBitsUninterrupted() is executing, and that the global interrupt mask (the I bit in the condition code register) is restored to its prior state after the function terminates.

Simple stores to and fetches from 1-byte or 2-byte memory locations are intrinsically uninterruptable because they are implemented with single assembly-language opcodes. However, the 68HC11 processor does not have a single opcode that can access a 32 bit memory location. Thus, problems can arise when one task writes to a floating point or long 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. In these cases uninterruptable operators should be used. An example is presented by the functions named:

PeekFloatUninterrupted()
PokeFloatUninterrupted()

which are defined using the _protect keyword in the TURNKEY.C program in the \MOSAIC\DEMOS_AND_DRIVERS\MISC\C EXAMPLES directory; this program is discussed in detail later in this book.

 

Connecting hardware to the digital I/O lines

You may connect to the digital I/O lines by connecting IDC ribbon cable sockets to heaer H3 on the QED Board (for port PPB, the lower nibble of PPC, and high current drivers), or to header H2 on the QVGA Board (for processor port PA, PI A port PPA, and the upper nibble of PPC). In either case, you should connect only to the I/O signals on the connector, and not to the system control lines, data or address lines, clock, or SPI lines.

Do Not Connect to System Control Signals

When connecting to the Digital I/O Connector (H2 on the QVGA Board) with a ribbon cable, notch out cable wires 11 through 24. Even short pieces of wire connected to some of these lines may cause intermittent operation of the touchscreen or processor.

When connecting to the Supplemental I/O Connector (H3 on the QED Board) with a ribbon cable, only connect the wires you need, and do not connect to the data bus lines or system control lines.

 

Electrical characteristics of the 68HC11’s I/O ports

On the QVGA Controller the processor’s ports A and D are available for you to connect to external devices. You can use them to directly drive LEDs, relays, transistors, opto-isolators or other digital logic devices. But please be careful -- whenever these outputs are connected to external devices you must stay within the voltage and current capabilities of the output pins. Because the MC68HC11 reference manuals don’t specify the electrical capability of these ports very well we provide some additional information here.

The electrical characteristics of the 68HC11F1’s digital I/O signals are specified in detail in section 13.4 of the MC68HC11F1 Technical Data Manual. 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.

 

Protecting the input and output pins

These output pins are very useful because they can directly drive a wide range of devices. Nevertheless, any circuitry connected to the processor should take care to:

  • Prevent excessive voltage levels at the pin; and,
  • Prevent excessively great currents.

We’ll address each of these concerns in turn.

 

Preventing excessive voltages

Excessive voltages are prevented by ensuring that voltages of less than a diode drop below VSS (-0.6 V) or greater than a diode drop above VDD (VDD+0.6 V ) are never applied to the processor. For some applications, particularly when driving inductive loads such as relays, you may need to provide Schottkey diode clamps between the pin and VDD and between the pin and ground. All pins on the processor have inherent diode clamps to the processor’s ground voltage, VSS, but it is best not to rely on these; if there is the possibility of the output pin being driven to a negative voltage level it is better to prevent excessive power dissipation in the processor package by externally clamping the voltage to ground (VSS) with a Schottkey diode. Processor ports A and D also have inherent diode clamps to the chip’s +5V supply voltage, VDD, but it is likewise better not to rely on these; instead external Schottkey clamps to VDD should be used.

 

Preventing excessive currents

The current into or out of any pin on the MC68HC11 should also be limited to prevent damage. The specified maximum current is 25 mA into or out of any one pin at a time, although these pins can typically withstand transients of more than 100 mA at room temperature. In driving more than one pin at a time it is necessary only to stay within the processor’s maximum power dissipation. Unfortunately, Motorola doesn’t specify what this maximum is, but we recommend that you don’t exceed a total of 100 mW for all processor I/O pins combined. The chip’s total power dissipation is the sum of its internal power (which varies from device to device so much that it can only be determined by actually measuring it, but which is specified at less than 150 mW) and the power associated with the I/O pins. Pin currents must be limited using external resistors.

 

Output pin V-I characteristics

The output pins of the MC68HC11 are similar in electrical characteristics to the SN54/74HC digital logic family. They can source or sink up to 25 mA and are guaranteed to source 0.8 mA while providing a valid logic high and to sink 1.6 mA at a valid logic low, although they generally do much better. A valid logic high level is between VOH = VDD and VOH = VDD - 0.8 V, and a valid low level is between VOL =VSS = 0 V and VOL =VSS + 0.4 V. As the output is loaded, the VOL and VOH levels rise or fall. It is often useful to know just how much to expect the VOL and VOH levels to degrade with current. For currents of less than 10 mA the voltage change is linear with current; that is, it can be modeled as a voltage source of either zero or five volts and an equivalent series resistance of 40 ohms. At greater output currents the resistance increases until at the greatest specified current for any one pin, 25 ma., the equivalent resistance is 60 ohms. At this current the voltage degradation of the VOL or VOH is 1.5 volts. Figure 8-2 and Figure 8-3 illustrate this variation.

These figures can be used to choose component values for particular circuits. For example if we wish to use a pin of Port A or D to drive a light-emitting diode we would place the LED in series with a resistor and connect them between an output pin and ground. The resistor limits the current, to the LED. From the LED data sheet we note that its forward voltage at a current of 10 mA is specified to be 2.2 V. What should the resistor value be? We calculate it as,

      R = (VOH - 2.2 V ) / 10 mA

Consulting the VOH vs I curve for the output pin we find that at 10 mA VOH = 4.4 V. We therefore need a resistance of 220 ohms.

digital output high side

Degradation of the Port A or Port D output high voltage with current.
The maximum current allowed for continuous operation is 25 ma.

digital output low side

Degradation of the Port A or Port D output low voltage with current.
The maximum current allowed for continuous operation is 25 ma.
 

Programmable timer and pulse accumulator

The processor’s output compare functions

The processor’s programmable timer subsystem contains 5 output compare (OC) functions (named OCx for x from 1 to 5) associated with PORTA output pins PA7 through PA3 (in descending order). These output compare functions allow you to specify actions that take place at particular, well determined times. Using output compares, it is easy to set up real-time clocks, cause periodic execution of code, and generate precisely timed synchronous or asynchronous waveforms. They can be used to implement a stepper motor controller, pulse generator, pulse width modulation (PWM) signals, precisely timed output pulses, timesliced multiplexing, or serial communications.

Output-compare functions work by automatically changing PORTA output pins and/or invoking an interrupt service routine (ISR) whenever the contents of a free-running 16-bit counter (TCNT) matches the contents of user-set output-compare registers, TOCx. When these contents match, we say that a "successful output compare" has occurred. Thus the programmer can precisely specify a future time at which an action will occur by simply storing the time as a 16-bit value in the appropriate output compare register, TOCx. The free running counter counts at a programmable rate, from 0 to 65536, then rolls over to zero and continues counting. Its rate is one count each 2 microseconds, for a rollover period of 131.072 milliseconds. Consequently, you can set up output compares to trigger events with a resolution of 2 microseconds, and up to 131.072 milliseconds into the future (or arbitrarily longer if you keep track of rollovers on TCNT).

Because TCNT is clocked by a prescaler driven from the system E clock, you can change the count rate by modifying the prescaler’s division ratio, from its current value of 8 to 1, 4, or 16, changing its rollover period to 16.384, 65.536, or 262.144 milliseconds. If you do though, the system timeslicer will be affected. We find that a 2 microsecond tick rate provides sufficient resolution for most applications.

Each of the five output compare subsystems has a 16-bit TOCx register, a successful compare OCxF (interrupt) flag, and an interrupt mask OCxI, where "x" is the output compare number. OC1 can control any of pins PA3 through PA7 and it has its own register to specify which of PORTA pins are affected. Output compares OC2, OC3, OC4 and OC5 each control a single pin. They each have a pair of output mode/level bits, OMn and OLn, which determine the effect that each successful compare has on PORTA bits PA6, PA5, PA4, and PA3 respectively. The processor automatically sets an output compare’s OCxF flag bit in the TFLG1 register when the contents of the TCNT register and the OC’s TOCx register are equal. At the same instant, the state of the associated PORTA pin is set, cleared, or toggled as specified by the output mode bits. In addition, if the output compare’s OCxI mask bit in the TMSK1 register is set, an interrupt is recognized when a successful compare occurs.

An active output compare function can cause a signal change on a PORTA pin at a specified time T, and/or trigger an interrupt at time T:

Signal Change – To cause a signal change on a PORTA pin when time T equals the contents of TCNT, the PORTA pin must be configured as an output, and the output compare function must be enabled. OC1 is enabled by storing the data to be output in OC1D and specifying the pins to be changed in OC1M, and OC2-OC5 are enabled simply by storing a 2-bit code into TCTL1 specifying the desired signal change. Using the CFORC register, it is also possible for software to immediately force a state change on a timer-controlled signal without causing an interrupt.

Interrupt – To trigger an interrupt when time TCNT = T, an interrupt handler must be installed, and the output compare’s local interrupt must be enabled by setting bits in TMSK1.

Output Compares and their properties
Output Compare Controlled PORTA Pin Comparison Register Comments and Alternate Use
OC1 PA3, 4, 5, 6, and/or 7 TOC1 May control multiple pins simultaneously, or be paired with another OC to jointly control pin PA3, 4, 5, or 6.
OC2 PA6 TOC2 The OC2 timer is used by the kernel’s timeslicer and elapsed time clock functions. If you do not use these functions, pin PA6 may be controlled by OC1 or used for general purpose I/O.
OC3 PA5 TOC3 Not used by the kernel.
OC4 PA4 TOC4 Used as an output by the secondary serial port. Available if you do not need Serial 2.
OC5 PA3 TI4O5 Shared with Input Capture 4, which is used as an input by the secondary serial port. Available if you do not need Serial 2.

As summarized in the above table, the output compares are not all identical in function, and some are used by the operating system. OC1 and OC5 differ from the others slightly in function, OC2 is used by the operating system’s timeslicer, and OC4 and OC5 are used by the secondary serial port:

OC1 is special in that it can synchronously control any of PORTA pins PA7, PA6, PA5, PA4, and PA3. Even when OC1 is used to control several PORTA pins, the timer and interrupt functions of those pin’s output compares may still be used independently of the pin (to implement clocks, etc.). While the other output compares can be used to set, clear, or toggle an output pin, OC1 can be used only to set or clear a pin, but not to toggle it.

OC2 is used by the timeslicer. Consequently, if you need the services of the timeslicer (timesliced task switching, elapsed time clock, or BENCHMARK: function) make sure that you do not use OC2 for other functions. Even if you do use the timeslicer, pin PA6 is still available for use as general purpose I/O, or as an output controlled by OC1.

OC4 is used as an output by the secondary serial port, so you can’t use it or its associated pin PA4 if you need the second RS232 serial link.

OC5 shares its timer register and output pin with input capture 4 (IC4). OC5 operates like the other output compares, but it must be initialized by clearing the I4/O5 bit of the PACTL (pulse accumulator control) register before it may be used. Also, IC4/OC5 and associated pin PA3 are used by the secondary serial port, so be sure not to use these resources if you need the second RS232 serial link.

 

Pulse and PWM generation techniques

The processor’s output compare functions provide lots of flexibility for creating single pulses or pulse-width-modulated waveforms. Most methods are variations on this algorithm:

  1. The desired start time of the pulse is programmed by storing an appropriate count in the output-compare register (TOCx) of OCx, and the OCx interrupt is enabled by setting a flag bit in TMSK1.
  2. OCx’s mode/level bits (OMx and OLx) are configured to automatically set the output compare’s corresponding output either high or low, depending on the polarity of the desired pulse (this action enables the output compare).
  3. When the compare occurs, the pin state is automatically changed and an interrupt service routine called.
  4. The interrupt service routine (ISR) reprograms the output compare to automatically change its pin back to its inactive level on the next compare;
  5. The ISR also increments the output-compare register by a value corresponding to the desired duration of the pulse.

Since the pin-state is changed by hardware automatically at specific values of the free-running counter, the pulse width is controlled accurately to the resolution of the free-running counter irrespective of software latencies. By repeating the actions for generating a pulse, you can generate an output signal of a specific frequency and duty cycle. While software latency and execution times do not affect the timing of the waveform, they do impose limits on the frequency and duty cycles attainable. The different methods of generating PWM signals differ primarily on where the software execution times are constrained to fit, either within the on time, the off time, or the waveform’s period as a whole.

The following is a quick summary of some of some specific ways you can use output compares to generate pulses or PWM waveforms. You can find complete descriptions of the registers mentioned in Motorola’s MC68HC11F1 Technical Data Manual. Example 1 shows you how to generate a tirggered pulse, Examples 2 and 3 represent exceptional and instructive methods of generating PWM signals, and examples 4-6 are commonly used PWM methods. Example 6 provides code for generating "failsafe" PWM signals.

PWM Methods
Method ISR Used Output Compares Turn ON/OFF Jitter Duty Cycle Accuracy Duty Cycle Range Rollovers inserted? Period
2 no OC1 and one other OC/OC none perfect any no – failsafe Fixed at 131.072 ms
3 yes any OC ISR/ISR yes limited by ISR delays Ton, Toff >ISR yes on and off times must each be greater than ISR latency and execution times
4 yes any OC OC/OC no perfect Ton, Toff >ISR yes on and off times must each be greater than ISR latency and execution times
5 yes OC1 and one other OC/OC no perfect Ton, Toff unlimited yes P>ISR1+ISR2
6 yes any OC ISR/OC yes perfect Ton unlimited, Toff>ISR failsafe – into only the off time
 

Method 1
Create a single pulse from an external trigger

Suppose you’d like to output a single pulse on PA5 with very precise duration in response to a triggering event, for example the leading edge of an input pulse on PA0. You’d like the output pulse to start a precise, fixed time after the initiating trigger and to last some precise duration, between 2 microseconds and 131 milliseconds. Further, the output pulse should occur after the first occurrence of the trigger (after enabling the system) and then stay off rather than being retriggered by subsequent input pulses.

To do this you would use one input capture (IC3) and two output compares (OC1 and OC3). Because the trigger may occur anytime an input capture is used to determine the precise time of its leading edge. And because the output pulse width must be precisely controlled, and its duration can potentially be shorter than any interrupt service routine, the pulse should be turned on and off by output compares. The input capture invokes an interrupt service routine that enables the output compares. For our example we’ll assume the desired pulse start time is 10 milliseconds (or 5000 TCNT counts) after the trigger is detected, and its duration is precisely 10 microseconds (5 TCNT counts). Here’s one way to do it using three routines:

  • An initialization routine (called ENABLE) that configures and enables IC3 to capture a rising edge on PA0, forces PA5 off to initialize it, and configures and enables OC3 to turn off pin PA5;
  • An interrupt service routine for IC3 (called IC3_ISR) that programs the comparator registers of OC1 and OC3 and enables OC1; and,
  • An interrupt service routine for OC1 (called OC1_ISR) that disables OC1 so that after the output pulse is first turned on it is not turned on again.

Here’s how to write the routines:

ENABLE – Inhibit IC3, OC1, and OC3 interrupts by storing 0x0xxxx0 to TMSK1 (using CLEAR.BITS with a mask of 0xA1). Configure OC1 to set PA5 high on an output compare by setting bit 5 of OC1D, but don’t enable it using OC1M yet – the IC3_ISR will be responsible for doing that. Configure OC3 to clear its associated pin (PA5) on an output compare by storing appropriate mode/level bits (OM3 and OL3), that is xx10xxxx, into the timer control register (TCTL1). Initialize PA5 to the OFF state by forcing an early output compare on OC3. This is done by setting bit 5 of CFORC. Configure and enable IC3 to capture a rising edge PA0. This is done by clearing bit 0 of DDRA (to set the data direction of PA0 to input), and setting the lower two bits of TCTL2 (the two corresponding to IC3) to xxxxxx01 to capture a rising edge. Clear the interrupt flag bit (IC3F) left over from any prior edge detection, if any, by writing a one to IC3F in TFLG1. Finally, enable an IC3 interrupt by setting the IC3I bit in TMSK1.

IC3_ISR – On entering the ISR routine first disable further interrupts by clearing the IC3I bit in TMSK1, and clear the interrupt flag bit (IC3F) by writing a one to IC3F in TFLG1. Then read TIC3 to determine the trigger time, we’ll call it TT. Set up OC1 to turn on output pin PA5 at time TT+5000 by setting TOC1=TT+5000 and configure OC3 to turn it back off just 5 counts later, by setting TOC3=TT+5000. Enable an OC1 interrupt by setting the OC1I bit in TMSK1. Finally enable OC1 and tie it to PA5 by setting bit 5 in OC1M.

OC1_ISR – This interrupt service routine will be invoked when the output pulse is turned on. It only needs to disable OC1 so that further pulses are not produced until the system is re-enabled by executing ENABLE again. Disable OC1 by clearing bit 5 in OC1M. Disable interrupts on OC1 by first clearing the OC1I bit in TMSK1, then clear the interrupt flag bit (OC1F) by writing a one to OC1F in TFLG1.

 

Method 2
Generate a PWM waveform without interrupts

Using two output compares you can generate a PWM waveform of any duty cycle (from 1/65536 to 65535/65536) without using interrupt service routines. As no ISR is used, no software resources are needed to maintain the waveform, and there is no impact on overall system performance. The PWM waveform is free – from a software perspective. So what’s the catch? The catch is that the waveform must have a fixed period, equal to the rollover period of the free-running counter, or 131.072 milliseconds. If you can live with that, here’s how it’s done: Two output compares are used, one sets the output pin at a particular value of TCNT, and the other simply resets the pin at another TCNT value. One of the output compares must be OC1 – because it can be used in conjunction with another to control the same pin. Let’s use OC1 to turn ON an output pin (PA5) whenever TCNT hits 0x0000, and OC3 to turn it OFF whenever TCNT hits 0x1000. More specifically,

  1. Disable interrupts caused by OCs by storing 0x00 to the timer interrupt mask register 1 (TMSK1). Now, output compares will not cause interrupts. Even so, they can still control output pins.
  2. Use OC3 to turn OFF the pulse whenever TCNT=0x1000 (for example, for a duty cycle of 1/16) by storing 0x1000 into TOC3. Configure OC3 to clear its associated pin (PA5) on a successful compare by storing appropriate mode/level bits (OM3 and OL3), that is xx10xxxx, into the timer control register (TCTL1). Now, whenever TCNT hits 0x1000 pin PA5 will be cleared. We configure the OFF transition first because we don’t want the pin to get stuck ON before we’re done configuring our output compares, just in case.
  3. Use OC1 to turn ON the pulse whenever TCNT=0x0000 by storing 0x0000 into TOC1. Associate OC1 with pin PA5 by setting bit 5 in the output compare mask register OC1M. Configure OC1 to set the pin high by storing 0x20 into the OC1 data register, OC1D. Now, whenever TCNT hits 0x0000 pin PA5 will be set high.

Because an ISR isn’t used, there is no possibility of software delays influencing the PWM output.

Advantages: Precise transition time control, all duty cycles possible with 16-bit resolution, no software needed to keep things running, failsafe in that a software crash is not likely to affect operation.

Disadvantages: Only a single channel, only a single PWM period.

 

Method 3
Many PWM channels from a single OC/ISR

What if you want to generate many channels of PWM waveforms, more than there are output compares? In the prior example output compares were used to generate a precisely-timed high-resolution waveform on a single channel without the assistance of an ISR. This example provides the other extreme, an unlimited number of channels of low-resolution PWM signals are generated by a single output-compare-driven interrupt service routine.

The scheme uses a single output compare to periodically invoke an interrupt service routine. The OC is not tied to a PORTA pin, rather it is used only as a dedicated clock that calls the ISR at a fixed interval corresponding to the smallest ON or OFF time that can be produced. Each time the ISR is called it updates all the PWM outputs using any general purpose output pins available. It may do this by reading values from a look-up table, counting, or more computationally.

Because the ISR latency can vary depending on what other interrupt-driven services are running on the controller there is some jitter (or variance) on the transition times, producing a slightly varying PWM duty cycle. This variation can be compensated on the average if the ISR reads TCNT to determine the actual ON and OFF times and modulates the next ON or OFF time to attain the desired PWM duty cycle averaged over a number of cycles – but of course that requires greater execution time.

The sum of the ISR latency and execution times must be less than the difference between adjacent OC times, placing a limit on the smallest ON or OFF time attainable. If the ISR is delayed so long that the next OC time is missed, the next ISR doesn’t occur until TCNT rolls over and another match occurs. Consequently rollover delays of a TCNT period may be inserted into the desired ON or OFF times.

For an example of software generated PWM signals with 8-bit resolution and best averaging properties see "MI-AN-056 Optimal PWM Algorithm" and "MI-AN-058 Using Port PPA for PWM".

Advantages: Any number of channels can be accommodated.

Disadvantages: ISR latency causes jitter in the transition times; ON or OFF times smaller than the ISR latency and execution time are not possible; rollover delays possible if timing criteria not met; not failsafe.

 

Method 4 - One OC/ISR generates "no jitter" PWM signals

The simplest way of generating a precise PWM waveform with arbitrary duty cycle and period is to use a single output compare to automatically turn on and off an output pin and an interrupt service routine that reprograms the output compare after each transition. The "off" transition invokes the ISR which sets up the turn-on time and programs the next output state to be "on", and the "on" transition invokes the same ISR to set up the turn-off time and the next "off" state. The on and off times must each be great enough to contain the latency and execution time of the ISR. So duty cycles that would require very small on or off times are not attainable. If the ISR is delayed so that it does not program the next transition in time, than the output compare doesn’t find a match until TCNT rolls all the way around. In this case rollover delays of approximately 131 msec may be inserted into either the on or off time.

Advantages: Transitions are precise, with no jitter; duty cycle and period are programmable over a wide range.

Disadvantages: ON or OFF times smaller than the ISR execution time and latency are not possible; rollover delays are possible; not failsafe – a software crash can leave the output stuck ON.

 

Method 5 - Make a "no jitter" PWM of any duty cycle from two OCs/ISRs

To obtain ON and OFF times that may be each as small as a single clock tick, two OCs and ISRs are required. The "off" transition invokes an ISR which sets up the next turn-off time, and the "on" transition invokes a different ISR to set up the next turn-on time. Each ISR simply increments the next ON or OFF comparison register by the period. There is no particular restriction on the shortness of the ON or OFF times, either can extend down to just a single count of TCNT, but their sum, the period, must be great enough to contain the latency and execution times of both ISRs. Because OCs are used to drive the output pin, the transition times are exact, with no jitter. If service of either ISR is delayed for more than a period then a rollover delay may be inserted into either the on or off time.

Advantages: Transitions are precise, with no jitter; duty cycle and period are programmable over a wide range, duty cycle extends fully from 1/65536 to 65535/65536.

Disadvantages: Rollover delays are possible; not failsafe – a software crash can leave the output stuck ON.

 

Method 6 - One OC/ISR generates a "failsafe" PWM signal

A single OC and associated ISR is used. The OC invokes an ISR for each transition. For the ON transition, the ISR is responsible for setting the output pin. It also computes the next turn-off time based on the time at which the pulse is actually turned on, and programs the OC to automatically turn it back OFF at the turn-off time. At the next OC the pin is turned off by hardware and the ISR is again called. This time the ISR just sets the turn-on time for the next OC time, disconnecting the OC from the pin so that the pin is not automatically set. This sequence of events produces pulses whose duration is invariant with respect to ISR delay, but that may jitter back and forth within their fixed period. Despite any jitter, the duty cycle and period are both precisely controlled. If the ISR is delayed by more than the off time, rollovers are inserted into only the off time, never the on time. So the pulse on times are failsafe so long as the processor’s clock is running.

Advantages: Failsafe operation assures an ON pulse is never longer than desired and the pulses turn off on a software crash. ON time may be as small as a single TCNT count.

Disadvantages: Pulse position jitter; rollover delays are possible in the OFF time; minimum OFF time must be greater than the IST latency and execution time.

 
This page is about: Using Timer-controlled Digital I/O Ports of 68HC11 Microcontroller, 68HC11 I/O Port Electrical Characteristics, Digital Output Pin Current Voltage Limits, Control Digital I/O from Graphical User Interface – Using the timer controlled digital I/O ports of the 68HC11 microcontroller to generate pulses or measure frequency, input captures, output compares, pulse accumulator, microcontroller pulse counter, 68HC11 PWM pulse width modulation, digital I/O current voltage levels, PWM software generation. PORTA, PORTB, PORTC, PORTD, peripheral interface adapter (PIA), PWM pulse width modulation, OC/ISR, frequency counter
 
 
Navigation