next up previous
Next: Mechanical Switches Up: Analog and Digital Interfacing Previous: Analog and Digital Interfacing

Input/Output Ports

A micro-controller communicates with the outside world by either

The "pins" are those pins shown on the pinout of the MicrStamp11. We refer to these as input/output or IO pins.

Recall that the IO pins of the Motorola 68HC11 micro-controller IC are arranged into four 8-bit ports. Each of these ports is directly connected to a hardware register that is memory mapped into RAM address space. As a result all IO ports are memory mapped. The actual addresses for these IO ports are associated with logical names such as PORTA, PORTB, PORTC, and PORTD. If you take a look at the hc11.h include file that is input as part of kernel.c, you'll see the following declarations of the form

#define PORTA   *(unsigned char volatile *)(_IO_BASE+0x00)
This declaration associates the logical name PORTA with the physical address _IO_BASE+0x00. In the MicroStamp11, _IO_BASE has the value 0x00.

These ports serve as either inputs or outputs for the micro-controller (hence the name IO port). At a given time, however, a pin can only act as either input or output. This means that each pin has a distinct direction state. A pin cannot be used for input and output at the same time. In other words, the directional states input and output are mutually exclusive. In other words, once you've decided to output a voltage on pin 3 of PORTA, you cannot go ahead and try to read that voltage. You must actually reset the direction state of that pin before attempting to read the pin's logical state.

We can think of each pin on an IO port as a single bit in an 8-bit binary number. If PORTA is in its output state, then setting a bit in PORTA high, gives it the logical value 1. Because this bit is directly mapped to the IO pin, then setting a bit in PORTA high causes the voltage on the associated pin to +5 volts. Setting a bit low in PORTA gives that bit the logical value of zero and causes the output pin to be set to ground (0 volts).

As an example, let's consider the program you wrote in the MicroStamp11 familiarization learning module. In that program you used the following instruction on PORTA

 PORTA = 0xFF;
This instruction sets all bits of PORTA "high". PORTA is the logical name for MicroStamp11 pins 1-8 (PA7-PA0). The hex number 0xFF corresponds to the binary number 11111111, which means that all 8 bits of PORTA have been set to one (high). As a result all pins on PORTA whose direction state is "output", would be set to +5 volts. Similarly, if we had wanted to set all output pins on PORTA low, we would have used the instruction
PORTA = 0x00;

The programmer can control a pin's direction state by setting an appropriate bit in a direction register. Direction registers are hardware registers in the 68HC11 that are also memory mapped into the device's RAM address space. Rather than accessing the registers by their absolute addresses, the programmer would use the addresses logical name. These logical names are defined in hc11.h (definitions have the same form that we saw earlier for the IO port addresses). The logical name for PORTD's direction register is DDRD. If the $i$th bit in DDRD is set high (1), then bit PDi is treated as an output port. If the $i$th bit in DDRD is set low (0), then bit PDi is treated as an input port. Figure 14 illustrates how DDRD effects the IO directions of PORTD. In this figure, we set DDRD to 0x4E and we set PORTD to 0xC3. The logical values output by the physical pin is shown on the figure as either a 1 or 0. If the IO pin has been marked with an asterisk, then its output value is unspecified because the pin's direction state has been set to "input".

Figure 14: DDRD direction register
\begin{figure}\centerline{\psfig{file=figs/direction-register.eps,width=2.5in}} \end{figure}

The preceding discussion showed how to set the IO direction state for PORTD. What about PORTA? Not all of PORTA's IO pins are bidirectional. In fact, only two pins (PA3 and PA7) can have their direction states set by the programmer. The other pins on PORTA are tied to specific timer interrupt functions that fix the pin's direction state as either input or output. For the pins PA3 and PA7, the programmer can set their direction state by setting the appropriate bits in the hardware register PACTL. In particular, the logical names for the direction bits in PACTL are DDRA7 and DDRA3. Bit DDRA7 sets the direction state of pin PA7 and bit DDRA3 sets the direction state of pin PA3.

As mentioned above, only pins PA3 and PA7 on PORTA are bidirectional. The other pins in PORTA have fixed directional states. In particular, pins PA4 to PA6 are always output pins whereas pins PA0 to PA2 are always input pins.

You can access all of the PORTA pins on the MicroStamp11 module. All of the PORTD pins are bidirectional, but you can only access six of PORTD's pins on the MicroStamp11 (PD0-PD5). This means that you have a total of 8 bi-directional pins, 11 output pins, and 11 input pins on the MicroStamp11.

The logical state of an input pin (high or low) can be determined by examining the appropriate bit in the port's logical name (PORTA or PORTD). Because the ports are memory mapped, we don't need to waste memory cycles fetching the port's state, we simply need to check the value of the bits in memory. As an example, let's assume that we want to check the logical state of pin PA1. Since pin PA1 is always an input pin, we don't need to explicitly set its input state. So we could check the bit's logical state with the following code segment

 if((PORTA & 0x02) == 0){
   OutString("PA1=Low");
 }else{
   OutString("PA1=High");
 }
The conditional test takes the logical-and of PORTA and the binary number 0x02. The result of the "and" operation is to produce one of two numbers. The result is 0x00 if the second bit in PORTA is low or we get 0x02 if the second bit in PORTA is high. Note that if we had wanted to check the logical state of pin PA3, we would first need to set the pins direction state to input before attempting the test the bit. In other words, we would need to use the code segment
   PACTL |= DDRA3;
   if((PORTA & 0x08)==0){
     OutString("PA3=Low");
   }else{
     OutString("PA3=High");
   {
Note that we set the DDRA3 bit in PACTL using the incremental-or operation |=. This instruction, of course, is equivalent to PACTL = PACTL | DDRA3.

To conclude our discussion of the IO ports of the MicroStamp11, we now illustrate the hardware registers used in controlling the direction state of the IO ports. These registers along with the logical names of their bits will be found in figure 15.

Figure 15: IO and direction registers
\begin{figure}\centerline{\psfig{file=figs/io-register.eps,width=4in}} \end{figure}


next up previous
Next: Mechanical Switches Up: Analog and Digital Interfacing Previous: Analog and Digital Interfacing
Bill Goodwine 2002-09-29