Как выполнять в прерывании TIMER_OVF_vect разные задачи?

dimax
dimax аватар
Offline
Зарегистрирован: 25.12.2013

Осваиваю таймеры :) Написал простой скетч, в нём по нажатии на кнопку (d2) загорается светодиод (d13), далее запускаю таймер1, от отсчитывает некоторое время (для примера секунду) , создаёт прерывание, и в функции прерывания гасит светодиод (или выполняет ещё какие-то команды) и таймер отключается, т.к. основная задумка -сработать один раз.  Скетч работает, с ним  вопросов нет. Но хочется большего, -создать некую функцию, которая будет задавать параметры таймеру и команды, которые нужно выполнить в прерывании. К примеру одна задача записать ноль в d13  через 500мс,  другая задача прочитать  аналоговый вход спустя секунду после запуска функции.  Итп. Эти задачи хочется подсовывать функции.   Схематично что-то вроде my_timer (unsigned int delay_ms,  команда_которую_нужно_выполнить_в_прерывании или другая функция )  Пол дня бьюсь -никаких сдвигов...  Сам начальный скетч:

void setup() {
pinMode (2,INPUT_PULLUP); //кнопка
pinMode (13,OUTPUT); //светодиод
TCCR1B=0; TCCR1A=0; 
TIMSK1=(1<<TOIE1); //разрешить прерывание
}
void loop() {
  if bit_is_clear(PIND,2) { // если на выводе 2 низкий уровень (кнопка нажата), то
  PORTB |= 1<<5; // записать лог 1 в порт 13                   
  ICR1=3000;// настройка задержки прерывания (1мс задержки = примерно 8 попугаев (8000/1024) )
  TCCR1B= _BV(WGM13)|_BV(CS12)|_BV(CS10); //запуск таймера, делитель на 1024
  }
}

ISR (TIMER1_OVF_vect) { //запуск перрывания
PORTB ^= (1<<5); //инверсия 13 пина ардуино
TCCR1B = _BV(WGM13); //отключение таймера
}

 

kisoft
kisoft аватар
Offline
Зарегистрирован: 13.11.2012

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

dimax
dimax аватар
Offline
Зарегистрирован: 25.12.2013

kisoft, в библе timerOne  используется какая то штуковина isrCallback, нигде толком про неё не нашёл инфы. Судя по названию она может запустить прерывание, а потом вернуться туда, откуда её запустили, я правильно мыслю? Вот только как бы это применить, если это так..

kisoft
kisoft аватар
Offline
Зарегистрирован: 13.11.2012

Это обработчик, вот пример http://robocraft.ru/blog/arduino/614.html
Сам не юзал. Только оно для периодичных событий, придётся отключать постоянно.
Можно исходники посмотреть.
Обработчик вызывается при возникновении прерывания, значит при выходе из обработчика вернёмся в то место, где возникло прерывание, конечно