【问题标题】:How does this ISR routine work?这个 ISR 例程如何工作?
【发布时间】:2016-10-05 16:29:59
【问题描述】:

我目前正在尝试为步进电机编写步进信号,最近发现 atmel 写了这个application note, 并提供了一些用于此目的的代码。我必须提供给我的电机的信号是脉冲调制信号,其中信号的频率决定了速度,而不是它们提供的 4 针信号。代码可在github(链接)上找到。

但我目前正在质疑控制电机所有阶段(停止、加速、运行、减速)的 ISR 例程。 更具体地说,它如何跟踪负责更改状态的 step_count。

#pragma vector=TIMER1_COMPA_vect
__interrupt void speed_cntr_TIMER1_COMPA_interrupt( void )
{
  // Holds next delay period.
  unsigned int new_step_delay;
  // Remember the last step delay used when accelrating.
  static int last_accel_delay;
  // Counting steps when moving.
  static unsigned int step_count = 0;
  // Keep track of remainder from new_step-delay calculation to incrase accurancy
  static unsigned int rest = 0;

  OCR1A = srd.step_delay;

  switch(srd.run_state) {
    case STOP:
      step_count = 0;
      rest = 0;
      // Stop Timer/Counter 1.
      TCCR1B &= ~((1<<CS12)|(1<<CS11)|(1<<CS10));
      status.running = FALSE;
      break;

    case ACCEL:
      sm_driver_StepCounter(srd.dir);
      step_count++;
      srd.accel_count++;
      new_step_delay = srd.step_delay - (((2 * (long)srd.step_delay) + rest)/(4 * srd.accel_count + 1));
      rest = ((2 * (long)srd.step_delay)+rest)%(4 * srd.accel_count + 1);
      // Chech if we should start decelration.
      if(step_count >= srd.decel_start) {
        srd.accel_count = srd.decel_val;
        srd.run_state = DECEL;
      }
      // Chech if we hitted max speed.
      else if(new_step_delay <= srd.min_delay) {
        last_accel_delay = new_step_delay;
        new_step_delay = srd.min_delay;
        rest = 0;
        srd.run_state = RUN;
      }
      break;

    case RUN:
      sm_driver_StepCounter(srd.dir);
      step_count++;
      new_step_delay = srd.min_delay;
      // Chech if we should start decelration.
      if(step_count >= srd.decel_start) {
        srd.accel_count = srd.decel_val;
        // Start decelration with same delay as accel ended with.
        new_step_delay = last_accel_delay;
        srd.run_state = DECEL;
      }
      break;

    case DECEL:
      sm_driver_StepCounter(srd.dir);
      step_count++;
      srd.accel_count++;
      new_step_delay = srd.step_delay - (((2 * (long)srd.step_delay) + rest)/(4 * srd.accel_count + 1));
      rest = ((2 * (long)srd.step_delay)+rest)%(4 * srd.accel_count + 1);
      // Check if we at last step
      if(srd.accel_count >= 0){
        srd.run_state = STOP;
      }
      break;
  }
  srd.step_delay = new_step_delay;
}

在我看来,step_count 在 ISR 开始时是否设置为零,并在 ACCEL、RUN 或 DECEL 状态下递增。

快速调试确实表明变量增加到我希望的值,但我真的不知道如何。

我知道遗漏了一些非常简单的东西。

【问题讨论】:

    标签: c++ debugging arduino-uno atmega


    【解决方案1】:

    这三个变量是静态的。这意味着它们只会被初始化一次:

    // Remember the last step delay used when accelrating.
    static int last_accel_delay;
    // Counting steps when moving.
    static unsigned int step_count = 0;
    // Keep track of remainder from new_step-delay calculation to incrase accurancy
    static unsigned int rest = 0;
    

    如果您遵循代码,您会发现它们用于保持状态从一个中断到下一个。

    【讨论】:

      【解决方案2】:

      您需要了解static 应用于函数局部变量时的工作原理。

      那个static unsigned int step_count = 0;表示第一次进入函数step_count设置为0,不是每次进入函数都设置。

      static 表示它不是堆栈变量,它与全局变量在同一内存空间中,只是它只能在声明它的函数内部访问。

      【讨论】:

      • 是的.. 无论如何,我必须更仔细地阅读它:)
      猜你喜欢
      • 2014-07-20
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-11-25
      • 2010-12-03
      • 1970-01-01
      • 1970-01-01
      • 2012-08-27
      相关资源
      最近更新 更多