One Byte at a Time Part 2 (PIC Microcontroller)

The maximum current into or out of Ports A, B and E combined is 200 mA with the same figure being specified for Ports C and D in total, subject to the global IDD and Iss figures and individual pin limitation.

Port pins configured as inputs with normal TTL buffer inputs (Port A except RA4 and PortB) recognize an input as low where V|L < 0.5 V and a high for an input VIH > 2 V. Ports with Schmitt trigger input buffers (RA4 and Ports C upwards) have a VIL of 0.2VDD (1V for VDD = 5 V) and VIH of 0.8VDD (4 V for VDD = 5 V).

The block diagram of Fig. 11.1 is a typical representation of a parallel port I/O bit. Specific ports may vary in ways that can affect the electrical performance in a significant manner; especially Ports A and B.

Port A I/O pin driver structure.

Fig. 11.5 Port A I/O pin driver structure.

Looking first at Port A, specifically RA3:0 and RA5, which are illustrated in Fig. 11.5(a), we see that the TRIS buffer is implemented using a series N-channel/P-channel field effect transistor totem pole.


• Where the TRIS bit is logic 1 the lower AND gate has a logic 0 output and the upper OR gate has a logic 1 output. In this situation, both transistors TRN and TRP are non conducting and the state of the Data flip flop is isolated from the I/O pin. In this situation the port bit is configured as an input.

• Where the TRIS bit is logic 0 then the complement state of the Data flip flop is gated through to both totem-pole transistors. With D low, TRN conducts and TRP is off giving a low pin voltage. With D high, TRP conducts and TRN is off giving a high pin voltage. In this situation the pin follows the state of the Data flip flop with current being sourced or sunk through the relatively low resistance active conducting transistors.

As an example, consider the situation where an electromagnetic relay is to be activated from pin RA0 and requires a 200 mA activation current at 12 V. For currents and voltages of this magnitude we need external buffering. In Fig. 11.5(d) a bipolar transistor acts as an external switch. If the minimum gain of this transistor is 100 then a 1.8kQ resistor will give a base current of 2 mA assuming a base-emitter conduction voltage of 0.7 V and a PIC VOH of at least 4.3 V.

The output of RA4 shown in Fig. 11.5(c) is somewhat different in that only the bottom totem-pole transistor is implemented. As opposed to the 3-state structure of Fig. 11.5(a), this structure has only two states; that is active logic 0 and open-circuit. This type of output is known as open drain (or open-collector), see Fig. 2.3.

• When the TRIS flip flop is logic 1 , its reset state, then the AND output is low and TRN is off with the output pin high resistance. RA4 is then set to input.

• When TRIS is logic 0 the output transistor conducts when the Data flip flop is logic 0 giving an active-low output. When the Data is logic 1 , TRN is off and the output floats.

An open-drain output cannot source current; either the load itself must be connected from the output pin to a positive voltage or an external pull-up resistor used as a load for the on-chip transistor. This is the case in Fig. 11.5(d) where the base current for the external transistor is derived from the 1.8kQ pull-up resistor when RA4 is off.

There is one further difference between RA4 and RA0:3/RA5. The distinction is in the use of a Schmitt trigger buffer to give a better noise immunity when RA4 is used as the input to Timer 0 – see Fig. 13.3.As a consequence, logic levels into RA4 are different to other Port A (and PortB) inputs. If RA4 is to be used as the Timer 0 input, it is usually configured as an input. If configured as an output, then in this situation PORTA[4] must be set to logic 1, which will disable the open-drain transistor and prevent interaction between it and the external clock input to the Timer.

Many applications involve reading the state of arrays of switches. Rather than use the relatively more expensive single-pole double-throw (SPDT) switch arrangement of Fig. 11.6(a) to give the two logic states, most switches; for example, those in the keypad of Fig. 11.8, are single-throw (SPST) types. In these situations an external pull-up resistor is needed to convert the open-circuit state to a high voltage, as shown in Fig. 11.6(b). A similar situation arises when open-drain/collector electronic devices, such as phototransistors, are to be read by a port. The value of such pull-up resistors should not be too low, as a large current will flow through the switch when closed, nor too high to reduce noise induced by electromagnetic means from external sources. A good compromise is in the range 10 – 100 kQ.

Interfacing switches to a port line.

Fig. 11.6 Interfacing switches to a port line.

