Кнопка устранения дребезга кода pic16f877a не работает

на pic16f877a я пытаюсь создать код, используемый для устранения дребезга программного обеспечения с помощью одной кнопки, но всякий раз, когда я нажимаю кнопку, она включается и больше никогда не гаснет, вот код:

                #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;

                }

РЕДАКТИРОВАТЬ


Я также сделал этот новый код, у которого есть проблема, и иногда он работает, иногда не здесь:

        #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;

        }

и, кстати, я забыл упомянуть, что config.h — это заголовочный файл, который я сделал для настройки битов и частоты кристалла (_XTAL_FREQUENCY)


person user3674628    schedule 15.08.2014    source источник
comment
Добавьте задержку (скажем, 50 мс), когда RC0 становится высоким. Это исключает дребезг переключателя. В вашем коде цикл вращается так быстро, переключая светодиод при нажатии кнопки.   -  person rmi    schedule 15.08.2014
comment
@rmi Я также сделал новый код, но у него есть некоторые проблемы, которые я отредактирую   -  person user3674628    schedule 15.08.2014


Ответы (2)


Я вижу здесь две неправильные вещи. Во-первых, вы меняете состояние своего выхода только тогда, когда RC0 высокий. Поэтому, когда RC0 становится низким, ваш выход просто остается в своем предыдущем состоянии, каким бы оно ни было. Если, например, вы хотите, чтобы ваш выход был низким, когда вход выключен:

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

Второе, что я вижу здесь неправильно, связано с комментарием rmi. Вы упомянули, что пытаетесь отменить отскок кнопки, но без задержки или какой-либо другой логики этот код этого не делает. Если на вашей картинке больше нечего делать, простым решением может быть:

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;
}
person Mathieu L.    schedule 15.08.2014
comment
Это не совсем дебаунс, не так ли? Я считаю, что для устранения дребезга задержка должна применяться только после изменения состояния ключа и должна применяться в обоих направлениях. Потому что, когда кнопка нажата, детектор может колебаться между состояниями до тех пор, пока кнопка не будет полностью нажата, и аналогичным образом качаться, когда кнопка будет отпущена, пока она не будет полностью поднята. Таким образом, суть устранения дребезга состоит в том, чтобы игнорировать колебания, что означает игнорирование состояния кнопки в течение короткого времени после изменения состояния. - person ; 15.08.2014

Я нашел лучшее и простое решение для моего вопроса:

второй код не работал (иногда работает, а иногда нет), потому что, когда я нажимаю кнопку, приходит сигнал, представляющий собой комбинацию 1 и 0, вот демонстрация!

http://i.imgur.com/gTDHavI.png

это очень простая и на самом деле плохая картинка, которую я нарисовал в краске, чтобы показать вам всем. поэтому вам нужно пропустить первую часть или часть с единицами и нулями (1010101010) при нажатии кнопки, и вы делаете это следующим образом:

1. объявить переменную с именем ButtonPress_Level

2. внутри цикла while создайте еще один цикл while, который продолжает добавлять 1 с к этой переменной, пока нажата кнопка

3. пропустите первую часть, где 0 и 1, и включите или выключите светодиодный индикатор, например, после первых 500 сигналов.

это может показаться непонятным, но вы поймете, когда увидите весь код::

                #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;

            }

и снова config.h - это заголовочный файл, в котором просто установите биты конфигурации, так что не волнуйтесь, это не важно для вас.

поэтому в этом коде debounce просто работает как счетчик и включает пин, если число четное, и выключает, если оно нечетное.

person user3674628    schedule 16.08.2014