Как работает эта процедура 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.

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

Я знаю, что упустил что-то очень простое.

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;

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

3

Другие решения

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

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

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

2

По вопросам рекламы ammmcru@yandex.ru
Adblock
detector