为什么中断会停止程序而不是跳回来?

时间:2016-11-06 14:38:05

标签: c loops arduino interrupt-handling

我正在研究arduino,我在loop()中有两种模式,在while循环中是mode1,在while循环中是第二种模式,它们有条件可以满足,我在它们之间使用按钮来切换它们当前执行,更改标志以强制程序更改为第二模式,并且出于某种原因而不是打破当前循环(因为不再符合conditoins)以更改为另一个它只是没有响应

或自动更改>停止响应

#define modeSwitch 2
boolean manual;
boolean automatic;
String sOld;
boolean flagPrint = false;
volatile int modeSwitchValue;
String receivedData = "";
String invitation = "Welcome to Morse Code Encoder!\nPlease choose a mode: Write 'automatic' for an automatic mode or 'manual' or manual code.\n";



void setup() {
  pinMode(modeSwitch, INPUT);
  attachInterrupt(0, changeMode, RISING);
  manual = false;
  automatic = false;
  volatile int modeSwitchValue = 5;
  Serial.begin(9600);
  Serial.println(invitation);
}

void loop() {
  if (Serial.available() > 0) {
    receivedData = Serial.readStringUntil('\n');
    if (receivedData == "manual" ) {
      manual = true;
      automatic = false;
      modeSwitchValue = 0;
    }
    if ( receivedData == "automatic") {
      automatic = true;
      manual = false;
      modeSwitchValue = 1;
    }

    while ((manual == true) && (modeSwitchValue == 0) ) {
      String s = "Manual mode:";
      while (checkPrint(s) == true) {
        Serial.println(s);
      }

      automatic = false;
    }

    while ((automatic == true) && (modeSwitchValue == 1)) {
      String s = "Automatic mode:";
      while (checkPrint(s) == true) {
        Serial.println(s);
      }
      manual = false;
    }

  }

}

void changeMode() {

  if (  modeSwitchValue == 0) {
    modeSwitchValue = 1;
    automatic = true;
    manual = false;

  }
  if ( modeSwitchValue == 1) {
    modeSwitchValue = 0;
    manual = true;
    automatic = false;

  }
}

我删除了checkPrint()函数,因为它只能确保msgs被打印一次因此我认为这不是必不可少的

我认为在执行自动代码时,我按下按钮并中断,更改模式变量然后返回到发生中断的程序中的相同位置。然后软件注意到自动模式的循环条件不再满足,因此它会跳转到循环()并找到自满足条件后执行手动模式的循环。我错了吗?或者我错过了什么?

2 个答案:

答案 0 :(得分:0)

你正在混淆任务" ="和比较" =="在你的changeMode()函数中。以下是该功能的更正版本。

fullText

您还应该意识到机械按钮可以有触点反弹。由于您使用中断来检测按钮状态的变化,因此可能会出现不稳定的行为。通常,最好轮询按钮状态并应用大约20ms的去抖时间延迟。

您还没有分享按钮的连线方式。由于您检测到上升沿,我认为按下按钮是为了在按下时将引脚拉高。如果您使用单刀单通按钮,则需要一个下拉电阻接地,否则中断引脚将浮动。

通过在输入引脚和地之间连接一个简单的按钮,可以避免所需的上拉或下拉电阻。然后将初始化代码更改为

var fullTextFunctions = [];
function setText(text, lang, full) {
    setTimeout(function () { $('#loading').fadeOut('fast'); }, 300);
    var mylang = '<?= $_SESSION['lang']; ?>';
    if (mylang != 'en' && lang == 'en')
        var AppendText = '<span class="db f09 grey mt10"><?= __('TEXT_ONLY_ENGLISH'); ?></span>';

    console.log(lang);

    if (full) {
        $('#text').html('<?= __('EMPTY'); ?>');
        setTimeout(function () { $('#text').fadeIn('fast'); }, 500);
    } else if (text) {
        // Full Text
        fullTextFunctions.push(function fullText() {
            console.log('yes');
            setText(text, lang, 1);
        })

        text = text.length > length ? text.substring(0, length - 3) +
        '... <a class="cp" onclick="fullTextFunctions[' + (fullTextFunctions.length - 1) + ']()"><?= __('MORE') ?></a>' : text;
        $('#text').html(text).append(AppendText);
        setTimeout(function () { $('#text').fadeIn('fast'); }, 500);
    }
};

function releaseFullTextFunction(index) {
    fullTextFunctions[index] = null;
}

然后,您将需要在下降沿触发中断。

我希望这会有所帮助。

答案 1 :(得分:0)

如果您确实要将ISR附加到按钮信号的RISING边缘,则应忽略多个触发器。至少2毫秒,但为什么不忽略所有不切实际的东西(例如100毫秒)

当你切换两个状态时,我会提出一个布尔变量istate

volatile bool istate; // the state maintained in the ISR changeMode

void changeMode() {
  static unsigned long lastime;
  if (millis() - lastime > 100) {
     lastime = millis();
     istate = ! istate;
  } 
}

如果需要,可以从主代码中的易失性ISR变量构建所有其他冗余内容(自动,手动)。 在我的解释中,名称buttonState是错误的。并且变量不必要。

您知道数据类型枚举吗?

enum {MANUAL, AUTO} mode;
 if (istate) mode = AUTO;
 else        mode = MANUAL;

可能对你的目的很好。