Как работает эта процедура ISR?

В данный момент я пытаюсь написать сигнал шага для шагового двигателя и недавно обнаружил, что atmel написал это примечания к приложению и предоставили код для этой цели. Сигнал, который я должен предоставить своему двигателю, представляет собой импульсно-модулированный сигнал, где частота сигнала определяет скорость, а не 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.

Быстрая отладка показывает, что переменная увеличивается до желаемого значения, но я действительно не могу понять, как это сделать.

Я знаю, что не хватает чего-то очень простого.


person Lamda    schedule 05.10.2016    source источник


Ответы (2)


Эти три переменные статичны. Это означает, что они будут инициализированы только один раз:

// 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;

Если вы будете следовать коду, то обнаружите, что они используются для сохранения состояния от одного прерывания к другому.

person Dale Wilson    schedule 05.10.2016

Вам нужно понять, как static работает, когда он применяется к локальной переменной функции.

Это static unsigned int step_count = 0; означает, что впервые в функции step_count установлено значение 0. Он не устанавливается каждый раз в функции.

static означает, что это не переменная стека, она находится в том же пространстве памяти, что и глобальная переменная, за исключением того, что к ней можно получить доступ только внутри функции, которая ее объявляет.

person Zan Lynx    schedule 05.10.2016
comment
Ага .. Мне все равно пришлось прочитать немного внимательнее, спасибо :) - person Lamda; 05.10.2016