• No results found

Reading฀a฀Keypad

So฀far,฀we’ve฀looked฀at฀isolated฀switches,฀with฀one฀pin฀for฀each฀switch.฀We’ll฀look฀at฀one฀type฀of฀multiple฀

switch฀assembly—called฀a฀rotary฀encoder—in฀Chapter฀7,฀and฀a฀different฀type—the฀keypad—in฀this฀chapter.

Keypads,฀such฀as฀those฀found฀on฀telephones฀and฀calculators,฀are฀almost฀always฀matrix฀switches,฀as฀illus-trated฀in฀Figure฀4-20.฀Pressing฀a฀button฀establishes฀a฀connection฀between฀its฀column฀and฀row฀terminals.฀For฀

example,฀pressing฀the฀“5”฀button฀in฀Figure฀4-20฀connects฀column฀2฀with฀row฀2.฀Many฀inexpensive฀keypads,฀

including฀the฀Velleman฀16KEY฀model฀we’ll฀use฀in฀our฀experiments,฀are฀constructed฀with฀a฀conductive฀elas-tomer฀design฀rather฀than฀physical฀make/break฀switches.฀These฀switches฀typically฀have฀an฀on฀resistance฀of฀

100–200฀ohms,฀compared฀with฀the฀milliohm฀range฀resistance฀found฀in฀mechanical฀switches.

Let’s฀see฀how฀we฀might฀go฀about฀reading฀the฀keyboard.฀Suppose฀we฀connect฀it฀as฀shown฀in฀Figure฀4-21.฀

Then,฀we฀sequentially฀make฀pins฀B4…B7฀output฀a฀high฀and฀after฀each฀high,฀we฀read฀pins฀B0…B3฀to฀see฀if฀

any฀are฀high.฀If฀so,฀we฀can฀determine฀the฀row฀number฀and฀column฀number฀and฀from฀that฀identify฀which฀but-ton฀has฀been฀pressed.฀This฀process฀is฀illustrated฀in฀Figure฀4-22.฀

Col_1 Col_2 Col_3 Col_4

Row_1

Row_2

Row_3

Row_4

1 2 3 A

4 5 6 B

7 8 9 C

* 0 # D

Figure฀4-20:฀Typical฀16-position฀keypad฀

switch.

Figure฀4-21:฀Keyboard฀connection฀to฀PIC.

R1…R4฀are฀“pull-down”฀resistors฀and฀ensure฀that฀input฀pins฀RB0…RB3฀do฀not฀drift฀upwards฀towards฀a฀

logical฀high฀from฀internal฀leakage฀currents฀or฀possible฀leakage฀across฀the฀keypad’s฀open฀contacts.฀R5฀limits฀

the฀current฀through฀LED฀D1฀to฀approximately฀10฀mA฀when฀RA0฀is฀high.

In฀pseudo-code,฀we฀would:

ScanKeyboard

For฀Row฀=฀B4฀to฀B7

High฀Row

Pause฀10

Column฀=฀PortB.Nib0

If฀Column฀<>฀0฀then฀key฀must฀have฀been฀pressed

So฀go฀to฀a฀subroutine฀to฀deal฀with฀the฀press

If฀not,฀then฀keep฀scanning฀the฀row Next฀Row

GoTo฀ScanKeyboard

We฀can฀determine฀the฀row฀number฀directly฀since฀RowNumber฀=฀Row-B4+1.฀Column,฀on฀the฀other฀hand,฀

is฀read฀as฀1,2,4฀or฀8.฀We฀have฀several฀ways฀to฀calculate฀the฀ColumnNumber฀from฀Column,฀but฀we’ll฀use฀

a฀simple฀one฀now.฀We฀define฀an฀auxiliary฀array,฀TempArray฀and฀assign฀TempArray(1)=1, TempAr-ray(2)=2,฀TempArray(4)=3฀and฀TempArray(8)=4.฀Then,฀ColumnNumber฀=฀TempArray(Column). Program฀4-5฀reads฀the฀keypad฀and฀then฀flashes฀an฀LED฀connected฀to฀RA0฀in฀the฀sequence฀<flash฀row฀num-ber>฀pause฀<flash฀column฀number>.

Program฀4-5

;Program฀to฀test฀keypad฀reading

;

;the฀keypad฀output฀pulses฀a฀LED฀with฀the฀row/column฀value.฀LED฀is

;powered฀by฀the฀port฀and฀goes฀to฀ground.฀For฀example฀pressing฀the฀;”8”฀key฀pulses฀

the฀LED฀in฀a฀3฀-฀pause฀-฀2฀pattern.

Column฀ ฀ Var฀ Byte฀ ;Counter฀for฀For/Next฀loops Row฀ Var฀ Byte฀ ;Counter฀for฀For/Next฀loops

Figure฀4-22:฀Reading฀the฀keypad.

Temp฀ Var฀ Byte฀ ;holds฀the฀column฀binary฀value LED฀ Con฀ A0฀ ;Have฀an฀LED฀hanging฀off฀A0 RIndex฀ ฀ Var฀ Byte฀ ;Holds฀the฀Row฀Value฀1..4 CIndex฀ ฀ Var฀ Byte฀ ;Holds฀the฀Column฀value฀1..4 i฀ Var฀ Byte฀ ;Counter฀for฀various฀For/Next฀loops TempArray฀ Var฀ Nib(9)฀ ;Use฀for฀conversion

;

;

;Initialize

;==========

Column฀=฀0 Row฀=฀0 Temp฀=฀0

