5

私はcとRaspberry Piに比較的慣れておらず、簡単なプログラムを試しています. 私が望むのは、ボタンが押されたときに一度 printfs され、ボタンが押されたままになっていても (一種のラッチ)、ボタンが再度押されるまで再度 printf しないことです。2番目のwhileループを追加するとこれが修正されるのではないかと思いましたが、それでもボタンの押下が検出されないことがあります。

#include <bcm2835.h>
#include <stdio.h>
#define PIN RPI_GPIO_P1_11

int main()
{
    if(!bcm2835_init())
        return 1;

    bcm2835_gpio_fsel(PIN, BCM2835_GPIO_FSEL_INPT);

    while(1)
    {
        if(bcm2835_gpio_lev(PIN))
        {
            printf("The button has been pressed\n");
        }

       while(bcm2835_gpio_lev(PIN)){}
    }

    bcm2835_close();
    return 0;
}
4

3 に答える 3

2

あなたのロジックは正しく、ボタンが完璧であればこれは機能します。しかし、そうではありません。ボタンの信号をデバウンスする必要があります。それを達成するための 2 つの方法 (組み合わせた場合に最も効果的):

I. ボタンの 2 つのピン間にコンデンサを追加する (または、さらに洗練されたボタン デバウンサー回路を試す)、および/または

Ⅱ.ソフトウェア デバウンス (疑似 C) を使用します。

while (1) {
    while (!button_pressed)
        ;

    printf("Button pressed!\n");


    while (elapsed_time < offset)
        ;
}

編集:@jerryが指摘したように、ボタンが押されていると上記は「正しく」機能しません。すべての要件を満たすために使用できる、よりプロフェッショナルなコード スニペットをいくつか紹介します。

于 2013-04-30T18:51:18.167 に答える
1

次の関数は、名目上 1 ミリ秒間隔でボタンをポーリングし、状態が 20 回の連続したポーリングまで「リリース」のままである必要があります。これは通常、応答性を維持しながらほとんどのスイッチをデバウンスするのに十分です。

while(bcm2835_gpio_lev(PIN)){}ループを への呼び出しに置き換えますwaitButtonRelease()

#include <unistd.h>
#define DEBOUNCE_MILLISEC 20

void waitButtonRelease()
{
    int debounce = 0 ;

    while( debounce < DEBOUNCE_MILLISEC )
    {
        usleep(1000) ;

        if( bcm2835_gpio_lev(PIN) )
        {
            debounce = 0 ;
        }
        else
        {
            debounce++ ; 
        }
    }
}

ボタンのプレスとリリースをデバウンスする必要がある場合もあります。それは同じ方法で行われますが、反対の状態を数えます:

void waitButtonPress()
{
    int debounce = 0 ;

    while( debounce < DEBOUNCE_MILLISEC )
    {
        usleep(1000) ;

        if( !bcm2835_gpio_lev(PIN) )
        {
            debounce = 0 ;
        }
        else
        {
            debounce++ ; 
        }
    }
}

または、どちらかの状態をデバウンスする単一の関数:

#include <stdbool.h>

void waitButton( bool state )
{
    int debounce = 0 ;

    while( debounce < DEBOUNCE_MILLISEC )
    {
        usleep(1000) ;

        if( bcm2835_gpio_lev(PIN) == state )
        {
            debounce++ ;
        }
        else
        {
            debounce = 0 ; 
        }
    }
}

この最後の関数を考えると、メインの while ループは次のようになります。

    while(1)
    {
        waitButton( true )
        printf("The button has been pressed\n");

        waitButton( false ) ;
    }

デジタル ストレージ オシロスコープにアクセスできる場合は、スイッチ信号を直接調べて、スイッチ バウンスがどのように見えるかを正確に確認できます。問題を理解し、特定のスイッチの特性に合わせてデバウンスを調整するのに役立つ場合があります。

于 2013-04-30T19:31:05.370 に答える