Программирование таймера 0
- Войдите на сайт для отправки комментариев
Чт, 02/04/2015 - 14:31
Не могу монять почему прерывание не срабатывает по совпадению, а работает как по переполнению.
void setup() { pinMode(13, OUTPUT); OCR0A =125; //регистр совпадения //Timer in CTC mode (TCCR0A) TCCR0B =(1<<CS00)|(1<<CS01); // Тактировать с делителем 64 TIMSK0|=(1<<OCIE0A); // Разрешить прерывание по совпадению // turn on CTC mode:CTC (сброс при совпадении)Clear Timer on Compare (CTC) установкой бит WGMn1 в TCCRn. //При этом счётчик после совпадения с регистром сравнения будет сбрасываться автоматически. TCCR0A |= (1 << WGM01); sei(); //бит общего разрешения прерываний } void loop() { } //ОБРАБОТЧИК ПРЕРЫВАНИЙ ПО ТАЙМЕРУ ISR(TIMER0_COMPA_vect) { //TCNT0 = 0;// счетный регистр if (iiii==1000){ digitalWrite(13,!digitalRead (13)); iiii=0;} iiii++; }
Чувствую что где-то туплю, а где непонятно, ткните носом если кто знает. Нулевой таймер под ардуиной решил использовать так как не буду использовать функции delay, millis, и pwm
Всё вроде правильно, но не объявлена переменная iiii. Atmel Studio такой код даже не компилирует.
volatile int iiii;
Объявил переменную, прогнал код через отладчик в студии - всё работает. Происходит прерывание по совпадению с OCR0A.
Olm, Вы тупите в 11 строке :) Записываете бит, видимо подразумевая, что регистр TCCR0A=0. Откуда такая уверенность? Делайте как в 7 строке. Всё что не указано - сбросится в ноль.
Записываете бит, видимо подразумевая, что регистр TCCR0A=0. Откуда такая уверенность?
В даташите написано Initial Value 0 0 0 0 0 0 0 0, т.е. в теории TCCR0A=0. Но на практике черт его знает.....
Я ненужные мне биты никогда не сбрасываю специально в ноль, всё и так работает. Как по даташиту. Мож от конкретного экземпляра МК зависит.
Jeka_M, Лучше сбрасывать :)) Дуняша свой порядок наводит, тем более timer0 её любимчик :)
Спасибо за такие нюансы, буду знать.
Ничего что-то не помогает. Прерывание наступает вовремя, но регистр TCNT0 не обнуляется автоматически по совпадению и продолжает тикать до переполнения. Только если его вручную обнулять в обработчике прерывания. Но в даташите сказано что в режиме CTC должен счетчик сбрасываться автоматически при совпадении с регистром сравнения
Я всё это дело из среды ардуино компилирую и прошиваю, может она что-то меняет?
В общем заработало. Регистры TCCR0A и TCCR0B надо сначала грузить, чтоб работали прерывания по совпадению.
И еще пожалуй лучше обнулить перед разрешением прерываний счетный регистр TCNT0.
Olm, по идее стартовой "кнопкой" таймера является запись клоков. Желательно их первой же строкой обнулить, потом сперва сконфигурировать все другие регистры, и в конце дать нужные клоки (7 строка) , тогда всё должно стартовать правильно.
Еще перед запуском таймера (CS01, CS00) можно обнулять "буфер" предделителя (бит PSRSYNC в регистре GTCCR). Т.к. даже когда таймер остановлен - предделитель постоянно тикает.
Но надо быть осторожным, если используются два таймера (Timer0 и Timer1), т.к. "буфер" предделителя у них общий. Будет сбрасываться у обоих.
Здравствуйте написал код использующий таймер 0 для подсчета количество переполнений для борьбы с дребезгом и прерывание по изменению состояния вывода PCINT в данном случае с кнопкой на выводе РВ0 подтянутой внутренним резистором к питанию.
[Плата pro mini на mega168, памяти не особо много остается и такой вариант кода опроса на регистровом уровне считаю оптимальным в плане расхода памяти.]
Тестовый светодиод должен инвертироваться по каждому нажатию
Дребезг часто проскакивает, в чем может быть причина?
ПС: подскажите если не трудно как перейти к setup() и loop() Возникает конфликт с delayMicroseconds
Дребезг часто проскакивает, в чем может быть причина?
Плохой алгоритм. Дребезг возникает как при нажатии кнопки, так и при отпускании её. У вас прерывание срабатывает и на нажатие и на отпускание, и счёт времени запускается и так и так, в результате получается что и алгоритм срабатывает и на нажатие и на отпускание, и ваше условие if( !(PINB & (1 << PINB0))) легко срабатывает от дребезга, а не от нажатия кнопки. Короче аглоритм негодный.
ПС: подскажите если не трудно как перейти к setup() и loop() Возникает конфликт с delayMicroseconds
Разумеется, таймер0 - системный таймер ардуины, который по умолчанию занят. Так что либо не используёте таймер0, либо не используйте функцию setup(), которая прогружает все настройки по умолчанию.
dimax, спасибо. Понял свою ошибку и решил несколько упростить код - убрал прерывание по таймеру 0. Подавление дребезга произвожу аппаратно - параллельно каждой кнопке поставил керамический конденсатор на 100 нФ. Дребезг пропал.