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

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

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

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

Добавлен: 15.06.2025

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

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

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

11. One Byte at a Time 297

#include

<16f84.h>

#use

fast_io(b)

#define PORT_B *(unsigned int *)0x06

unsigned int scan_it(void);

unsigned int get_it(void);

int main()

{

int ....;

/* Main’s variable declarations

*/

set_tris_b(0xF0);

/* RB7:4 outputs, RB3:0 inputs

*/

port_b_pullups(TRUE); /* PortB pullups active

*/

......

......

}

Program 11.6 Coding the keypad device driver in C.

unsigned int get_it(void)

{

unsigned int count, old_key, new_key; count = 0;

while(count<255)

{

new_key = scan_it(); if(new_key == old_key)

{ count++;}

else

{

old_key = new_key; count = 0;

}

}

return (old_key);

}

/**************************************************************/

unsigned int scan_it(void)

{

unsigned int key, pattern;

key=1; pattern = 0xF7;

/* Initial pattern 11110111b */

while(key<13)

{

PORT_B = pattern; if(!input(PIN_B7)) {break;} if(!input(PIN_B6)) {key+=3; break;} if(!input(PIN_B5)) {key+=6; break;} if(!input(PIN_B4)) {key+=9; break;} pattern = pattern >>1;

key++;

}

if(key==13) {key = 0xff;} return key;

}


298 The Quintessential PIC Microcontroller

The code in Program 11.6 shadows that of Program 11.1 in that two functions are used; scan_it() scans the keypad once and returns with a value 1 – 12 or FFh if no key is pressed. Function get_it() repetitively calls scan_it() until 255 identical values are returned, and this value is the final outcome.

scan_it() initializes the column count key to 1 and the column scan pattern to 11110111b. This test vector is sent to Port B and each row is tested in turn adding 3, 6 or 9 to the value of key if a zero is found and the while loop is exited (break). If after the four rows have been tested no outcome has been detected, the column scan pattern is shifted right and key is incremented. The process is continued until either a 0 is found or count reaches 13. In the latter case a key value of FFh (−1) is returned.

get_it() keeps a number of tries count tally, last reading old_key and current reading new_key variables. count is incremented after calling scan_it() if the current reading is the same as the last reading. If not, count is reset and old_key is updated. The while loop exits if count reaches 255 (the maximum value of an int variable), indicating that the last 255 readings are the same.

Example 11.5

Despite the increasing use of liquid-crystal alphanumeric readouts, discrete 7-segment LED displays are commonly used to show up to six numerical digits. Such readouts are particularly e ective in low ambient light situations and where large displays are needed.

RA2

RA1

RA0

RB7

RB6

RB5

RB4

RB3

RB2

RB1

RB0

VDD

VDD

VDD

Common anode

Common anode

Common anode

f

a

f

a

f

a

b

b

b

g

g

g

e

c

e

c

e

c

dp

d

dp

d

dp

d

330R

330R

330R

C1

1D

C1

1D

C1

1D

Common anode package

Common

a b c d e f g dp

Fig. 11.13 Using port expansion to drive three 7-segment displays.


11. One Byte at a Time 299

Assuming each display requires eight lines (seven segments plus decimal point) then a budget of 8 × n parallel lines are required for an n- digit display. The straightforward solution to this problem is shown in Fig. 11.13, where a 3-digit display is driven from three parallel registers on a local bus, in the manner of Fig. 11.10. The principle can be extended to six or more digits using the appropriate number of registers.

VDD

VDD

VDD

4K7

4K7

4K7

Common anode

Common anode

Common anode

f

a

f

a

f

a

b

b

b

g

g

g

e

c

e

c

e

c

dp

d

dp

d

dp

d

180R

180R

180R

RA2

RA1

RA0

RB0

RB1

RB2

RB3

RB4

RB5

RB6

RB7

Fig. 11.14 Scanning a 3-digit 7-segment array.

