user3674628
user3674628

Reputation: 29

Button debouncing pic16f877a code not working

in pic16f877a I am trying to make a code used for software debouncing using a single button but whenever I click the button it goes on and never goes off again here is the code:

#include "config.h"

unsigned int ledToggle(void);

void main(){
    
    TRISCbits.TRISC0 = 1;
    TRISDbits.TRISD0 = 0;
    PORTDbits.RD0 = 0;
    
    while(1){
        if(PORTCbits.RC0 == 1){
            
            if(ledToggle()%2 == 0){
                PORTDbits.RD0 = 1;
            }else{
                
                PORTDbits.RD0 = 0;
                
            }
        }
        
        
    }
    
}


unsigned int ledToggle(){
    static int i = 2;
    i++;
    return i;
    
}

EDIT


I also made this new code which has a problem and it is it sometimes work sometimes not here it is:

#include "config.h"

static char flag = 0;
static int counter = 0;

unsigned int ledToggle(void);

void main(){
    
    TRISCbits.TRISC0 = 1;
    TRISDbits.TRISD0 = 0;
    PORTDbits.RD0 = 0;
    
    while(1){
        
        if(ledToggle()%2 == 0){
            PORTDbits.RD0 = 1;
        }else{
            
            PORTDbits.RD0 = 0;
            
        }
        
        
    }
    
}


unsigned int ledToggle(){
    
    if(PORTCbits.RC0 == 1 && flag == 0){
        
        counter++;
        flag = 1;
        
    }else{
        
        counter += 0;
        flag = 0;
    }
    if(PORTCbits.RC0 == 0){
        
        flag = 0;
    }
    return counter;
    
}

and btw I forgot to mention that config.h is a header file I made to configure bits and crystal frequency (_XTAL_FREQUENCY)

Upvotes: 0

Views: 1496

Answers (2)

user3674628
user3674628

Reputation: 29

I found the best and easiest solution for my question:

the second code wasn't working(sometimes work and others not) because when I press the button the signal that comes are a combination of 1s and 0s here's the demonstration!

https://i.sstatic.net/qR42D.png

this is a very simple and actually bad pic I drew in paint to show you all. so what u need to do is to skip the first part or the part with ones and zeroes (1010101010) on button press and u do it that way:

1.declare a variable called ButtonPress_Level

2.inside the while loop make another while loop that keeps adding 1s to this variable as long as button is pressed

3.skip the first part where the 0s and 1s are and start led on or off for example after the first 500 signals

this might not seems understandable but you will get it when you see the whole code::

                #include "config.h"

                static char flag = 0;
                static int counter = 0;
                static unsigned int Pressed_Level = 0;

            unsigned int ledToggle(void);

            void main(){
                TRISDbits.TRISD0 = 0;
                TRISCbits.TRISC0 = 1;

                PORTDbits.RD0 = 0;

                while(1){

                        if(ledToggle()%2 == 0){
                            PORTDbits.RD0 = 1;
                        }else{

                            PORTDbits.RD0 = 0;

                        }


                }

            }


            unsigned int ledToggle(){

                if(PORTCbits.RC0 == 1 && flag == 0){

                    while(PORTCbits.RC0 == 1){
                    Pressed_Level++;
                    }
                    flag = 1;

                    if(Pressed_Level >= 500){
                    counter++;
                    }

                }else{

                    counter += 0;
                    flag = 0;
                    Pressed_Level = 0;

                }
                if(PORTCbits.RC0 == 0){

                    flag = 0;
                }
                return counter;

            }

and again config.h is a header file where just set the configuration bits so don't worry it is not important for you

so in this code the debounce just works as a counter and switches the pin on if number if even and off if it is odd

Upvotes: 0

Mathieu L.
Mathieu L.

Reputation: 438

I see two things wrong here. First, you only change the state of your output when RC0 is high. Therefore, when RC0 goes low your output just stays in its previous state, whatever it may have been. If, for example, you want your ouput to go low when the input is off:

while(1){
    if(PORTCbits.RC0 == 1){
        if(ledToggle()%2 == 0){
            PORTDbits.RD0 = 1;
        }else{
            PORTDbits.RD0 = 0;
        }
    }
    else
        PORTDbits.RD0 = 0;
}

The second thing I see wrong here is related to rmi's comment. You mention that you are trying to de-bounce a button but without a delay or some other logic, this code does not do that. If your pic does not have much else to do, a simple solution could be :

while(1){
    if(PORTCbits.RC0 == 1){
        PORTDbits.RD0 = 1;//Or use you toggle, or something else

        //This will waste more than 65025 cycles (255*255 + loop overhead)
        //At 4MHz, thats 16ms minimum
        for( char i = 0; i < 0xFF; i++ )
            for( char j = 0; j < 0xFF; j++ )
                Nop();
    }
    else
        PORTDbits.RD0 = 0;
}

Upvotes: 0

Related Questions