Проблема с прерыванием по совпадению

titanium17
Offline
Зарегистрирован: 21.10.2019

Доброго времени суток. 

Прошу не судить строго - я только недавно начал пробовать работать с ардуино. Возник следующий вопрос - в моем коде 

#include <avr/io.h>
#include <avr/interrupt.h>

volatile int nOverflows = 0;//Keeps track of the number of overflows

void initBlinkTimer()
{
  DDRB |= (1<<PB1);//Set PB1 as output
  asm("cli");
  TCCR0A = 0;
  TCCR0B = 0; 
  TCCR0B |= (1<<CS02) | (1<<CS00);//Set the prescaler to 1024
  TCCR0A |= (1<<WGM01); //Timer0 with CTC Mode
  OCR0B = 250;//Compare TCNT0 with 250
  TIMSK |= (1<<OCIE0B);  //Interrupt at OCR0B compare match aka: execute interrupt when TCNT0 equals 16
  asm("sei");//Enable global interrupts, so that the interrupt routine can be executed upon the OCR0B compare match
}
ISR(TIMER0_COMPB_vect)
{
nOverflows ++;
}
int main()
{
    initBlinkTimer();
    while(1){
      
      if (nOverflows == 2){
      PORTB ^= (1<<PB1);
      nOverflows =0;
      }
   
      }
}

прерывание вызывается только 1 раз и все. Что не так? Если поставить значение переменной  nOverflows == 1 то светодиод засветится, если более 1 (тоесть 2 и более) ничего не работает. Хотя по логике должно.

titanium17
Offline
Зарегистрирован: 21.10.2019

Как ни странно но добавление в обработчик прерывания строчки с обнулением счетчика решило проблему. тоесть 

ISR(TIMER0_COMPB_vect)
{
nOverflows ++;
TCNT0 = 0;
}

Но тогда почему он сам не сбрасывается в 0 при достижении максимума? это не понятно...

DetSimen
DetSimen аватар
Offline
Зарегистрирован: 25.01.2017

и чо, и миллис так намайна работает?

wdrakula
wdrakula аватар
Offline
Зарегистрирован: 15.03.2016

Дед! Я про тебя картинко утром на анекдотах увидал! Держи!

DetSimen
DetSimen аватар
Offline
Зарегистрирован: 25.01.2017

от спасибо.  В рамочку повешаю. 

titanium17
Offline
Зарегистрирован: 21.10.2019

На счет милис не понял. 

Это пока просто проверка идеи, а так в будущем это будет генератор звуковой частоты с плавным изменением значения выходного сигнала (частоты) с помощью оптического энкодера. Для моргалки и милис подойдет)) 

 

DetSimen
DetSimen аватар
Offline
Зарегистрирован: 25.01.2017

ты счетчик в прерывании сбрасываешь в 0, т.е до 0хFF он не доходит, и прерывание по переполнению, на котором зиждеца millis() не срабатывает.  По крайней мере - не должно, это ж нулевой таймер?

titanium17
Offline
Зарегистрирован: 21.10.2019

Кажись начинаю понимать. Милис конечно мне и даром не нужен, а ардуинка получается что ждет его? А его все нет и нет)))  Да, таймер Т0 пользую. Других то в тини85 и нету (кроме Т1) но он тоже 8ми битный. потому и приходится так извращаться.

DetSimen
DetSimen аватар
Offline
Зарегистрирован: 25.01.2017

вот рабочий код прерывания по совпадению с регистром А

Настройка

	ATOMIC_BLOCK(ATOMIC_RESTORESTATE) {

		TCCR0A = TCCR0A & 0b11111100;  // Таймер в режиме Normal
		OCR0A = 245;		// загрузим регистр совпадения
		TIMSK0 |= 0x3;		// установить OCIE0A и TOIE0, разрешим совпадение А и переполнение
		TIFR0 |= 0x2;		// очистим флаг OCF0A если до этого он был установлен, ждём следущего совпадения
	}

 

процедура прерывания 

ISR(TIMER0_COMPA_vect){
TCNT0 = 0xFF; // чтоб на следующем шаге сработало переполнение и посчитался millis
.
.
.
}