Загадка про таймеры

Vlad_J
Offline
Зарегистрирован: 28.04.2013
Доброго всем!
Решал простую задачу - мигать светодиодом. Временем свечения управляет первый таймер, временем потухлости - второй. 
Так вот, при старте пару раз (два раза, если быть точнее) мигает правильно - меньше секунды смена состояния, а потом время свечения продлевается до четырёх секунд примерно. Как будто первый таймер отринул настройки и стал игнорировать OCR1A = 3000; 
Что такое происходит через два такта мигания - у меня фантазия всё. Может, просветит кто?
Вот код:
uint8_t pin = 13;
volatile uint16_t state = 50, count = 1;
 
void setup()
{
  //Timer2. Constant period
    cli();
    TCCR2A = 0;
    TCCR2B = 0;
    TCNT2 = 0;
    TCCR2A |= (1 << WGM21);     
    TCCR2B |= (1 << CS20);
    TCCR2B |= (1 << CS21);
    TCCR2B |= (1 << CS22);    
    TIMSK2 |= (1 << OCIE2A);
    OCR2A = 220;
    
  //Timer1. For shift
    TCCR1A = 0;
    TCCR1B = 0;
    TCNT1 = 0;
    TCCR1B |= (1 << WGM12);
    TIMSK1 |= (1 << OCIE1A);
    OCR1A = 3000; //for change
    sei();
    
  pinMode(pin, OUTPUT);
}
 
void loop(){
 
}

ISR(TIMER2_COMPA_vect){
  if(count < state){
    count++;
  }else{
    //cli();
    digitalWrite(pin, HIGH);  
    TCCR2B &= (0 << CS20)&(0 << CS21)&(0 << CS22);      
    TCCR1B |= (1 << CS10)|(1 << CS12);
    //OCR1A = 3000;   
    count = 1;
    //sei();
  }   
}

ISR(TIMER1_COMPA_vect){
  //cli();
  digitalWrite(pin, LOW);
  TCCR1B &= (0 << CS10)&(0 << CS11)&(0 << CS12);
  TCCR2B |= (1 << CS20)|(1 << CS21)|(1 << CS22);  
  //sei();
}

 

 

Komandir
Komandir аватар
Offline
Зарегистрирован: 18.08.2018

ОТГАДКА - А где сброс самих счетчиков ??? После 3000 он идёт до 65536 и потом снова до 3000

Vlad_J
Offline
Зарегистрирован: 28.04.2013

Вот эта строчка:

TCCR1B |= (1 << WGM12);

Разве не подразумевается, что счётчик сбрасывается в ноль, достигая этого числа:

OCR1A = 3000;

?

 

Upper
Offline
Зарегистрирован: 23.06.2020

TCCR1B &= (0 << CS10)&(0 << CS11)&(0 << CS12);
равносильно
TCCR1B = 0;

Green
Offline
Зарегистрирован: 01.10.2015

Да, но не наглядно. Обычно:
TCCR1B = 0<<CS10 | 0<<CS11 |  0<<CS12;
а не фиг знамо что.

Vlad_J
Offline
Зарегистрирован: 28.04.2013

В TCCR1B есть и другие полезные биты, которые не надо трогать на этом действии

Green
Offline
Зарегистрирован: 01.10.2015

Да что вы говорите! Так сделайте по другому. Сбросьте одни, добавьте другие. 

ЕвгенийП
ЕвгенийП аватар
Offline
Зарегистрирован: 25.05.2015

Vlad_J пишет:

 TCCR2B &= (0 << CS20)&(0 << CS21)&(0 << CS22);      

В TCCR1B есть и другие полезные биты, которые не надо трогать на этом действии

Так нахрена же Вы их все до единого в ноль сбросили?

Вам же уже сказали:

Upper пишет:

TCCR1B &= (0 << CS10)&(0 << CS11)&(0 << CS12);
равносильно
TCCR1B = 0;

Вы этого не прочитали?

Вы тупо прописываете весь регистр нулями, а потом чего-то хоите.

Vlad_J
Offline
Зарегистрирован: 28.04.2013

ЕвгенийП пишет:

Vlad_J пишет:

 TCCR2B &= (0 << CS20)&(0 << CS21)&(0 << CS22);      

В TCCR1B есть и другие полезные биты, которые не надо трогать на этом действии

Так нахрена же Вы их все до единого в ноль сбросили?

Вам же уже сказали:

Upper пишет:

TCCR1B &= (0 << CS10)&(0 << CS11)&(0 << CS12);
равносильно
TCCR1B = 0;

Вы этого не прочитали?

Вы тупо прописываете весь регистр нулями, а потом чего-то хоите.

Не равносильно. Обращу Ваше внимание, что регистр TCCR1B, как минимум, восемь бит. А я только три обнуляю, остальные не трогаю.

Vlad_J
Offline
Зарегистрирован: 28.04.2013

Green пишет:

Да что вы говорите! Так сделайте по другому. Сбросьте одни, добавьте другие. 

Я так и делаю. Разве нет?

xDriver
xDriver аватар
Offline
Зарегистрирован: 14.08.2015

Vlad_J пишет:

Не равносильно. Обращу Ваше внимание, что регистр TCCR1B, как минимум, восемь бит. А я только три обнуляю, остальные не трогаю.

да, ну выведи в ком порт чему равно 

uint8_t reg = 0xFF;
reg &= (0 << CS10)&(0 << CS11)&(0 << CS12);

 

b707
Offline
Зарегистрирован: 26.05.2017

Vlad_J пишет:

Не равносильно. Обращу Ваше внимание, что регистр TCCR1B, как минимум, восемь бит. А я только три обнуляю, остальные не трогаю.

че седня такое.... вспышка на Солнце? одни дебилы...

Ваша строка

TCCR1B &= (0 << CS10)&(0 << CS11)&(0 << CS12);

равнозначная вот этой

TCCR1B &= (0b00000000);

еще будут возражения на тему "в регистре 8 бит" ?

xDriver
xDriver аватар
Offline
Зарегистрирован: 14.08.2015

b707 пишет:

че седня такое.... вспышка на Солнце? одни дебилы...

причем с датой регистрации - не вчера.

b707
Offline
Зарегистрирован: 26.05.2017

а то что вы хотите, делается так:

TCCR1B &= ~((1 << CS10) | (1 << CS11) | (1 << CS12));

видите разницу?

Vlad_J
Offline
Зарегистрирован: 28.04.2013

xDriver пишет:

Vlad_J пишет:

Не равносильно. Обращу Ваше внимание, что регистр TCCR1B, как минимум, восемь бит. А я только три обнуляю, остальные не трогаю.

да, ну выведи в ком порт чему равно 

uint8_t reg = 0xFF;
reg &= (0 << CS10)&(0 << CS11)&(0 << CS12);

 

Понял, проникся! Всем спасибо! Обещаю исправиться

Vlad_J
Offline
Зарегистрирован: 28.04.2013

b707 пишет:

а то что вы хотите, делается так:

TCCR1B &= ~((1 << CS10) | (1 << CS11) | (1 << CS12));

видите разницу?

Да, спасибо. Что-то разогнался быстрее головы.

Green
Offline
Зарегистрирован: 01.10.2015

Ну вот когда понимает, тогда и приятно с человеком разговаривать. А не как с дебилом каким то!
Если понимаешь свои ошибки, анализируешь, то всё у тебя получится.