The standard way of using a 3 x 4 keypad is to use 7 pic pins. This method uses 3 pic pins, saving 4 pic pins. This enables one to use smaller pics while still have enough pins left for other I/O's. The trade-off in this case is the pic must have 3 A/D inputs.

How it works is really simple. The 5 x 1k resistors between 5V and GND forms a volatge devider that gives about 1V, 2V, 3V and 4V voltage drop over the resistors measured from ground. If a 10-bit A/D is used, you have a count of 1024 for the full 5V.
This means that about 205 counts per devider resistor is going to be counted. I say about, because it is easy to compensate for variations of counts and component tolerances in the software as you will see.
Looking at the circuit you can see that if no key is pressed, 0V will go to the A/D input.
Row 1, 2 and 3 gets pulled to GND by the 100k resistors.
If the * key is pressed, row 1 will output about 1V (or about 205 counts in AN1)
The 7 key will give about 2V (or about 410 counts in AN1)
The4 key will give about 3V (or about 615 counts in AN1)
The1 key will give about 4V (or about 820 counts in AN1)
The same will values will be read by AN2 if you press keys 0, 8, 5 and 2
and again the same values will be read by AN0 if you press keys #, 9, 6 and 3
So by reading the values with the different A/D's, you know which key is pressed.
Here's a neat trick. The three A/D inputs can be used as 5V logic inputs as well, but you will have to compensate in the software for that. The code below only provides for reading the keys voltages, you will have to add -
If Vin > 950 Then Disp1 = 12 ' Logic Input on this pin
If Vin > 950 Then Disp1 = 13 ' Logic Input on this pin
If Vin > 950 Then Disp1 = 14 ' Logic Input on this pin
If Vin > 950 Then Disp1 = 13 ' Logic Input on this pin
If Vin > 950 Then Disp1 = 14 ' Logic Input on this pin
Dim Disp1 As Byte ' The key pressed is returned in this variable
Dim Vin As Dword ' The A/D Value of the key pressed
'************************************************* *****************
' Read keypad input call routine
'************************************************* **************
KeyIn:
DelayMS 10 'Debounce
Disp1 = 15 'dummy value in case no key pressed
KeyIn1:
Vin = ADIn 1 'Read A/D Input cha 1
'Compare lowest value first, if a higher value is compared,
'that key will be the key that was pressed.
If Vin < 50 Then GoTo KeyIn2 ' No key pressed, do next column
If Vin > 150 Then Disp1 = 10 ' Key * pressed
If Vin > 350 Then Disp1 = 7 ' Key 7 pressed instead
If Vin > 550 Then Disp1 = 4 ' Key 4 pressed instead
If Vin > 750 Then Disp1 = 1 ' Key 1 pressed instead
GoTo KeyIn4 ' Do key release Routine
KeyIn2:'
Vin = ADIn 2 'Read A/D Input cha 2
If Vin < 50 Then GoTo KeyIn3 ' No key pressed, do next column
If Vin > 150 Then Disp1 = 0 ' Key 0 pressed
If Vin > 350 Then Disp1 = 8 ' Key 8 pressed instead
If Vin > 550 Then Disp1 = 5 ' Key 5 pressed instead
If Vin > 750 Then Disp1 = 2 ' Key 2 pressed instead
GoTo KeyIn4 ' Do key release Routine
KeyIn3:
Vin = ADIn 0''' 'Read A/D Input cha 0
If Vin < 50 Then Return ' No key pressed, return to the main loop
If Vin > 150 Then Disp1 = 11 ' Key # pressed
If Vin > 350 Then Disp1 = 9 ' Key 9 pressed instead
If Vin > 550 Then Disp1 = 6 ' Key 6 pressed instead
If Vin > 750 Then Disp1 = 3 ' Key 3 pressed instead
'************************************************* ********************
KeyIn4: 'Key release Routine if required – keeps from reading the same key over and
'over by mistake if you have fingers slower than the code ;-)
Vin = ADIn 1
If Vin > 50 Then GoTo KeyIn4
Vin = ADIn 2
If Vin > 50 Then GoTo KeyIn4
Vin = ADIn 0
If Vin > 50 Then GoTo KeyIn4
Return
End
Dim Vin As Dword ' The A/D Value of the key pressed
'************************************************* *****************
' Read keypad input call routine
'************************************************* **************
KeyIn:
DelayMS 10 'Debounce
Disp1 = 15 'dummy value in case no key pressed
KeyIn1:
Vin = ADIn 1 'Read A/D Input cha 1
'Compare lowest value first, if a higher value is compared,
'that key will be the key that was pressed.
If Vin < 50 Then GoTo KeyIn2 ' No key pressed, do next column
If Vin > 150 Then Disp1 = 10 ' Key * pressed
If Vin > 350 Then Disp1 = 7 ' Key 7 pressed instead
If Vin > 550 Then Disp1 = 4 ' Key 4 pressed instead
If Vin > 750 Then Disp1 = 1 ' Key 1 pressed instead
GoTo KeyIn4 ' Do key release Routine
KeyIn2:'
Vin = ADIn 2 'Read A/D Input cha 2
If Vin < 50 Then GoTo KeyIn3 ' No key pressed, do next column
If Vin > 150 Then Disp1 = 0 ' Key 0 pressed
If Vin > 350 Then Disp1 = 8 ' Key 8 pressed instead
If Vin > 550 Then Disp1 = 5 ' Key 5 pressed instead
If Vin > 750 Then Disp1 = 2 ' Key 2 pressed instead
GoTo KeyIn4 ' Do key release Routine
KeyIn3:
Vin = ADIn 0''' 'Read A/D Input cha 0
If Vin < 50 Then Return ' No key pressed, return to the main loop
If Vin > 150 Then Disp1 = 11 ' Key # pressed
If Vin > 350 Then Disp1 = 9 ' Key 9 pressed instead
If Vin > 550 Then Disp1 = 6 ' Key 6 pressed instead
If Vin > 750 Then Disp1 = 3 ' Key 3 pressed instead
'************************************************* ********************
KeyIn4: 'Key release Routine if required – keeps from reading the same key over and
'over by mistake if you have fingers slower than the code ;-)
Vin = ADIn 1
If Vin > 50 Then GoTo KeyIn4
Vin = ADIn 2
If Vin > 50 Then GoTo KeyIn4
Vin = ADIn 0
If Vin > 50 Then GoTo KeyIn4
Return
End
Key 1 Returns a 1
Key 2 Returns a 2
Key 3 Returns a 3
Key 4 Returns a 4
Key 5 Returns a 5
Key 6 Returns a 6
Key 7 Returns a 7
Key 8 Returns a 8
Key 9 Returns a 9
Key 0 Returns a 0
Key * Returns a 10
Key # Returns a 11
Logic on ADIn1 (if implemented) Returns a 12
Logic on ADIn2 (if implemented) Returns a 13
Logic on ADIn0 (if implemented) Returns a 14
No key pressed Returns a 15
All you need to do when the code returns with a value in Disp1 is decide what to do with it.
If Disp1 = 5 then goto.... ' Keypad key 5 pressed or -
If Disp1 = # then Relay1 = 1 ' Key # pressed, switch lights relay on
If Disp1 = # then Relay1 = 1 ' Key # pressed, switch lights relay on
In low power apps the 5V supply for the keypad resistors can be supplied by a pic pin. The keypad will consume no power when that pin is made low or 0
Should work as well with 3V3 pics, keypad also gets supplied with 3v3 then.
contributed by Fanie.


Menu
Recent Articles


Using PDS with SPI GLCD based on ST7565R Controller
Graphic LCDs based on the ST7565 are cheaper then GLCDs with other controllers. SPI requires only four pins. If the circuit