Еще один отсчет таймера
- Войдите на сайт для отправки комментариев
Чт, 22/06/2017 - 16:04
Использую таймер для генерациии прерывания на частоте 250 ГЦ
void set_timer_T2A(void) { TCCR2B=0; // Т2 стоп TCNT2=0; // счётный регистр OCR2B=0; TIFR2&=0xff; TCCR2A=(1<<WGM21); //Mode2(CTC) OCR2A=249; // 500 Гц TIMSK2=(1<<OCIE2A); //прерывание по совпадению с OCR2A TCCR2B=(1<<CS22)|(1<<CS21); // делитель на 256 } ISR (TIMER2_COMPA_vect) { ; ; }
Как описать настройку таймера T2B, чтобы он вызывал другое прерывание,
ISR (TIMER2_COMPB_vect) { ; ; }
по частоте синхронное с T2A, но исполняемое при значении OCR2B=83 и при этом T2 бы не начинал отсчет заново как в случае с OCR2A=249, а вызывал его прерывание TIMER2_COMPA и только после этого перезапускался ?
Те частота вызовов нового и старого прерываний должна остаться без изменения.
Нахрена такие сложности, при входе в аервое прерывание запустите другой таймер, который через 83 клока даст вам прерывание . И на этом всё !
при этом T2 бы не начинал отсчет заново как в случае с OCR2A=249, а вызывал его прерывание TIMER2_COMPA и только после этого перезапускался ?
Частота тут неизменна, она жёстко задана регистром OCR2A. Таймер не в состоянии начать отчёт заново не досчитав до OCR2A. Стало быть если вы допишите OCR2B=83; TIMSK2|=1<<OCIE1B; то второе прерывание будет работать с той же частотой, но сдвинуто по времени на OCR2A-OCR2B тактов.
OCR2A и OCR2B не равноценны, частоту задает OCR2A, а не OCR2B?
Можете тыкнуть на пункт в описании от Microchip (владелец компании Atmel) или книгу Евстифеева?
Kunzo, даташит, страница 155 Table 18-8. Mode 2. Графа "Top" говорит о том, что будет конец счёта. Регистры не равноценны. Регистр OCR2A в данном случае работает в 2х качествах -как число, до которого считает счётчик, и как число при сравнении с которым произойдёт прерывание. Регистр OCR2B только в одном качестве.
а если добавить задержку, то первый отсчет вообще печатается ка отрицательный
Kunzo, вы недостаточно ясно описали что не так. Из того, что бросается в глаза -TIFR лучше обнулять после настройки TIMSK, ибо после его конфигурации сразу может сработать прерывание. Ну и можно на всякий случай перед всей этой конструкцией запретить прерывания. Т.е. запрет, потом настройка таймера, потом разрешение прерываний, и в конце всей очереди T1=micros.
Изменил все указанное, только местоположение T1=micros(); менять не стал тк он привязан к Serial.print(), который распечатывает его значение. Если выполнить Serial.print() после инициализации таймера, то возможно вывод в COM сдвинет (предположение) по времени входы в прерывания компараторов A и B ?
А если добавить задержку, то результат еще более изменяется, я писал об этом выше
Kunzo, не понимаю что вам не понятно.. У вас первым срабатывает прерывание COMPB, и в нём вы уже делаете операцию TB-TA , а TA на этот момент =0. Т.к. второе прерывание ещё не сработало. В резульате вы имеете то что запрограммировано -первый отсчёт -это время от глобального старта микрос до прерывания.
dimax, поскольку мне был нужен еще один таймер, я добавил прерывание от T0. Инициализировал однотипно с T2, но T0 испортил работу прежней программы.
В чем конфликт не знаю. МК Atmega328P - вместо T0 придется использовать T1 ?
В программе еще будут задействованы библиотечные функции: аппаратный SPI, аппаратный Serial COM1 на время отладки и аппаратный I2C для LCD.
Kunzo, Timer0 использует ардуиновские системные функции (миллисы, микросы, и прочее)
Тогда нужно использовать оставшийся T1 если библиотечные функции: аппаратный SPI, аппаратный Serial COM1 на время отладки и аппаратный I2C для LCD на него не претендуют ?
Кстати, почему он в datasheet называется 3,4-16 битным и ATmega328PB устроена также как ATmega328P AU ?