ABC of Electronics cosycom.com
PIC BASICS · LESSON 10

Reading a Push Button

Reading a button sounds trivial, but a mechanical switch is messier than it looks — this lesson covers pull resistors and the 'bounce' every button produces.

A push button is just a switch: press it, and it connects two points; release it, and the connection breaks. To read that state with a GPIO pin, the pin needs to have a well-defined voltage in both the pressed and unpressed positions — and a bare button wired to only one side of the circuit doesn't guarantee that.

The fix is a pull resistor. A pull-up resistor connects the pin to the supply voltage through a large resistance (commonly ten thousand ohms or more); when the button is not pressed, the pin reads high through that resistor, and when the button is pressed and connects the pin to ground, the small resistance of the closed switch overwhelms the pull-up and the pin reads low. A pull-down resistor does the reverse, defaulting the pin to low and pulling it high when pressed. Many PIC chips include configurable internal pull-up resistors on their pins, removing the need for an external one entirely.

Reading a button with an internal pull-up
Button statePin reads
Not pressedHigh (1) — pulled up through the resistor
PressedLow (0) — pulled directly to ground

The second issue is switch bounce: the metal contacts inside a mechanical button don't close cleanly — they physically bounce for a few milliseconds, producing several rapid on/off transitions before settling. Read the pin during that window and your code may see one press as five or six. The simplest software fix, called debouncing, is to detect a change and then wait a short, fixed time — typically ten to twenty milliseconds — before trusting the new reading as stable.

main.c — a simple debounced button read
void main(void) {
    TRISB1 = 1;        // RB1 as input (button)
    TRISB0 = 0;        // RB0 as output (LED)

    while(1) {
        if (PORTBbits.RB1 == 0) {   // pressed (active-low)
            __delay_ms(15);              // wait out the bounce
            if (PORTBbits.RB1 == 0) {   // still pressed?
                LATB0 = ~LATB0;          // toggle the LED
                while (PORTBbits.RB1 == 0); // wait for release
            }
        }
    }
}
KEY TAKEAWAY
A real button is noisy for a few milliseconds every time it's pressed. A short delay after detecting the first change is usually all it takes to read it reliably.