Output฀LED฀ ;set฀up฀the฀LED฀pin฀

Low฀LED฀฀ ;we฀want฀the฀LED฀off

For฀Column฀=฀B0฀to฀B3฀฀

฀฀฀฀Input฀Column฀ ;Set฀these฀for฀input Next฀;Next฀Column

For฀Row฀=฀B4฀to฀B7฀

฀฀฀Output฀Row฀ ฀ ;Set฀these฀for฀output

฀฀฀Low฀Row฀ ;we฀will฀pulse฀a฀high,฀start฀them฀out฀as฀lows Next฀;Next฀Row

;holds฀the฀actual฀column฀number.฀1,2,4฀&฀8฀are฀only฀legal฀values

;so฀other฀elements฀of฀the฀array฀can฀have฀random฀values TempArray(1)฀=฀1฀

TempArray(2)฀=฀2฀

TempArray(4)฀=฀3฀ TempArray(8)฀=฀4

;

;

;Main฀Here฀we฀read฀the฀keypad.฀Put฀a฀1฀sequentially฀on฀the฀rows

;====฀ and฀see฀which฀column฀has฀the฀high.

;Since฀the฀called฀subroutine฀takes฀a฀long฀time฀to฀run฀and฀is฀only฀

;triggered฀once,฀no฀additional฀debounce฀is฀required.฀This฀may฀not฀

;be฀the฀case฀for฀other฀called฀subroutines.

Loop:

฀฀฀For฀Row฀=฀B4฀to฀B7฀ ฀ ;Scan฀the฀rows

฀฀฀฀฀฀฀High฀Row฀ ;pulse฀a฀1฀across฀each฀row

฀฀฀฀฀฀฀Pause฀10฀ ;wait฀a฀bit

฀฀฀฀฀฀฀Temp฀=฀PortB.Nib0฀ ;read฀all฀4฀columns฀at฀once

฀฀฀฀฀฀฀Low฀Row฀฀ ;restore฀the฀low

฀฀฀฀฀฀฀If฀Temp฀>฀0฀฀Then฀GoSub฀LED_On฀฀ ;button฀pushed

฀฀฀Next฀;Row฀฀฀฀

GoTo฀Loop฀;check฀for฀more฀keypresses

;Execute฀upon฀keypress฀--at฀the฀moment฀it฀just฀flashes฀an฀LED

;---LED_On:

฀฀;pulse฀LED฀number฀of฀row฀times

฀฀฀Rindex฀=฀Row฀-฀B4฀+฀1฀;the฀row฀number,฀from฀1..4

฀฀฀For฀i฀=฀1฀to฀RIndex฀;now฀flash฀the฀LED

฀฀฀฀฀฀฀High฀LED

฀฀฀฀฀฀฀Pause฀150

฀฀฀฀฀฀฀Low฀LED

฀฀฀฀฀฀฀Pause฀150

฀฀฀Next฀฀ ;Next฀i฀฀฀฀

฀฀฀

฀฀฀;now฀we฀convert฀column฀value฀(held฀in฀Temp)฀to฀column฀number฀

฀฀฀;Column฀value฀is฀1,2,4,8฀corresponding฀to฀Column฀1,2,3฀or฀4.

฀฀฀

฀฀฀CIndex฀=฀TempArray(Temp)฀;conversion฀via฀array฀indexing

฀฀฀฀฀

฀฀฀Pause฀500฀ ;pause฀to฀permit฀the฀user฀to฀distinguish฀rows฀

;from฀columns฀when฀watching฀the฀LED

฀฀฀

฀฀;same฀approach฀to฀flash฀the฀column฀number฀using฀the฀LED

฀฀฀For฀i฀=฀1฀to฀CIndex฀

฀฀฀฀฀฀฀High฀LED

฀฀฀฀฀฀฀Pause฀150

฀฀฀฀฀฀฀Low฀LED

฀฀฀฀฀฀฀Pause฀150

฀฀฀Next฀;Next฀i฀฀฀฀

Return฀฀;LED_On

End

The฀central฀portion฀of฀the฀program฀is฀the฀key฀scan฀loop,฀which฀implements฀the฀pseudo-code฀almost฀directly:

Loop:

฀฀฀For฀Row฀=฀B4฀to฀B7฀ ฀ ;Scan฀the฀rows

฀฀฀฀฀฀฀High฀Row฀ ;pulse฀a฀1฀across฀each฀row

฀฀฀฀฀฀฀Pause฀10฀ ;wait฀a฀bit

฀฀฀฀฀฀฀Temp฀=฀PortB.Nib0฀ ;read฀all฀4฀columns฀at฀once

฀฀฀฀฀฀฀Low฀Row฀฀ ;restore฀the฀low

฀฀฀฀฀฀฀If฀Temp฀>฀0฀฀Then฀GoSub฀LED_On฀;button฀pushed

฀฀฀Next฀;Row฀฀฀฀

GoTo฀Loop฀;check฀for฀more฀keypresses

The฀subroutine฀LED_On ฀is฀a฀dummy฀routine฀that฀simply฀flashes฀an฀LED฀to฀show฀the฀row฀and฀column฀num-bers฀of฀the฀button฀being฀pressed.฀You฀may฀wish฀to฀use฀this฀keypad฀routine฀as฀one฀building฀block฀in฀a฀more฀

complex฀and฀useful฀program.

References

[4-1]฀ Mancini,฀Ron,฀“Examining฀Switch-Debounce฀Circuits,”฀EDN,฀p.฀22,฀Feb.฀21,฀2002.

C H A P T E R ฀ 5