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;

 Skip Navigation Links.

Collapse Site Tutorial IndexSite Tutorial Index
Collapse 16F PIC Examples16F PIC Examples
LED's
Switches
Keypads
LCD's
7 Seg Displays
ADC
DAC
Expand MotorsMotors
Expand ThermometersThermometers
DS1307 RTC Chip
DS275
EEPROM's
RF Modules
RGB LED's
Code Snippets
Expand Code SnippetsCode Snippets
Expand 18F PIC Examples18F PIC Examples
Expand Handy TipsHandy Tips