In order to simplify the interface of such devices, PortB inputs have optional internal pull-up resistors. These internal resistors are called weak pull-ups as their typical equivalent values of around 20 kQ is high enough not to interfere with devices being read which have ‘normal’ logic low and high outputs.

PortB's weak pull-up option.

Fig. 11.7 PortB’s weak pull-up option.

We see from Fig. 11.7 that the internal pull-up resistors (actually a P-channel FET) are switched in only if RBPU (Register B Pull Up, bit 7) of the Option register is low. Although all eight pull-ups are qualified by RBPU only those pins configured as inputs (TRIS[n] = 1) will have the resistor switched in. RBPU resets to 1 and so the pull-up resistors default to off.

As a typical application of weak pull-ups, consider the problem of reading a keypad, such as that illustrated in Fig. 11.8(a). In this particular example there are 12 switches and rather than use up all these scarce I/O pins it is hardware efficient to connect these switches in the form of a 4 x 3 matrix, as illustrated in Fig. 11.8(b). This 2-dimensional array reduces the I/O pin count to 7. Larger keypads show an even greater efficiency gain, with a 64-contact 8 x 8 keyboard needing only 16 I/O pins.

Interfacing to a keypad.

Fig. 11.8 Interfacing to a keypad.

Although there are variations on this theme, the topology shown here is typical. The four rows are read in via RB7:4 with internal pull-up resistors enabled. The three columns connected to RB1:3 can be individually selected in turn by driving the appropriate pin low, thus scanning through the matrix. The switch contacts are normally open and, because of the pull-up resistors, read as logic 1 . Should a switch connected to a low column line be closed then the appropriate row line is low. This means that once the closed key row has been detected the column:row intersection is known. The 330 Q resistors limit the current through the switch should one of the RB7:3 pins accidentally give a low output due to erroneous software.

In order to tie these concepts together, consider a subroutine to interrogate the keypad and return either with the key pressed (or at least the first key found if more than one) or if no key then -1 (i.e. FFh). Before looking at the coding we can assume that somewhere in the main software Port B has been configured appropriately with the correct input and outputs assigned and that bit RBPU in the Option register has been cleared. Something like:

tmp9118_thumb_thumb

The listing of Program 11.1 is based on the task list:

tmp9119_thumb_thumb

Basically the sequence of operations is to begin with a count of one; i.e. key[1], and bring column[0] low. As each row is checked for a zero, the count kept in the Working register is advanced by 3 (lines 21, 24, 27) to reflect the three keys in each row. If no closure (that is a 0) is found, the column key tally in memory at KEY_COUNT is advanced by one (i.e. one column) and the next column tried. There are two ways out of the loop.

• If a 0 is found during the scan, the count in W is the desired value and the subroutine immediately returns (lines 20, 23, 26, 29).

• If the column pattern shift in line 36 results in the sample 0 arriving in bit0 then the subroutine returns FFh to show no key has been found.

In the real world a subroutine like this would often read in rubbish due to switch bounce and possibly noise induced in the connections between keypad and the electronics.

One way of filtering out this unpredictability is shown in the subroutine of Program 11.2. Here the state of the keypad is interrogated using

Program 11.1 Scanning the keypad.

Program 11.1 Scanning the keypad.

By keeping the state of the previous reading in Data memory, any change can be detected. Only if no change over 256 readings occurs will subroutine GET_IT return with the keypad state. Depending on the quality of the keypad, ambient noise and processor speed, the outcome can be improved at the expense of response time by including a short delay in the loop, or by using a 2-byte stability count.

Program 11.2 Noise filtered keypad scanning.

Program 11.2 Noise filtered keypad scanning.

 

Given that RB0 doubles as the hardware INT input,6 it is possible to interrupt the processor when any key is pressed. By bringing RB3:1 all low and ANDing all four rows, any key closure will result in the AND gate going low. This can in turn drive the RB0/INT pin and either force the processor into its interrupt service routine or at the very least set the INTF flag in the INTCON allowing the processor to poll for keypad activity.

Another approach to an interrupt-driven keypad interface is to use the Port B Change feature shown in Fig. 11.9. The top four Port B I/O pins have a second D latch in parallel but in anti-phase to the usual input Capture latch. When the CPU reads Port B the Capture latch samples the state 6Note from Fig. 11.7 that the internal interrupt logic is activated via a Schmitt trigger buffer as opposed to the regular PortB TTL buffer.

The Port B change feature.

Fig. 11.9 The Port B change feature.

Next post:

Previous post: