根据我的阅读,我的问题的解决方案是使用中断,但如果我理解正确,我就不能在中断调用的例程中使用延迟。我有一个大按钮 LED转变。我希望它在闲置时有心跳,但一旦它被推送,就保持绿色并执行代码。
如果我按下按钮的次数足够多,我可以中断 heartbeat()
(我假设在正确的时间获得状态更改,因为它完成了 heartbeat
),但我一直在研究如何让它在第一次点击时起作用。有没有其他方法可以完成我正在尝试的事情?
void loop(){
heartbeat(); //Make LED beat.
buttonVal = digitalRead(buttonPin); //Check the button.
if (buttonVal != buttonState) { //If the button state changed.
if (buttonVal == HIGH){ //Check if the button is pressed.
analogWrite(greenPin, 255); //Button stays green once pushed.
functionA //Has some delays in it.
functionB //Has some other delays.
}
}
}
void heartbeat(){
for(i = 0; i < pmw; i++) {
analogWrite(greenPin,i);
delay(((60000/rate)*.1)/pmw);
}
for (i = pmw; i > 0; i--){
analogWrite(greenPin,i);
delay(((60000/rate)*.2)/pmw);
}
for(i = 0; i < pmw; i++) {
analogWrite(greenPin,i);
delay(((60000/rate)*.1)/pmw);
}
for (i = pmw; i > 0; i--){
analogWrite(greenPin,i);
delay(((60000/rate)*.6)/pmw);
}
}
最佳答案
您的大部分假设都是正确的。处理此问题的正确方法是使用中断,在中断服务例程 (ISR) 中延迟并不是一个好主意。所以您要做的是在您的 ISR 中设置一个标志并在您的主循环中检查该标志。
// Flag needs to be volatile if used in an ISR
volatile int buttonFlag = 0;
void loop()
{
if (buttonFlag == 0)
{
heartbeat(); //make led beat
}
else
{
analogWrite(greenPin, 255); //button stays green once pushed
functionA //has some delays in it
functionB //has some other delays
buttonFlag = 0; //clear flag after executing code
}
}
// Interrupt Service Routine attached to INT0 vector
ISR(EXT_INT0_vect)
{
buttonFlag = digitalRead(buttonPin); //set flag to value of button
}
由于中断只会在按钮状态发生变化时触发,因此您无需检查。
确保你的标志变量是全局的并且被声明为volatile
用于 ISR。并确保您使用正确的中断 vector 与您正在使用的引脚一起使用。
这是一个good tutorial在 Arduino 中断。这是另一个 good example你正在尝试做的事情。
您可能还想查看 debouncing your switch按下取决于您使用的开关类型。如果不是错过第一次按下,而是按下太多,则需要实现某种类型的去抖动。
关于c - Arduino 中断替代品,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/13583419/