No announcement yet.

Interfacing a keypad with a microcontroller

  • Time
  • Show
Clear All
new posts

  • Interfacing a keypad with a microcontroller

    I am using a PIC16F877A (, running at 20 MHz.
    I have two paralleled, 3 columns, 4 rows keypad. My setup is as follows:

    KR1 to KR4 are rows, KC1 to KC3 are columns, and they all go to the microcontroller.
    In the program, rows are set as digital outputs and columns are set as digital inputs. Other peripherals of the pins are disabled. The way I scan the keys is as follows:
    I make the first row bit HIGH, then I check column 1, column 2 and column 3. If any of them is HIGH, then I wait a little and check again to de-bounce. If it is still HIGH, the program decides that a key is pressed. This routine follows for the other 3 rows.
    I check the keypad about every 100 ms, and for each row, it takes about 2.4uS as I measured with the oscilloscope. That, I guess, means, for a specific digit; set it high then try to measure for about 800nS, if nothing happens, move on.
    So the problem was weird. Every digit worked, except from '0'. It worked randomly and that random means rarely at the same time. Also, when I tried to measure its voltage to the ground with a multimeter in DC volts mode, and then pushed the button at the same time, it worked for every press.
    Then I added a delay of 5 uS after making the specific row HIGH and then I checked the columns. It worked!
    Now, what is the problem here? The keypad wires are about 30 cm (~12 inches) long. Is it some kind of a transmission line problem, like it is adding a delay? Or is the problem is sourced from the microcontroller; the microcontroller is not fast enough?
    Here is a portion of the code that is relevant to the issue:

    ... KEY_R4 = 1; delay_us(5); if (KEY_C1) { scan_keys.waitstate = 10; goto c4r1; } else if (KEY_C2) { scan_keys.waitstate = 11; goto c4r2; } else if (KEY_C3) { scan_keys.waitstate = 12; goto c4r3; } else { KEY_R4 = 0; presstime = 0; } ... c4r2: if (++presstime >= PRESSTIMEVALUE && !KEY_C2) { scan_keys.waitstate = 0; KEY_R4 = 0; return '0'; } return 'n'; ...

  • #2
    Hello Lucy12345. did you try to place series termination resistor into the lines (placing 33R resistors close to the microcontroller) or placing some small caps there? I would say, the note "wires are about 30cm long" could be important and also "with a multimeter ... it worked". By placing multimeter on the tracks you are changing capacitance and it can help to lower crosstalk / reflections on the tracks. What you may want to do is measure the rising / falling edge of the signals and make it slower (that can be done by series termination resistors or additional small capacitors or by combination of both). Please, let me know if that helped.