1
\$\begingroup\$

enter image description hereI am trying to make a simple counter using pic16f877a. I want to count each time a push button is pressed, that is taking one press as one count, regardless of how long the button is pressed.

The software I am using are MPLAB X IDE and XC8 compiler. I use Pickit 3.5. I use an indicator LED to see whether the code is working.

The thing is, I have barely achieved what I needed, but the code seems unstable. It works sometimes but not in others. For example, let say the code worked now and LED blinked correctly when one of two connected buttons pushed. Then if I "make" and "download" the program again without any edits to the code in MPLAB X IDE, the LED won't blink. While writing this I tested several times just by making and downloading using MPLAB IDE, without changing anything hardware or code, and then it worked. The only thing that was changed in those situations was TIME. I suspect this has something to do with resetting of the PIC although I have no idea. Never worked on 2 consecutive "make and download"s.

Code:

#define _XTAL_FREQ 20000000
#include <xc.h>
#include <stdio.h>
#include <stdlib.h>
#include <pic16f877a.h>
// CONFIG
#pragma config FOSC = HS    
#pragma config WDTE = OFF    
#pragma config PWRTE = OFF   
#pragma config BOREN = OFF   
#pragma config LVP = OFF    
#pragma config CPD = OFF  
#pragma config WRT = OFF        
#pragma config CP = OFF

void main(void) {
    TRISB=0;//LED connected to RB0
    TRISD=1;//two push buttons connected to RD0(buttonRight) and RD1(buttonLeft)

    while(1)
    {
        if (PORTDbits.RD0==0)//if buttonRight is pressed,
        {
            __delay_ms(5);//debouncing.
            if (PORTDbits.RD0==0)//if buttonRight is still pressed,
            {
                PORTBbits.RB0=1;
                __delay_ms(500);
                PORTBbits.RB0=0;
                __delay_ms(500);

                /*to take as one press no matter for how long it is pressed.*/
                while(PORTDbits.RD0==0);
            }
        }

        else if (PORTDbits.RD1==0)//if buttonLeft is pressed,
        {
            __delay_ms(5);//debouncing.
            if (PORTDbits.RD1==0)//if buttonLeft is still pressed,
            {
                PORTBbits.RB0=1;
                __delay_ms(100);
                PORTBbits.RB0=0;
                __delay_ms(100);

                /*to take as one press no matter for how long it is pressed.*/
                while(PORTDbits.RD1==0);
            }
        }
    }
}
\$\endgroup\$
  • \$\begingroup\$ What does the rest of the circuit look like? Power supply, connections to PIC etc... \$\endgroup\$ – awjlogan Nov 29 '17 at 18:36
  • \$\begingroup\$ Do you have decoupling caps near your uC? \$\endgroup\$ – Tyler Nov 29 '17 at 18:46
  • \$\begingroup\$ @Tyler not near uC, but near the pickit connection Vdd and Vss are connected by a capacitor on breadboard. \$\endgroup\$ – stackUsr Nov 29 '17 at 18:48
  • 1
    \$\begingroup\$ TRISB=0; sets the whole of portB (all 8 pins) as outputs. TRISD=1; sets RD0 as an input, and the rest of portD as outputs. Is this what you intended? \$\endgroup\$ – brhans Nov 29 '17 at 19:41
  • 1
    \$\begingroup\$ @brhans You are RIGHT!! adding "TRISD0=1; and TRISD1=1" makes the code work everytime! although i have no idea what was the reason it worked. I thought TRISD=1 was the way to go. Why is that? Please post as answer if you will. \$\endgroup\$ – stackUsr Nov 29 '17 at 20:21
0
\$\begingroup\$

Port D0 and Port D1 should be an input. If you write:

TRISD = 1;

you only make PortD.1 an input.

Maybe ist clearer if you think in binary:

TRISD = 1:

is simular to:

TRISD = 0b00000001;

which writes 1 only to Port D.0 and put all other Pin of D to 0. So write:

TRISD = 0b00000011;
\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.