pull up resistors needed to connect keypad to PIC16f877A

Discussion in 'Embedded Systems and Microcontrollers' started by FG1, Jun 16, 2010.

  1. FG1

    Thread Starter New Member

    Jun 11, 2010
    6
    0
    i need to connect a 4x4 keypad to PIC16F877A. i have read about some pull up resistors needed to perform this connection and i don't quite get it. do they need to be connected on all the 8 lines (4 rows, 4 columns) of keypad. if yes, how?
    also i have read somewhere that if keypad is being connected to portB of PIC then these resistors aren't needed. is that true? i am using port B only and confused about whether or not to use the resistors.
     
  2. Vaughanabe13

    Active Member

    May 4, 2009
    102
    5
    So you will have 4 rows and 4 columns. You connect the 4 rows to any 4 INPUTS, and the 4 coloumns to any 4 OUTPUTS. You can can use one port and make half input and half output, for convenience. It will look like this graphic:
    [​IMG]
    Then put pullup resistors on each row of this grid. IE, attach a resistor from Row1 to VCC, Row2 to VCC, etc. (NOT shown in this graphic). This will make the rows be logic HIGH by default. Depending on your uC you can probably enable these pullup resistors in software, rather than adding physical resistors. I think PORTB on most PIC uC's has internal pullups, which is why you were told to use that port.
    Now poll in software to see which button is being pressed. Drive all the columns low and wait for a low input on Rows 1-4 (this can be handled in interrupts if you have 4 pins that will throw an interrupt on a high-low transition). Lets say Row4 becomes low, so we know either C,D,E or F is being pressed. Now debounce the button by delaying about 5-10ms. Now to figure out which button in Row4 is pressed, go through the 4 combinations of low-high on the columns and look for a low value on the row. IE, make Col1 low, and Cols2-4 high and if Row4 is low it means button C is being pressed. etc.
     
    Last edited: Jun 23, 2010
    Yvan Ngassa likes this.
  3. Markd77

    Senior Member

    Sep 7, 2009
    2,803
    594
    If you do a quick search for keypad PIC16F877 you should find some examples.
    Port B has internal pull up resistors when the pins are set as inputs, but they have to be turned on in software. Have a look at the OPTION register to turn them on.
     
  4. FG1

    Thread Starter New Member

    Jun 11, 2010
    6
    0
    thanks for the help.. here is what i have done (hoping its not wrong).
    port B (0:3) used for column rows and connected directly to PIC
    port B (4:7) connected to PIC via 10K resistors whose other end is grounded.

    are these connections right? Also, i have no clue about how to program the keypad. I am using PicBasic Pro. can anyone please help and provide a relevant code that i may try and test my keypad with?
     
  5. Vaughanabe13

    Active Member

    May 4, 2009
    102
    5
    Um, I just told you exactly how to do it. You're not going to get any more clear of an explanation than that. I told you how to hook it up to the PIC and how to read the key presses in software.
     
  6. John P

    AAC Fanatic!

    Oct 14, 2008
    1,634
    224
    I disagree with Vaughanabe13. Don't use any resistors at all, and don't connect anything to Vcc or Gnd. Just connect the 4 rows to (say) PortB pins 0-3 and the 4 columns to (say) PortB 4-7. Turn on the internal pullups (set Option reg bit 7 to 0) and decide whether your rows or columns will be the inputs: clear the Tris bits for those pins and set the Tris pins for the outputs. That's all you need to do.
     
  7. MMcLaren

    Well-Known Member

    Feb 14, 2010
    759
    116
    I disagree too.

    A carefully designed keypad driver will scan one column at a time by making one column line "output low" and the other three column lines "input high" (using int/ext pull-up).

    Caveat! If you drive one column line "output low" and the other three column lines "output high" then you can cause a dead short by pressing certain key combinations at the same time.

    Cheerful regards, Mike
     
    Last edited: Jun 22, 2010
  8. John P

    AAC Fanatic!

    Oct 14, 2008
    1,634
    224
    I think you mean "output high". But anyway, you can avoid the possibility of connecting two outputs together if you scan the keypad by setting all four of the column lines to 0 (if it's the columns that are the outputs) and then controlling the Tris bits for the columns. The way this works is that one column at a time can sink current, and none of them can source current, except from the internal pullups. I admit that earlier I said that the columns should all be made into outputs, and that was wrong; only one at a time should be an output.
     
  9. FG1

    Thread Starter New Member

    Jun 11, 2010
    6
    0
    thanks for the input from all you people..i have managed to get hold of it now and your comments have clarified a few more points =)
     
  10. Vaughanabe13

    Active Member

    May 4, 2009
    102
    5
    That is exactly what I said, therefore you do not disagree with me. If you drive all 4 columns high, set the 4 rows as inputs, tie them to VCC with internal pullups and set them to interrupt-on-negedge, then you can run other code instead of constantly checking the keypad. Then you use the interrupt service to handle the button press, as I already described in my earlier post. It is a more efficient and more versatile way of doing it.
     
    Last edited: Jun 22, 2010
  11. Vaughanabe13

    Active Member

    May 4, 2009
    102
    5
    Again, this is exactly what I said. I already mentioned using internal pullups instead of physical resistors, which is the same thing as connecting a line to VCC. You can do it in software or hardware, it doesn't matter. But the result is identical.
     
  12. MMcLaren

    Well-Known Member

    Feb 14, 2010
    759
    116
    I disagreed with you on a couple points;

    (1) If you're using rows as inputs with pull-up resistors then you're looking for an active-low signal through the switches which requires one (or all) column outputs to be driven low and not high as you suggested.

    (2) You weren't clear about how you set the column outputs low and high and so I suspect you were simply leaving them setup as outputs and setting the corresponding port latch bits low and high which is a potential hazard. That method works fine if you install diodes on the four column driver lines, otherwise you need to select column outputs using the TRIS bits so that only one of the column driver lines is an output.

    If I misinterpreted your post, I apologize.

    Cheerful regards, Mike
     
    Last edited: Jun 23, 2010
  13. FG1

    Thread Starter New Member

    Jun 11, 2010
    6
    0
    i am using the following code in Pic basic pro but only my first 2 rows seem to gvie the correct pressed number on LCD, the last two rows give the wrong value.

    can anyone identify the problem in the code

    HARDWARE CONNECTIONS: pin 0:3 connected to rows via `10k resistors
    pin 4:7 connected to coulmns

    ' PicBasic Pro program to display key number on LCD
    ' Define LOADER_USED to allow use of the boot loader.
    ' This will not affect normal program operation.
    Define LOADER_USED 1
    ' Define LCD connections
    DEFINE OSC 20
    DEFINE LCD_DREG PORTD
    define LCD_DBIT 0
    DEFINE LCD_RSREG PORTE
    DEFINE LCD_RSBIT 0
    DEFINE LCD_EREG PORTE
    DEFINE LCD_EBIT 1
    DEFINE LCD_RWREG PORTE
    DEFINE LCD_RWBIT 2
    DEFINE LCD_BITS 8
    DEFINE LCD_LINES 2
    DEFINE LCD_COMMANDUS 2000
    DEFINE LCD_DATAUS 50
    ' Define program variables
    col var byte ' Keypad column
    row var byte ' Keypad row
    key var byte ' Key value
    OPTION_REG.7 = 0 ' Enable PORTB pullups
    ADCON1 = 7 ' Make PORTA and PORTE digital
    Low PORTE.2 ' LCD R/W low (write)
    Pause 500 ' Wait for LCD to start
    Lcdout $fe, 1
    pause 250
    lcdout "Press any key" ' Display sign on message
    loop: Gosub getkey ' Get a key from the keypad
    Lcdout $fe, 1, #key ' Display ASCII key number
    Goto loop ' Do it forever
    ' Subroutine to get a key from keypad
    getkey:
    PAUSE 50 'Debounce key-input
    getkeyu:' Wait for all keys up
    PORTB = 0 ' All output-pins low
    TRISB = $f0 ' Bottom 4-pins out, top 4-pins in
    IF ((PORTB >> 4) = $f) THEN getkeyu'If keys down, loop
    PAUSE 50 ' Debounce key-input
    getkeyp:' Wait for keypress
    FOR row = 0 TO 3 ' 4 rows in keypad
    PORTB = 0 ' All output-pins low
    TRISB = (DCD row) ^ $ff ' Set one row pin to output
    col = PORTB >> 4 ' Read columns
    IF col != $f THEN gotkey' If any keydown, exit
    NEXT row
    GOTO getkeyp ' No keys down, go look again
    gotkey: ' Change row and column to key number 1 - 16
    key = (row * 4) + (NCD (col ^ $f))
    'NOTE: for 12-key keypad, change to key = (row * 3)
    RETURN ' Subroutine over

    END
     
  14. MMcLaren

    Well-Known Member

    Feb 14, 2010
    759
    116
    Hi FG1,

    What is "DCD"? Could this be a problem?
    Code ( (Unknown Language)):
    1.     TRISB = (DCD row) ^ $ff    ' Set one row pin to output
    Could this be generating TRISB values of '11111111' (row = 0), '11111110' (row = 1), '11111101' (row = 2), and '11111100' (row = 3)?

    You want to generate TRISB values of '11111110', '11111101, '11111011', and '11110111' as you scan rows 0 through 3. I'm not familiar with PBP but couldn't that be done something like this?
    Code ( (Unknown Language)):
    1. FOR row = 0 TO 3            ' 4 rows in keypad
    2.   PORTB = 0                 ' All output-pins low
    3.   TRISB = (1 << row) ^ $ff  ' Set one row pin to output
    4.   col = PORTB >> 4          ' Read columns
    5.   IF col != $f THEN gotkey  ' If any keydown, exit
    6. NEXT row
    7.  
    Cheerful regards, Mike
     
  15. FG1

    Thread Starter New Member

    Jun 11, 2010
    6
    0
    DCD is actually decode...(DCD row) sets the corresponding bit position as indicated by the row value
    DCD 0 = 00000001 (for row=0)
    DCD 1 = 00000010 (for row=1) and so on..

    so this cannot be the problem. i cant really seem to understand the fucntionality of the getkeyu loop.. what is its significance in this program?
     
  16. FG1

    Thread Starter New Member

    Jun 11, 2010
    6
    0
    Also, thanks a lot for the input :)
     
Loading...