[Back to Home Page]


Keypad to a PIC with only 3 pins!
A circuit and code procedure for interfacing a 12-key Keypad to a PIC
Roman Black - April 2004 - web Aug 2006

What is it?

A 12-key telephone style keypad can be interfaced to a PIC micro using only 3 digital input pins and a few cheap resistors and capacitors.

This is useful when you need to use a small (cheap!) PIC chip or other micro that does not have a lot of pins. 12-key keypads are cheaply avaliable from the hobby electronics stores and are already connected in a 3x4 matrix. With even the smallest of PICs (like a 12c508) this setup can make a 12-key remote control or DTMF sound generator. These 8-pin PIC micros have 6 digital I/O pins and with only 3 pins needed for the keypad there are 3 PIC pins still available!


The information provided here is not a complete application. It is however tested and works, provided you have the PIC programming skills and electronic hardware skills to put it together. It is very suitable for use by a professional product developer or high-level PIC hobbyist. Beginner PIC hobbyists may struggle with this design - please don't email me for help! All the help is already provided here on this page.

How it works

The circuit operates by discharging the 3 caps, and then measuring the time taken for a cap to charge up. A cap will only charge up if a key is pressed. My code procedure allows for efficient battery use and no current is required (apart from the PIC itself) unless a key is pressed.

                                 |      |      |      |
                                 R      R      R      R
   ,------,                      |10k   |27k   |47k   |68k
   | PIC  |                      |      |      |      |
   |12c508|  270 ohm             |      |      |      |
   |      |----R---------*-------S------S------S------S-------
   |      |              |       |      |      |      |
   |      |              |       |      |      |      |
   |      |              |       |      |      |      |
   |      |----R-----*---|-------S------S------S------S-------
   |      |          |   |       |      |      |      |
   |      |          |   |       |      |      |      |
   |      |          |   |       |      |      |      |
   |      |----R-*---|---|-------S------S------S------S-------
   |      |      |   |   |
   '------'      C   C   C           12-key keypad matrix:
                 |   |   | 3.3nF
                 |   |   |                    |
                -*---*---*-              ,-S--*
                   GND                   |    |

In the circuit diagram you can see that the 3 PIC pins are connected by 270 ohm resistors to the 3 caps. The 12-key keypad is connected in the standard 3x4 matrix, most of them are supplied like this anyway. There are also 4 resistors at the top that give different capacitor charge times depending on which key is pressed.

The system is only suitable for a single keypress at a time which is also a standard for remote controls etc.

In sleep mode the PIC is configured for wake up on pin change so it stays in the low-current sleep mode and will automatically wake up when any of the 3 input pins goes hi, which happens on any keypress.

The procedure

The benefit of this procedure is that the timing process is very simple, using very little code space, and it is reliable and fast.

  • PIC wakes up on keypress, reads the 3 pins and knows the ROW
  • PIC grounds the 3 pins, waits a short time
  • PIC resets its internal timer, and releases the 3 pins
  • When the pin goes HIGH (again) the timer is grabbed
  • The COLUMN is known based on the timer value

    The code goes something like this;
    (PIC has just woken up on keypress)
    	movf GPIO,w		; read the pins
    	andlw b'00001011'	; only keep GP3,GP1,GP0
    	movwf row		; save as ROW data
    	(your code goes here to set pins as LOW outputs)
    	clrf TMR0		; reset timer0
    	btfss TMR0,4		; and wait 16 timer counts
    	goto $-1		;
    				; ready to start the time test now
    	(your code goes here to set pins as inputs again)
    	clrf TMR0		; reset timer0 again
    	movf GPIO,w		; read the pins
    	skpnz			; nz means a pin is now HIGH
    	goto charging		; z, pin not HIGH yet 
    	movf TMR0,w		; grab timer0 value
    	movwf timer		; save timer value

    After this point the PIC knows the row from the bit set in the ROW variable, and can compare the value it grabbed from the timer against 3 setpoints to determine the column using this method;

    column = 1, if timer < sp1 then goto done
    column = 2, if timer < sp2 then goto done
    column = 3, if timer < sp3 then goto done
    column = 4
    done: (we now have the column value)

    With the parts values shown in the circuit, the 4 timer periods are all less than 256uS. This is ideal for a PIC internal RC clock running at 4MHz and timer0 prescaler set to 1:1 (so 256uS = 256 timer counts). The 3 setpoints can be adjusted after some testing and ideally the grabbed timer values should be safely in the middle between the setpoints you choose.

    Advantages and Disadvantages

  • Only 3 pins needed for a 12-key keypad!!
  • The system uses no power until a key is pressed
  • Very little power is used to do the key tests
  • No power is used after tests are done if key is held down
  • The system is very reliable once good setpoints have been chosen
  • Testing is very quick, and can be repeated as a safety "debounce"
  • System uses very little code space
  • Suitable to be a battery powered remote (use a low quiescent current voltage regulator)

  • Needs a reasonably stable (regulated) supply voltage
  • Needs 7 resistors and 3 caps
  • More fussy to use than just using 7 PIC pins in the traditional way

    Tips for commercial use

    By reducing the caps to 22pF you can get rid of the 3x 220 ohm resistors to save costs. This will mean increasing the 4 timing resistors by a large amount and changing the timing code accordingly. PIC pin leakage will affect timing periods so some careful tuning may be needed.

    To save the cost of a regulator, you could increase the difference between the timed periods by changing the 4 resistor values. Make the first R much lower and the last R much higher as these can be defaulted, and the only 2 critical values are the middle 2. Something like a binary multiple may work best, like 1k,4k,16k,64k etc. I'm fairly sure that with some fine tuning the time periods can be made reliable even through a full 40% PSU voltage drop as may occur with batteries. Code will need to be modified to suit the wider timing ranges. As an interesting bonus the PIC could detect it's own battery voltage by the change in time periods as the battery ages, this effect has been noted before when using RC timed periods and the PIC TTL inputs.

    - end -

    [Back to Home Page]