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此计数器的起始值取决于当前循环时间。
当开关被翻转时,该计数器被清零,因此它(几乎)立即变为下一个周期。
这是我的代码:
#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此计数器的起始值取决于当前循环时间。
当开关被翻转时,该计数器被清零,因此它(几乎)立即变为下一个周期。