Файл: The quintessential PIC microcontroller (S. Katzen, 2000).pdf

ВУЗ: Не указан

Категория: Не указан

Дисциплина: Не указана

Добавлен: 15.06.2025

Просмотров: 5350

Скачиваний: 0

ВНИМАНИЕ! Если данный файл нарушает Ваши авторские права, то обязательно сообщите нам.

11. One Byte at a Time 279

• 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 o giving a low pin voltage. With D high, TRP conducts and TRN is o 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 bu ering. 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.8 kΩ 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 di erent 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 on page 20.

• When the TRIS flip flop is logic 1, its reset state, then the AND output is low and TRN is o 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 o 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.8 kΩ pull-up resistor when RA4 is o .

There is one further di erence between RA4 and RA0:3/RA5. The distinction is in the use of a Schmitt trigger bu er to give a better noise immunity when RA4 is used as the input to Timer 0 – see Fig. 13.3 on page 365. As a consequence, logic levels into RA4 are di erent to other Port A (and Port B) 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 opendrain 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

280 The Quintessential PIC Microcontroller

33K +5V

+5V

(a) Single-pole double-throw (b) Single-pole single-throw

Fig. 11.6 Interfacing switches to a port line.

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 pullup 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 kΩ.

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

OPTION

File 81 h

7

6

5

4

3

2

1

0

RBPU INTEDG

T0CS

T0SE

PSA

PS2

PS1

PS0

(R/W 1) (R/W 1) (R/W 1) (R/W 1) (R/W 1) (R/W 1) (R/W 1) (R/W 1)

VDD

12 -- 100K

TRIS buffer

Data flip flop

TRIS flip flop

To transparent

Capture latch

To INT logic

RBn

RB0 only

Fig. 11.7 Port B’s weak pull-up option.


11. One Byte at a Time 281

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

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 e cient to connect these switches in the form of a 4×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 e ciency gain, with a 64-contact 8 × 8 keyboard needing only 16 I/O pins.

1

2

3

VDD

RB7

(1)

1

2

3

4

5

6

RB6

(0)

4

5

6

7

8

9

RB5

(1)

7

8

9

MEM

0

SET

RB4

(1)

MEM

0

SET

(a) A 4x3

keypad

RBPU = 0

(1)

RB3

330R

(0)

RB2

330R

(1)

RB1

330R

(b) Showing

key 5 being

accessed

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


282 The Quintessential PIC Microcontroller

once the closed key row has been detected the column:row intersection is known. The 330 Ω 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:

include "p16f84.inc"

MAIN bsf

STATUS,RP0

; Change to Bank1 where

movlw

b’11110000’

; TRISB & OPTION_REG lie

movwf

TRISB

; RB7:4 inputs, RB3:0 outputs

bcf

OPTION_REG,NOT_RBPU ; Activate internal pull-ups

bcf

STATUS,RP0

; Go back to Bank0

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

1.Set KEY_COUNT to one.

2.For i = 0 to 2.

Activate column i.

For j = 0 to 3.

Check row j.

IF zero THEN BREAK to step 4.

ELSE advance KEY_COUNT by 3.

Reset KEY_COUNT back to j+1.

3.Set KEY_COUNT to −1 if no key found.

4.Return KEY_COUNT.

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 bit 0 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


11. One Byte at a Time 283

Program 11.1 Scanning the keypad.

;*************************************************************

;* FUNCTION: Scans 4x3 keypad & returns with a key identifier*

; *

ENTRY

:

None

*

; *

EXIT

:

Key in W [MEM]=10, [0]=11, [SET]=12

*

;

*

EXIT

:

Return -1 (FFh) if no key detected

*

;

*

RESOURCE:

KEY, PATTERN byte vars

*

; *************************************************************

cblock

; Two global variables

KEY_COUNT:1, PATTERN:1

endc

SCAN_IT clrf

KEY_COUNT

; Key 1 is the first key

incf

KEY_COUNT,f

movlw

b’11110111’

; The initial scan pattern

movwf

PATTERN

SLOOP movf

PATTERN,w

; Get scan pattern from mem

movwf

PORTB

; Set column low

movf

KEY_COUNT,w

; Get Key count

; Now check each row for a zero

btfss

PORTB,7

; Check row 1

goto

GOT_IT

; IF zero THEN found the key!

addlw

3

; ELSE inc Key count by four

btfss

PORTB,6

; Check row 2

goto

GOT_IT

; IF zero THEN found the key!

addlw

3

; ELSE inc Key count by four

btfss

PORTB,5

; Check row 3

goto

GOT_IT

; IF zero THEN found the key!

addlw

3

; ELSE inc Key count by four

btfss

PORTB,4

; Check row 4

goto

GOT_IT

; IF zero THEN found the key!

;Reach here if no closed key movlw -1

incf KEY_COUNT,f rrf PATTERN,f btfsc PATTERM,0

goto SLOOP

;Scan is finished here

GOT_IT return

;Maybe no key? return -1

;Advance Key count one column

;Shift scan pattern once ->

;Check; has the 0 reached RB0?

;IF not DO another column

;Return with Key count in W

the SCAN_IT subroutine of Program 11.1. 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


284 The Quintessential PIC Microcontroller

Program 11.2 Noise filtered keypad scanning.

; *************************************************************

; * FUNCTION:

Scans 4x3 keypad and returns with a debounced

*

; * FUNCTION:

key identifier

*

; * ENTRY

:

None

*

; * EXIT

:

Key in W [MEM]=10,

[0]=11, [SET]=12

*

; * EXIT

:

Return -1 (FFh) if

no key detected

*

; * RESOURCE:

COUNT, NEW_KEY, OLD_KEY

*

; * RESOURCE:

Subroutine SCAN_IT

*

; *************************************************************

cblock

; Three global variables

COUNT:1, NEW_KEY:1, OLD_KEY:1

endc

GET_IT

clrf

COUNT

; The no-change count zeroed

GLOOP

call

SCAN_IT

; Raw value returned in W

movwf

NEW_KEY

; Is new value

subwf

OLD_KEY,w

; New and old the same?

btfsc

STATUS,Z

goto

EQUAL

; IF same go to EQUAL

; Otherwise the readings are different, so:

movf

NEW_KEY,w

; Make old key = new key

movwf

OLD_KEY

goto

GET_IT

; and start all over again

; IF readings

are the same THEN

EQUAL

incfsz

COUNT,f

; Increment count; IF not

goto

GLOOP

; rolled around to 00 repeat

movf

OLD_KEY,w

; ELSE thats it!

return

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.

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 bu er as opposed to the regular Port B TTL bu er.