The displays shown in the diagram are common anode and the appropriate LED is illuminated when the register output is low, with the sink current limited by the series resistance. In practice most logic circuitry can sink more current into a low output as compared to sourcing current from high and because of this common cathode displays are less common. In some larger displays , eg. 5 cm (2"), several LEDs may be paralleled or in series in each segment. In this situation larger anode voltages and/or currents may be needed and suitable drivers required to bu er the register outputs.

An alternative approach, shown in Fig. 11.14, is frequently used with LED-based displays. Instead of using a register for each digit, all readouts are connected in parallel to the one PIC port. Each readout is en-


300 The Quintessential PIC Microcontroller

abled in turn for a short time with the appropriate data from the output port. Provided that the scan rate is greater than 50 per second (preferably greater than 100) the brain’s persistence of vision will trick the onlooker into visualizing the display as flicker free.9 Of course the current flowing through the segment must be increased to compensate for the mark:space ratio but LEDs are more e cient at larger current pulses and the reduction of series resistance need not be pro-rata.

Discuss the pros and cons of these two arrangements with particular reference to the tradeo of software and hardware. Illustrate your answer by displaying the decimal equivalent of the binary byte in File 20h. For example if the contents of BINARY were FFh then the display should be

.

Solution

From the software perspective two main functions can be identified. Firstly the binary code in File 20h has to be decomposed into three BCD digits; HUNDREDS, TENS and UNITS. Once this is done then each BCD digit ranging from 0–9 must be converted to 7-segment code to illuminate the relevant segments to form the appropriate characters. We already have a subroutine to implement the former in Program 6.10 on page 161 and the latter in Program 6.4 on page 149. Based on this code in situ, we have as a task list for software to interact with the hardware of Fig. 11.13:

1.Convert the binary byte into BCD.

2.DO

(a)Copy contents of HUNDREDS into W and convert to 7-seg.

(b)Copy 7-segment code to Port B.

(c) Pulse / \ RA2.

3.DO

(a)Copy contents of TENS into W and convert to 7-seg.

(b)Copy 7-segment code to Port B.

(c)Pulse / \ RA1.

4.DO

(a)Copy contents of UNITS into W and convert to 7-seg.

(b)Copy 7-segment code to Port B.

(c)Pulse / \ RA0.

The coding implementing this task list is shown in Program 11.7.

The interaction of the software to the hardware of Fig. 11.14 is not so straightforward as there are no registers to dump the data and run! Instead, data has to be continuously sent out in sequence with the appropriate display being enabled. If we use a scan rate of 100 updates each second then this data should be held for 10 ms before moving on. Thus we have as our new task list:

1.Convert the binary byte into BCD.

2.DO forever:

9Of course this is how the brain interprets a series of 24 still frames per minute in a movie, each shown twice, as a moving image.


11. One Byte at a Time 301

Program 11.7 Displaying the decimal equivalent of a binary byte.

; Task 1

DISPLAY movf

BINARY,w

; Get binary byte

call

BIN_2_BCD

; Convert to 3-digit BCD

; Task 2

movf

HUNDREDS,w

; Get Hundreds nybble

call

SVN_SEG

; Convert to 7-segment code

movwf

PORTB

; Send out to PortB

bsf

PORTA,2

; Clock into register

bcf

PORTA,2

; Task 3

movf

TENS,w

; Get Tens nybble

call

SVN_SEG

; Convert to 7-segment code

movwf

PORTB

; Send out to PortB

bsf

PORTA,1

; Clock into register

bcf

PORTA,1

; Task 4

movf

UNITS,w

; Get Units nybble

call

SVN_SEG

; Convert to 7-segment code

movwf

PORTB

; Send out to PortB

bsf

PORTA,0

; Clock into register

bcf

PORTA,0

(a)

Copy contents of HUNDREDS into W and convert to 7-segment code.

Copy 7-segment code to Port B.

• Bring RA2 low \ .

Delay 10ms.

• Bring RA2 high / .

(b)

Copy contents of TENS into W and convert to 7-segment code.

Copy 7-segment code to Port B.

• Bring RA1 low \ .

Delay 10ms.

• Bring RA1 high / .

(c)

Copy contents of UNITS into W and convert to 7-segment code.

Copy 7-segment code to Port B.

• Bring RA0 low \ .

Delay 10ms.

• Bring RA0 high / .

The coding in Program 11.8 makes use of the 10 ms delay subroutine illustrated in Program 11.5 to regulate the scanning rate. Apart from the length of the enabling pulse the core of the program is identical to our previous situation. However, the code must run continually to give the impression of a constant display. This illustrates the trade o between hardware and software. Reducing the hardware has lead to greater load-