Навчальний курс avr
Наступний режим роботи таймера Т0 - це режим CTC (Clear Timer on Compare) або "скидання при збігу". Таймер в цьому режимі працює наступним чином.
При ініціалізації таймера ми очищаємо рахунковий регістр TCNT0, а в регістр порівняння OCR0 завантажуємо число. Потім встановлюємо режим СТС і необхідний коефіцієнт предделителя.
Таймер починає роботу. По кожному імпульсу тактового сигналу рахунковий регістр збільшує своє значення на одиницю. Коли значення рахункового регістра співпаде з регістром порівняння, встановиться прапор OCF0, рахунковий регістр скинеться і рахунок продовжиться з нуля. Якщо переривання за випадковим збігом дозволені, то після установки прапора OCF0 запуститься підпрограма обробки. З регістром порівняння при цьому нічого не станеться, він своє значення не змінить. Діаграма нижче пояснює роботу таймера Т0 в режимі СТС.
Практичний приклад. Потрібно генерувати меандр з частотою 70 кГц на виведення PB1. Мікроконтролер ATmega16, тактова частота 16 МГц.
Найпростіший спосіб генерувати меандр, полягає в інвертуванні стану виводу мікроконтролера в перериванні таймера.
Меандр змінює свій стан два рази за період. Спочатку перемикається в 1, потім скидається в 0. Тому, щоб генерувати сигнал з частотою 70 кГц, переривання потрібно викликати в два рази частіше, тобто з частотою 140 кГц.
Обчислюємо необхідний період переривань.
T = 1 / F = 1/140000 = 7.143 мкс
Яку тактову частоту задати таймером, щоб він міг відміряти інтервал в 7.143 мкс? Якби один такт таймера становив
0.1 мкс, це б підійшло. 71 такт дасть 7.1 мкс.
Підберемо коефіцієнт предделителя. У нас п'ять варіантів 1, 8, 64, 256, 1024. При 1 ми отримаємо тактовий сигнал з періодом 0.0625 мкс.
Tt0 = 1 / (Fcpu / k) = 1 / (16000000/1) = 0.0625 мкс
При такому періоді для формування інтервалу в 7.143 мкс нам знадобляться 7.143 / 0.0625 = 114 тактів. Значить такий коефіцієнт підійде. І точність хороша і розрядності рахункового регістра вистачає.
114 - це кількість тактів, які повинен відрахувати таймер Т0. У регістр порівняння же потрібно завантажити на один такт менше, тобто 113. Рахунок повинен починатися з нульового такту.
Як бачите, для режиму CTC розрахувати значення регістра порівняння ще простіше, ніж для режиму Normal:
-обчислюємо період одного такту таймера Tt0 = k / Fcpu,
- обчислюємо необхідну кількість тактів для заданого інтервалу n = t / Tto - 1
Для оцінки точності одержуваного сигналу, можна виконати зворотну процедуру.
F = 1 / ((OCR0 + 1) * Tt0) = 1 / ((OCR0 + 1) * (1 / (Fcpu / k)) = Fcpu / ((OCR0 + 1) * k)
F = 16000000/114 = 140351 Гц
Весь код для нашої задачі буде виглядати приблизно так. (Код наведено для IAR`a. Для інших компіляторів потрібно змінити заголовки та оброблювач переривання.)
Управління висновком OC0 здійснюється в режимі СТС точно так же, як і в режимі Normal. Висновок OC0 змінює стан при збігу значення рахункового регістра і регістра порівняння. Варіанти управління задаються розрядами COM01 і COM00 регістра TCCR0.
Розглянуту вище програму можна переробити для генерації меандру на виведення OC0. При цьому переривання можна не використовувати.
Завдяки автоматичному скидання рахункового регістра, таймер в режимі СТС точніше відміряє тимчасові інтервали. Єдина заковика - в деяких мікроконтролерах таймери-лічильники Т0 не мають такого режиму.