# PIC16F877a input always true

I am programming a PIC16F877a with 3 toggle switches and a 20 x 4 LCD. The 3 switches are soldered to pins B0 - B2 on the PIC. The other end of the switches is connected to +5v (PortsB have internal pull up resistors). I am programming using CCS and the problem I've met is that for some reason, ports B0 - B2 always read true and ignores the buttons. The problem might be a software issue so here's my program:

#include <16f877a.h>
#fuses XT,NOWDT,BROWNOUT,PUT,NOLVP
#use delay (crystal=4000000)

#include <Flex_LCD420.c>
#include <7segDisp.c>

#define btn_A PIN_B0
#define btn_B PIN_B1
#define btn_C PIN_B2

int i;
void main() {

output_low(LCD_RW);

lcd_init();
printf(lcd_putc, "\fPress Any Button");
while(1){
if(input(btn_A) == 0 || input(btn_B) == 1 || input(btn_C) == 1) {
break;
}
}
printf(lcd_putc, "\fChecking Btns..A");
while(1){
if(input(btn_A) == 1) {
break;
}
}
printf(lcd_putc, "\fChecking Btns..B");
while(1){
if(input(btn_B) == 1) {
break;
}
}
printf(lcd_putc, "\fChecking Btns..C");
while(1){
if(input(btn_C) == 1) {
break;
}
}
printf(lcd_putc, "\f\nEnd Check");
while(1);
}


I need help urgently as this is for a project that is due today.

• I don't even see any modification to TRIS registers, analog selection registers, or portb pull-up bits? I don't know about CCS, but a quick search showed me that if you are using those output_low(); and such, you should add a directive, something like fast i/o. – abdullah kahraman Jun 12 '12 at 7:42

If you are using the internal pullups, then you can simply connect the other side of the switches to ground instead of +5V and invert your detection logic (i.e. 1 = no press, 0 = press)

The pullups are very weak so they act like a high value resistor connected from the pin to +5V inside the PIC.
As mentioned by arminb, the pullups are currently keeping your pins at a logic high, so the pin always reads 1.

In your code I would add a debouncing check to your routines to be thorough, as with the first "Press any button" check if you press button A, the switch may bounce, the micro will detect more than one press and and go through the second "Checking button A" check too.

A mechanical switch usually "bounces" between 1 and 0 a few times before it settles, so the microcontroller can detect more than one "press" unless you do something about it. This is often solved in software simply by testing the button, if pressed wait a few milliseconds and then check again - if it is still pressed then it is valid.
Here are a couple of links to debouncing tutorials/code:
Arduino example
12F675 example
Switch bounce tutorial with various solutions

Port B has internal pull-ups, but they're disabled at power-up (datasheet, p.46). You didn't enable them, so they're not active.

Even if they were you would have a problem: the pull-ups make the input high, and pressing a button will also set a high level to the input. When will it be low? Never. You have to connect the buttons to ground, not Vcc. And activate the pull-ups. Clearing the RBPU bit in OPTION_REG<7> enables all pull-ups on the port.

If you press a button, you feed the appropriate input pin with +5V. Because of the internal pull-ups the micorontroller wants to keep the +5V signal at the input pin. That means if you release the button there is no defined signal you feed into the pin. It is +5V but it should be 0V (GND). The solution is to connect resistors against GND for each button. The resistors can be ~100kOhm.

• This is not a good solution. First, you create a voltage divider. Second, a small amount of current will flow through the internal pull-up and through the pull-down at all times. You don't use both a pull-up and a pull-down on the same digital pin. – Armandas Jun 11 '12 at 6:31
• I guess I assumed too much, but you should point out, that if your solution is used, the internal pull-ups should be switched off. – Armandas Jun 11 '12 at 6:33
• The reason for internal pull ups is to reduce part count in these kind of situations. Seems wasteful to then add external ones. – Cybergibbons Jun 11 '12 at 6:49

I am going to assume that you have set TRIS, often you need to also set ANSEL to change the pins NOT to be analog. While configured as analog inputs the pins will always read one value, regarless of the value on the pin.