Jos*_*key 0 c embedded microcontroller arduino interrupt
从我读到的,我的问题的解决方案是使用中断,但如果我正确理解它,我不能在中断调用的例程中使用延迟.我有一个大按钮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);
}
}
Run Code Online (Sandbox Code Playgroud)
在大多数假设中,你是对的.处理此问题的正确方法是使用中断,并且在中断服务例程(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
}
Run Code Online (Sandbox Code Playgroud)
由于中断只会在按钮状态发生变化时触发,因此您无需检查.
确保您的标志变量是全局的,并声明volatile
在ISR中使用.并确保使用正确的中断向量与您正在使用的引脚一起使用.
这是一个关于Arduino中断的好教程.这是你要做的另一个很好的例子.
您可能还希望根据您使用的开关类型来调试您的开关印刷机.如果没有错过第一次按下,你得到太多的印刷机,你需要实施某种类型的去抖动.