如何强制中断重启主循环而不是恢复? (时间问题!)

时间:2015-04-29 03:57:57

标签: loops arduino interrupt isr

在过去的两天里,我编写了一个程序,基本上可以生成相当准确的用户可调脉冲信号(频率和占空比都可调)。它基本上使用micros()函数来跟踪时间,以便拉低4个数字输出通道的低电平或高电平。

这4个通道总是需要90度的相位差(比如4cyl引擎)。为了使用户更改设置,实现了ISR,该ISR向主循环返回标志以重新初始化程序。该标志定义为布尔值“set4”。当它为假时,主循环中的'while'语句将运行输出。当它为真时,'if'语句将执行必要的重新计算并重置标志,以便'while'语句将恢复。

该程序与初始值完美配合。阶段是完美的。然而,当ISR被调用并返回到主循环时,根据我的理解,它从“最初”中断的“while”语句中恢复程序,直到它完成并重新检查标志'set4'以查看它是现在是真的,它应该停止。 然后,即使之后的'if'语句重置并重新计算所有必要的变量,这4个输出通道之间的相位也会丢失。手动测试我看,根据调用ISR的时间,它将给出不同的结果,通常将所有4个输出通道同步在一起! 即使我可能不会更改任何值,也会发生这种情况(因此,当您第一次启动arduino时,'if'例程会将变量重置为完全相同的变量!)。但是,如果我注释掉这个例程并且只是离开重置标志'set4'的行,程序将继续正常,就像从未发生过任何事情一样!

我很确定这是因为micros()计时器导致的,因为循环将从ISR被调用的地方恢复。我试图通过使用cli()和sei()检查和禁用中断来做到这一点,但是我无法使它工作,因为当cli()的参数为真时它会冻结。我能想到的唯一解决方案(我已经尝试了一切,花了一整天时间搜索和尝试的东西)是强制ISR从循环开始时恢复,以便程序可以正确初始化。想到的另一个解决方案是,可能会以某种方式重置micros()计时器。但是这会让ISR陷入困境我相信。

为了帮助您想象这里发生的事情是我的代码片段(请不要介意微变量中的'Millis'名称以及任何缺少的大括号,因为它不是纯粹的复制粘贴:p):< / p>

    void loop()
    {
        while(!set4)
        {
        currentMillis = micros();
        currentMillis2 = micros();
        currentMillis3 = micros();
        currentMillis4 = micros();

          if(currentMillis - previousMillis >= interval) {
            // save the last time you blinked the LED 
            previousMillis = currentMillis;   

            // if the LED is off turn it on and vice-versa:
            if (ledState == LOW)
            {
              interval = ONTIME;
              ledState = HIGH;
            }
            else
            {
             interval = OFFTIME; 
             ledState = LOW;
            }

            // set the LED with the ledState of the variable:
            digitalWrite(ledPin, ledState);
            }
    .
    .
    //similar code for the other 3 output channels
    .
    .
    }
    if (set4){
    //recalculation routine - exactly the same as when declaring the variables initially  
      currentMillis = 0;
      currentMillis2 = 0;
      currentMillis3 = 0;
      currentMillis4 = 0;

      //Output states of the output channels, forced low seperately when the ISR is called (without messing with the 'ledState' variables)
      ledState = LOW;
      ledState2 = LOW;
      ledState3 = LOW;
      ledState4 = LOW;

      previousMillis = 0;
      previousMillis2 = 0;
      previousMillis3 = 0;
      previousMillis4 = 0;

     //ONTIME is the HIGH time interval of the pulse wave (i.e. dwell time), OFFTIME is the LOW time interval
     //Note the calculated phase/timing offset at each channel

      interval = ONTIME+OFFTIME;
      interval2 = interval+interval/4;
      interval3 = interval+interval/2;
      interval4 = interval+interval*3/4;

      set4=false;

    }
}

知道出了什么问题吗? 亲切的问候, 肯

1 个答案:

答案 0 :(得分:0)

问题在于:

  previousMillis = 0;
  previousMillis2 = 0;
  previousMillis3 = 0;
  previousMillis4 = 0;

所有if语句在下一个循环中都为真。

尝试:

  previousMillis = micros();
  previousMillis2 = micros();
  previousMillis3 = micros();
  previousMillis4 = micros();