Проблема запуска прерывания по таймеру из аппаратного прерывания.
- Войдите на сайт для отправки комментариев
Пнд, 07/09/2020 - 15:35
Добрый день.
Задача выполнить действие с заданным лагом от момента срабатывания аппаратного прерывания.
Код:
#include <avr/io.h> #include <avr/interrupt.h> //2,056мс unsigned int ArrS[] = {1, 4110, 5888, 7332, 8666, 9999, 11221, 12555, 13999, 15888, 19999}; volatile uint8_t nomer; void setup(){ pinMode(9, OUTPUT); pinMode(2, INPUT); attachInterrupt(0, znak_plvln, CHANGE); cli(); TCCR1A = 0; TCCR1B = 0; OCR1A = 9999; TCCR1B |= (1 << WGM12); TCCR1B |= (1 << CS11); TIMSK1 |= (1 << OCIE1A); sei(); } void loop(){} ISR(TIMER1_COMPA_vect){ digitalWrite(9, !digitalRead(9)); cli(); TIMSK1 &= ~ (1 << OCIE1A); OCR1A = ArrS[nomer]; //TIMSK1 |= (1 << OCIE1A); sei(); if (nomer == 10) nomer = 0; else nomer++; } void znak_plvln(){ TIMSK1 |= (1 << OCIE1A); }
в логическом анализаторе выдает
Прерывание по таймеру в основном срабатывает сразу после включения.
Пробовал для поиска ошибки отказаться от аппаратного прерывания:
#include <avr/io.h> #include <avr/interrupt.h> //2,056мс unsigned int ArrS[] = {1, 4110, 5888, 7332, 8666, 9999, 11221, 12555, 13999, 15888, 19999}; volatile uint8_t nomer; void setup(){ pinMode(9, OUTPUT); pinMode(2, INPUT); //attachInterrupt(0, znak_plvln, CHANGE); cli(); TCCR1A = 0; TCCR1B = 0; OCR1A = 9999; TCCR1B |= (1 << WGM12); TCCR1B |= (1 << CS11); TIMSK1 |= (1 << OCIE1A); sei(); } void loop(){} ISR(TIMER1_COMPA_vect){ digitalWrite(9, !digitalRead(9)); cli(); TIMSK1 &= ~ (1 << OCIE1A); OCR1A = ArrS[nomer]; TIMSK1 |= (1 << OCIE1A); sei(); if (nomer == 10) nomer = 0; else nomer++; } /* void znak_plvln(){ TIMSK1 |= (1 << OCIE1A); } */
В этом случае задержка по таймеру срабатывает корректно:
Можно ли прерывание по таймеру включать из аппаратного прерывания? и как это сделать
Спасибо
del
Аттач в конец сетапа. Сбрасывайте INT0F перед аттачем. cli()/sei() в ISR лишние.
sei не лишнее.
А это нормально, что функция прерывания прописана внутри loop ?
loop у него пустой. Внимательно паматри.
loop у него пустой. Внимательно паматри.
Угу, увидел.
А любом случае, вне зависимости от того включено прерывание по таймеру или нет(сравнение/переполнение и тд), счётчик тикает один фиг.
Есть смысл его обнулять перед запуском:
TCNT1=0;
Задача выполнить действие с заданным лагом от момента срабатывания аппаратного прерывания.
Вот здесь это делается очень красиво.
Заработало в таком виде:
Kakmyc, спасибо за указание на TCNT1=0;. Стало включаться в нужный момент.
ЕвгенийП, прошу прощения, решая одну проблему, не описал задачу в целом. Не только включить из апп прерывания, но и выключить через период. С режимом Force Output Compare не нашел возможности это сделать. Разве что включение 9 пина отслеживать, но это неаккуратно.