Raspberry Pi,循环延迟函数

时间:2015-05-07 05:22:57

标签: c function raspberry-pi delay

这是我的代码:

#include <wiringPi.h>
#include <stdio.h>

#define LED 18
#define IN 24

int main(void)
{
    wiringPiSetupGpio ();
    pinMode (LED, OUTPUT);
    pinMode (IN, INPUT);
    for (;;)
    {
        digitalWrite (LED, 1);
        delay (2000);
        digitalWrite (LED, 0);
        delay (2000);

        if (digitalRead (IN) == 1)
        {
            for (;;)
            {
                digitalWrite (LED, 1);
                delay(500);
                digitalWrite (LED, 0);
                delay(500);

            }
        }    
    }    
    return 0;
}

我使用开关从2000延迟到500延迟。问题是,当我按下开关时,它会等待直到环路结束,直到它变得更快。同样适用于反之亦然。我需要在我的代码中的某处编写一个函数或循环,允许我按下开关并立即无需等待转到更慢/更快的速度。我正在使用接线pi库和gpio引脚编号在C上编程,在树莓pi上编码。

1 个答案:

答案 0 :(得分:2)

首先,您所显示的代码永远不会偏离2000的延迟,因为无法退出初始的for(;;)循环。这可能是您需要检查和修复的第一个事物。

在能够提前结束延迟方面,你可以做一些改变:

delay (2000);

成:

for (i = 0; i < 2000; i += 10) {
    delay (10);
    if (digitalRead (IN) == 1)
        break;
}

如果开关改变,这基本上会提前退出延迟,这样你就不会等待超过10个时间单位(而不是等于2000)。

请注意,重复调用延迟可能会产生开销。换句话说,虽然delay(2000)可能需要非常接近2000个时间单位,但由于每次通话的设置时间等原因,对delay(10)的200次通话可能会花费更多时间。

事实上,通过不使用硬编码值,您可以大大简化代码。相反,您可以使用一个具有最小延迟的单个循环,并使用一些内部控制来确定何时以及如何更换LED(即,不是每个时间通过循环)。

例如,像这样的事情就可以做到。我没有测试过,因为我的Pi2仍然坐在一个盒子里等待一段时间让我玩它,但它应该非常接近:

#include <wiringPi.h>
#include <stdio.h>

#define LED 18
#define IN 24
#define RES 10

int main (void) {
    int cycleTime, ledState, lastSwitch, currSwitch, timeLeft;

    wiringPiSetupGpio ();
    pinMode (LED, OUTPUT);
    pinMode (IN, INPUT);

    cycleTime = 2000;  // Initial cycle time
    ledState = 0;      //   and LED state.
    lastSwitch = 0;    // Previous switch state,

    // Start infinite loop with first cycle time.

    timeLeft = cycleTime;
    for (;;) {
        // Delay for minimal time and adjust time left.

        delay (RES);
        timeLeft = timeLeft - RES;

        // Detect switch change.

        currSwith = digitalRead (IN);
        if (currSwitch != lastSwitch) {
            // If so, store new state, change cycle time
            //   and force IMMEDIATE end of current cycle.

            lastSwitch = currSwitch;
            cycleTime = 2500 - cycleTime;  // switch 500 <-> 2000
            timeLeft = 0;
        }

        // Detect end of cycle.

        if (timeLeft <= 0) {
            // Toggle LED and start new cycle.

            ledState = 1 - ledState;
            digitalWrite (LED, ledState);
            timeLeft = cycleTime;
        }
    }
}

基本上,你有一个循环,但每循环一个循环,而不是每500或2000循环。你维护一个单独的计数器,它决定何时应该翻转LED和起始值此计数器取决于当前的循环时间。

当翻转开关时,该计数器归零,以便(几乎)立即改变到下一个循环。