Загадка про таймеры
- Войдите на сайт для отправки комментариев
Ср, 07/09/2022 - 13:03
Доброго всем!
Решал простую задачу - мигать светодиодом. Временем свечения управляет первый таймер, временем потухлости - второй.
Так вот, при старте пару раз (два раза, если быть точнее) мигает правильно - меньше секунды смена состояния, а потом время свечения продлевается до четырёх секунд примерно. Как будто первый таймер отринул настройки и стал игнорировать 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();
}
ОТГАДКА - А где сброс самих счетчиков ??? После 3000 он идёт до 65536 и потом снова до 3000
Вот эта строчка:
Разве не подразумевается, что счётчик сбрасывается в ноль, достигая этого числа:
?
TCCR1B &= (0 << CS10)&(0 << CS11)&(0 << CS12);
равносильно
TCCR1B = 0;
Да, но не наглядно. Обычно:
TCCR1B = 0<<CS10 | 0<<CS11 | 0<<CS12;
а не фиг знамо что.
В TCCR1B есть и другие полезные биты, которые не надо трогать на этом действии
Да что вы говорите! Так сделайте по другому. Сбросьте одни, добавьте другие.
В TCCR1B есть и другие полезные биты, которые не надо трогать на этом действии
Так нахрена же Вы их все до единого в ноль сбросили?
Вам же уже сказали:
TCCR1B &= (0 << CS10)&(0 << CS11)&(0 << CS12);
равносильно
TCCR1B = 0;
Вы этого не прочитали?
Вы тупо прописываете весь регистр нулями, а потом чего-то хоите.
В TCCR1B есть и другие полезные биты, которые не надо трогать на этом действии
Так нахрена же Вы их все до единого в ноль сбросили?
Вам же уже сказали:
TCCR1B &= (0 << CS10)&(0 << CS11)&(0 << CS12);
равносильно
TCCR1B = 0;
Вы этого не прочитали?
Вы тупо прописываете весь регистр нулями, а потом чего-то хоите.
Не равносильно. Обращу Ваше внимание, что регистр TCCR1B, как минимум, восемь бит. А я только три обнуляю, остальные не трогаю.
Да что вы говорите! Так сделайте по другому. Сбросьте одни, добавьте другие.
Я так и делаю. Разве нет?
Не равносильно. Обращу Ваше внимание, что регистр TCCR1B, как минимум, восемь бит. А я только три обнуляю, остальные не трогаю.
да, ну выведи в ком порт чему равно
Не равносильно. Обращу Ваше внимание, что регистр TCCR1B, как минимум, восемь бит. А я только три обнуляю, остальные не трогаю.
че седня такое.... вспышка на Солнце? одни дебилы...
Ваша строка
равнозначная вот этой
еще будут возражения на тему "в регистре 8 бит" ?
че седня такое.... вспышка на Солнце? одни дебилы...
причем с датой регистрации - не вчера.
а то что вы хотите, делается так:
видите разницу?
Не равносильно. Обращу Ваше внимание, что регистр TCCR1B, как минимум, восемь бит. А я только три обнуляю, остальные не трогаю.
да, ну выведи в ком порт чему равно
Понял, проникся! Всем спасибо! Обещаю исправиться
а то что вы хотите, делается так:
видите разницу?
Да, спасибо. Что-то разогнался быстрее головы.
Ну вот когда понимает, тогда и приятно с человеком разговаривать. А не как с дебилом каким то!
Если понимаешь свои ошибки, анализируешь, то всё у тебя получится.