Sofar,we’velookedatisolatedswitches,withonepinforeachswitch.We’lllookatonetypeofmultiple
switchassembly—calledarotaryencoder—inChapter7,andadifferenttype—thekeypad—inthischapter.
Keypads,suchasthosefoundontelephonesandcalculators,arealmostalwaysmatrixswitches,asillus-tratedinFigure4-20.Pressingabuttonestablishesaconnectionbetweenitscolumnandrowterminals.For
example,pressingthe“5”buttoninFigure4-20connectscolumn2withrow2.Manyinexpensivekeypads,
includingtheVelleman16KEYmodelwe’lluseinourexperiments,areconstructedwithaconductiveelas-tomerdesignratherthanphysicalmake/breakswitches.Theseswitchestypicallyhaveanonresistanceof
100–200ohms,comparedwiththemilliohmrangeresistancefoundinmechanicalswitches.
Let’sseehowwemightgoaboutreadingthekeyboard.SupposeweconnectitasshowninFigure4-21.
Then,wesequentiallymakepinsB4…B7outputahighandaftereachhigh,wereadpinsB0…B3toseeif
anyarehigh.Ifso,wecandeterminetherownumberandcolumnnumberandfromthatidentifywhichbut-tonhasbeenpressed.ThisprocessisillustratedinFigure4-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
Figure4-20:Typical16-positionkeypad
switch.
Figure4-21:KeyboardconnectiontoPIC.
R1…R4are“pull-down”resistorsandensurethatinputpinsRB0…RB3donotdriftupwardstowardsa
logicalhighfrominternalleakagecurrentsorpossibleleakageacrossthekeypad’sopencontacts.R5limits
thecurrentthroughLEDD1toapproximately10mAwhenRA0ishigh.
Inpseudo-code,wewould:
ScanKeyboard
ForRow=B4toB7
HighRow
Pause10
Column=PortB.Nib0
IfColumn<>0thenkeymusthavebeenpressed
Sogotoasubroutinetodealwiththepress
Ifnot,thenkeepscanningtherow NextRow
GoToScanKeyboard
WecandeterminetherownumberdirectlysinceRowNumber=Row-B4+1.Column,ontheotherhand,
isreadas1,2,4or8.WehaveseveralwaystocalculatetheColumnNumberfromColumn,butwe’lluse
asimpleonenow.Wedefineanauxiliaryarray,TempArrayandassignTempArray(1)=1, TempAr-ray(2)=2,TempArray(4)=3andTempArray(8)=4.Then,ColumnNumber=TempArray(Column). Program4-5readsthekeypadandthenflashesanLEDconnectedtoRA0inthesequence<flashrownum-ber>pause<flashcolumnnumber>.
Program4-5
;Programtotestkeypadreading
;
;thekeypadoutputpulsesaLEDwiththerow/columnvalue.LEDis
;poweredbytheportandgoestoground.Forexamplepressingthe;”8”keypulses
theLEDina3-pause-2pattern.
Column Var Byte ;CounterforFor/Nextloops Row Var Byte ;CounterforFor/Nextloops
Figure4-22:Readingthekeypad.
Temp Var Byte ;holdsthecolumnbinaryvalue LED Con A0 ;HaveanLEDhangingoffA0 RIndex Var Byte ;HoldstheRowValue1..4 CIndex Var Byte ;HoldstheColumnvalue1..4 i Var Byte ;CounterforvariousFor/Nextloops TempArray Var Nib(9) ;Useforconversion
;
;
;Initialize
;==========
Column=0 Row=0 Temp=0
OutputLED ;setuptheLEDpin
LowLED ;wewanttheLEDoff
ForColumn=B0toB3
InputColumn ;Settheseforinput Next;NextColumn
ForRow=B4toB7
OutputRow ;Settheseforoutput
LowRow ;wewillpulseahigh,startthemoutaslows Next;NextRow
;holdstheactualcolumnnumber.1,2,4&8areonlylegalvalues
;sootherelementsofthearraycanhaverandomvalues TempArray(1)=1
TempArray(2)=2
TempArray(4)=3 TempArray(8)=4
;
;
;MainHerewereadthekeypad.Puta1sequentiallyontherows
;==== andseewhichcolumnhasthehigh.
;Sincethecalledsubroutinetakesalongtimetorunandisonly
;triggeredonce,noadditionaldebounceisrequired.Thismaynot
;bethecaseforothercalledsubroutines.
Loop:
ForRow=B4toB7 ;Scantherows
HighRow ;pulsea1acrosseachrow
Pause10 ;waitabit
Temp=PortB.Nib0 ;readall4columnsatonce
LowRow ;restorethelow
IfTemp>0ThenGoSubLED_On ;buttonpushed
Next;Row
GoToLoop;checkformorekeypresses
;Executeuponkeypress--atthemomentitjustflashesanLED
;---LED_On:
;pulseLEDnumberofrowtimes
Rindex=Row-B4+1;therownumber,from1..4
Fori=1toRIndex;nowflashtheLED
HighLED
Pause150
LowLED
Pause150
Next ;Nexti
;nowweconvertcolumnvalue(heldinTemp)tocolumnnumber
;Columnvalueis1,2,4,8correspondingtoColumn1,2,3or4.
CIndex=TempArray(Temp);conversionviaarrayindexing
Pause500 ;pausetopermittheusertodistinguishrows
;fromcolumnswhenwatchingtheLED
;sameapproachtoflashthecolumnnumberusingtheLED
Fori=1toCIndex
HighLED
Pause150
LowLED
Pause150
Next;Nexti
Return;LED_On
End
Thecentralportionoftheprogramisthekeyscanloop,whichimplementsthepseudo-codealmostdirectly:
Loop:
ForRow=B4toB7 ;Scantherows
HighRow ;pulsea1acrosseachrow
Pause10 ;waitabit
Temp=PortB.Nib0 ;readall4columnsatonce
LowRow ;restorethelow
IfTemp>0ThenGoSubLED_On;buttonpushed
Next;Row
GoToLoop;checkformorekeypresses
ThesubroutineLED_On isadummyroutinethatsimplyflashesanLEDtoshowtherowandcolumnnum-bersofthebuttonbeingpressed.Youmaywishtousethiskeypadroutineasonebuildingblockinamore
complexandusefulprogram.
References
[4-1] Mancini,Ron,“ExaminingSwitch-DebounceCircuits,”EDN,p.22,Feb.21,2002.