16F Keypad Example
This code was
improved with the help of Mike K8LH so that external
resistors are not required!
Most
keypads have some sort of matrix, and you need to be able to
decode them to know what button the user is pressing. This can be
achieved by making one row inputs and the other outputs. Now we can
'scan' the
keypad, waiting for that key press. If the user presses a
key, the PIC will detect it as one of the inputs will now be high.
But which one? That's where a little programming comes into play
I have broken up the Keypad_Decode and Keypad_Debounce routines as
in all of my projects I found it much better to grab the key as soon
as the user had pressed it, then update the screen/do whatever I had
to with it, then call the Debounce routine separately. If you don't
do it this way, the program will do nothing until you depress the
switch, making the program 'feel' slow.
It makes things run a lot more to that as they would in real life
applications, and doesn't give that laggy impression that happens if
you wait for the button depression before doing something with it.
Circuit
Diagram:

Click
here to see this circuit in action!
Note the PIC's power supply/oscillator are not shown
Note that it
doesn't matter what port the
keypad is wired to, the associated
pins are connected the same. The program has been modified
for easy integration onto different ports on the PIC. The following
variables and symbols must be defined in the program,
Symbol KeypadTris = TRISC ' What ever the TRIS statement is for the desired port
Symbol KeypadPort = PORTC ' The port name with the keypad attached
Dim Key as Byte ' Variables used within the keypad routine
Dim Col as Byte
Dim Row as Byte
The
keypad routine has 3 routines,
they are,
Keypad_Decode:
Performs a sweep of the
keypad to check if any key is down, if there
was no key
presssed, the value returned is 0
Wait_For_Key: A
routine that will loop until a key has been pressed, and return when
one has been
captured. This is handy as this function maybe used in many places
throughout the whole program.
Keypad_Debounce: After
the program has grab the key press, this routine should be called
before
requesting another input. It will only exit when all keys are
depressed.
With the
modifications that have been made to this routine, it can be used on
any PIC, on any port, so long as the correct symbols are defined.
Device 16F877 ' Define what device your using
XTAL = 4 ' Set the Osc speed
Symbol KeypadTris = TRISC
Symbol KeypadPort = PORTC
Dim Key as Byte
Dim Col as Byte
Dim Row as Byte
ALL_DIGITAL = True
LCD_DTPIN = PORTB.4
LCD_RSPIN = PORTB.2
LCD_ENPIN = PORTB.3
LCD_INTERFACE = 4 ' Setup the LCD
LCD_LINES = 2
LCD_TYPE = 0
Delayms 150 ' Allow LCD to warmup,
Cls
Delayms 10
Print At 1, 1, "Press any key..."
Main:
Gosub Wait_For_Key ' Loop until a key is pressed
If Key = 11 Then ' If 0 was pressed, change the value of key
Key = 0 '
EndIf '
If Key = 10 Then ' Display the data on the LCD, note:
Print At 2, 1, "*" ' 10 = "*" and 12 = "#"
ElseIf Key = 12 Then
Print At 2, 1, "#" '
Else '
Print At 2, 1, Dec Key '
EndIf '
Gosub Keypad_Debounce ' Wait for the user to depress the key
Goto Main ' Loop forever
Wait_For_Key: ' Loop until any key is pressed
Gosub Keypad_Decode
If Key = 0 Then Goto Wait_For_Key ' If 0 was returned, then loop
Return ' Input has been captured, return
Keypad_Decode:
Key = 0 ' Reset the key value
KeypadTris = %11111111 ' Make 7-4 outputs and 3-0 inputs
For Col = 4 to 6 ' 3 columns in keypad
ClearBit KeypadTris, Col ' Make one Column an output
SetBit KeypadPort, Col ' Set the Column high,
Row = KeypadPort << 4 >> 4 ' and check if a row is high by dumping Column data
ClearBit KeypadPort, Col ' Set the Col low
SetBit KeypadTris, Col ' Make the output an input (so that it has high impedance)
If Row <> 0 Then Goto Gotkey ' If a Row was high, then grab the key
Next
Return ' No keys down, then return
Gotkey:
Key = ((NCD Row - 1) * 3) + (Col - 3) 'Calculate what button was pressed
' Row = 1 to 4 and Col = 1 to 3
' So to calculate the key, determine what row equals
' by using NCD (Returns a decimal value of the MSB in
' the variable, eg, %00001000 would return the value 4
' and 00000010 would return 2. Then minus 1 from Row,
' so that it is a value between 0 and 3, and as Col
' is assigned to the upper part of the port, minus 3
' from it so it equals 1 to 3.
' Now if Row = 0 and Col = 1 then key pressed = 1 (Row + Col)
Return 'Subroutine over
Keypad_Debounce: ' This routine will only exit if
' all keys are depressed
Delayms 10 ' Debounce time
' Wait for all keys up
KeypadTris = %00001111
KeypadPort = %11110000
If (KeypadPort << 4) <> $00 Then Goto Keypad_Debounce
Return

Where you can get the components;

 | Site Tutorial Index |
|  | 16F PIC Examples |
| |  | Motors |
| |  | Thermometers |
| |  | Code Snippets |
|  | 18F PIC Examples |
|  | Handy Tips |