0

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)

Kozmotronik
  • 2,080
  • 3
  • 10
  • 25
user3674628
  • 29
  • 12
  • Add a delay (say 50ms) when RC0 goes high. That rejects bouncing of the switch. In your code the loop rotates so fast toggling the LED when the button is pushed. – rmi Aug 15 '14 at 10:22
  • @rmi I also made a new code but it has some problems I ll edit – user3674628 Aug 15 '14 at 16:34

2 Answers2

0

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;
}
Mathieu L.
  • 438
  • 2
  • 8
  • 1
    That's not quite a debounce is it ? I believe that for a debounce the delay should apply only after the state of the key changes, and should apply in both directions. Because, when the button is pushed the detector may wobble between states until the button is fully down, and similarly wobble as the button is released until it is fully up. So the essence of a debounce is to ignore the wobbling, which means ignoring the state of the button for a short time after the state is seen to change. –  Aug 15 '14 at 16:40
0

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.stack.imgur.com/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

user3674628
  • 29
  • 12