Raspberry Pi,循环延时函数

Raspberry Pi, looping delay function

这是我的代码:

#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 延迟。问题是,当我按下开关时,它会一直等到循环结束,直到它变得更快。反之亦然。我需要在我的代码中的某处编写一个函数或循环,让我按下开关并立即进入 slower/faster 速度。我正在使用接线 pi 库和 gpio 引脚编号在 raspberry pi 上用 C 编写代码。

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


就能够提前结束延迟而言,您可以做一些改变:

delay (2000);

进入:

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

如果开关发生变化,这基本上会提早退出延迟,这样您就不会等待超过 10 个时间单位(而不是最多 2000 个)。

请注意,重复调用 delay 可能会产生开销。换句话说,虽然 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;
        }
    }
}

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

当开关被翻转时,该计数器被清零,因此它(几乎)立即变为下一个周期。