У мікроконтролерах avr є такий периферійний модуль як таймер лічильник. Відповідно до своєї назви він вважає час. У таймер лічильника є регістр TCNT з якого можна прочитати скільки часу пройшло з моменту запуску таймера. Значення в цьому регістрі не в хвилинах або секундах, а в 'папуг' - 'тиках' таймера. Чому дорівнює один тик - залежить від тактової частоти, на якій працює мікроконтролер avr, і від налаштувань таймера.
Так само у таймера лічильника є настроюється дільник частоти, який визначає на скільки буде поділена тактова частота мікроконтролера перед тим як буде подана на таймер лічильник. Тривалість тика таймера є зворотною величиною від частоти, отриманої в результаті поділу.
наприклад:
Тактова частота = 11059200 Гц (11.0592 МГц)
Дільник = 1024
Частота таймера лічильника = Тактова частота / Дільник = 11059200/1024 = 10800 Гц
Тривалість періоду (тика) = 1/10800 = 92.593 * 10 ^ -6 секунди = 92.593 мкс
Для настройки дільника використовуються біти CS регістра TCCR.
Наприклад для таймера 1 в atmega8 використовуються регістр TCCR1B і біти CS10, CS11, CS12.
Залежність подільника від стану біт CS для таймера 1 в atmega8
TCCR1B = (1lt; lt; CS12) | (0lt; lt; CS11) | (1lt; lt; CS10); // xtall / тисячі двадцять чотири
У avr таймери можуть бути 8 або 16 розрядними. Розрядність визначає максимальну кількість тиків які може порахувати таймер. Для 8 розрядного це 256 тиків, для 16 це 65536.
У нашому випадку один тик дорівнює 92.593 мкс, відповідно максимальне значення, яке може виміряти 16 бітний таймер, це 65536 * 92.593 * 10 ^ -6 = 6.068 секунди, 8-ми бітний - 0.0237 секунди.
Після того як таймер дорахував до максимального значення, він переповнюється, тобто починає вважати з нуля. Цю ситуацію можна обробляти за допомогою переривань. Для цього треба дозволити переривання по переповнення таймера і виставити біт загального дозволу переривань.
Приклад коду для дозволу переривань таймера 1 avr atmega8:
TIMSK | = (1lt; lt; TOIE1); // дозволити переривання по переповнення таймера лічильника sei (); // виставити біт загального дозволу переривань
Так само треба визначити обробник даного переривання - функцію яка буде викликана при переповненні таймера.
Додамо в цю функцію код змінює стан ніжки PB0, до якої підключений світлодіод.
Приклад коду функції обробника переривання для таймера 1 avr atmega8:
ISR (TIMER1_OVF_vect) Світлодіод буде змінювати свій стан через кожні 6 секунд. Щоб світлодіод міняв свої статки з частотою 10Гц, треба щоб таймер відраховувати не 65536 тиків а менше. Розрахуємо необхідну кількість тиків: Щоб таймер вважав не з нуля а з деякого значення, при ініціалізації і при кожному спрацьовуванні переривання в регістр TCNT1 будемо записувати число (65536 - 1080) = 64456. Лістинг підсумкової програми для таймера 1 avr atmega8: #include lt; avr / io.hgt; #include lt; avr / interrupt.hgt; ISR (TIMER1_OVF_vect) Так само ви можете прочитати інші статті з рубрики «Мікроконтролери avr». Архів з вихідними кодами під avr-gcc (WinAvr) можна завантажити тут. Артем Колесников каже: Артем Двинин каже: Дякую за відгук. Так Ви праві, треба буде доповнити статтю, або може окрему замітку написати. Дякуємо. Толково. Є питання. Таймер стартує при включенні МК. А як можна запускати і зупиняти його вручну (за допомогою кнопки наприклад). Артем Двинин каже: Будь ласка :) Добрий день. як отримати сигнал від ІК приймача (38 КГц) його data підключений в PB0 у. Артем Двинин каже: Доброго вам дня! А який у Вас мікроконтролер? Допоможіть будь ласка. Зараз розбираюся з UART на avr studio4 (mega8) Артем Двинин каже: Може хто-небудь на асемблері викласти настройку таймера і мигалку на світлодіоді? Добридень! Ардуіно не вважає час менше 4 мкс, треба працювати з таймерами на пряму. Але я не знаю як і що. Допоможіть будь ласка! Артем Двинин каже: Назар, день добрий! До речі, а що це за пристрій, який Ви розробляєте? Привіт Артем! Спасибі за відповідь! (1 lt; lt; TOIE0); // Disable Timer 0. TIMSK2 - = Ще питання: як зробити що-б значення таймера при переповненні продовжувало збільшуватися, а не обнуляє і починалося спочатку? Тобто, я хочу зробити таймер 32-х бітовим. Це для того, що-б не робити окремі межі вимірювань, а просто збільшити час заряду конденсатора. П.С. могу скинуть схемку, якщо цікаво. Артем Двинин каже: Доброго времени суток, Назар! А схема звичайно цікава, надішліть, будь ласка! PS до речі, мені здається, в цьому рядку помилка: while ((((ACSR - (1lt; lt; ACO)) == 0)) - (TCNT1 = 14001) Справа може бути в тому, що у вас дільник = 1, тобто таймер працює з частотою 8МГц. З цієї ж частотою виконуються і команди мікроконтролера (1 - 3 такту на команду). Виходить, що якщо код обробника переривань виконується більш ніж за 256 тактів, то частота буде зменшуватися. Спробуйте дізасембліровать прошивку і подивитися який код генерується для обробника переривання. підкажіть а обов'язково значення в регістр OCR1A записувати в 16річном форматі? і обов'язково записувати значення спочатку в старший а потім молодший, тобто ось так: TCCR0 = (1lt; lt; 0) | (1lt; lt; 1); // Налаштовуємо переддільник TIMSK | = (1lt; lt; TOIE0); // // ___________________________________________________ TIMER1 TCCR1B = (1lt; lt; CS12) | (0lt; lt; CS11) | (0lt; lt; CS10); // Налаштовуємо переддільник 256 TIMSK | = (1lt; lt; TOIE1); // TCNT1 = 0; // ___________________________________________________ TIMER2 // TCCR2 = (1lt; lt; CS12) | (0lt; lt; CS11) | (1lt; lt; CS10); // Налаштовуємо переддільник 1024 // TIMSK | = (1lt; lt; TOIE2); // з таемером 2 все як то неработает Артем Двинин каже: Підкажіть будь ласка. У ATtiny2313a в налаштуваннях 16 бітного таймера в регістрі TCCR1A є такі біти: COMnA1: 0. COMnB1: 0, COMnC1: 0. З даташіта вичитав, що при збігу з регістром порівняння (відповідно до записаними значеннями в ці регістри) будуть змінюватися рівень напруги на протилежний, підтягуватися до + 5 або 0. Але от не можу зрозуміти, при активації даної функції можна міняти значення цих ніжок в програмі? Артем Двинин каже: Олександр, здрастуйте. Олександр М. каже: Спробував прошити програму під AtMega 128 із зовнішнім кварцом на 16МГц, програма чомусь не запрацювала. Напевно треба виправити значення бітів? Артем Двинин каже: Доброго времени суток, Олександр. #include Допоможіть початківцю! ///// void init (void) ISR (TIM0_OVF_vect) // переривання int main (void) ///////////////////////// 1. З IDE завантажую скетч в Ардуіно Леонардо, де інформація по USB кожну секунду направляється на вихід. В консолі бачу щосекундне оновлення. А чи не простіше в рахунковий регістр занести відразу нуль TCNT1 = 0;
Таймер стартує коли дільник частоти не дорівнює нулю, відповідно, що б зупинити таймер треба виставити дільник частоти рівним нулю, наприклад, для таймера 1 atmega8 треба обнулити біти CS12, CS11, CS10
не знаю як налаштує таймери.
Допоможіть будь ласка.
за ранні спасибі.
Хочу зробити програму. в якій через термінал ми вводимо число. і світлодіод блимає. ну наприклад написав 10, значить блимати буде 10 раз в сек і тд.
Допоможіть порадою будь ласка
Заздалегідь вдячний
Ось мій код
Потрібна ваша допомога! Я не програміст, починаю з простого - з Ардуіно (знаю, поганий початок, але так склалося). ось код
Вибачте, що не відразу відповідаю, літо, відпустка ... відпочиваю від комп'ютера :)
Ардуіно - нормальне початок, поки його можливостей вистачає, чомусь б і не використовувати, тим більше що це простіше ніж писати на голому Сі.
Можу підказати, як вирішити вашу задачу без бібліотек від arduino, використовуючи тільки ардуіновску плату.
Як компілятора буде avr-gcc або WinAvr.
Якщо Вам цікаво - пишіть, продовжимо спілкування :)
Я свою проблему вирішив, прилад - це вимірювач ємності від 1пФ + -0,25 пФ до 1,5 мкФ + -2,5нФ. Все працює, але цікаво було б зробити все не на Arduino IDE.
Ось мій код:
Заздалегідь дякую!
Таймер в avr 16 бітний, що б отримати 32 розряду можна налаштувати переривання по переповнення, і в цьому перериванні збільшувати програмний лічильник, назвемо його cnt.
Тоді виміряне значення буде (cnt <<16) + TCNT1;
Щоб отримати частоту більше ніж 8МГц / 256 можна спробувати переписати обробник на асемблері або використовувати таймер1 в режимі CTC (Clear Timer on Compare).
Виставляючи біти COMnA1: 0. COMnB1: 0, COMnC1: 0 Ви включаєте альтернативну функцію виведення, і забороняєте його роботу як звичайного порту введення-виведення (тобто виставити значення з програми не вийти). При цьому треба не забути налаштувати відповідний висновок на вихід.
Може спробувати спочатку просту програму?
Якщо буде блимати, то справа в налаштуваннях таймера, якщо немає, то не працює світлодіод.
Чи не запускається таймер на Attiny44
#define F_CPU 8000000UL
#include
TCCR0B | = (1<
init (); // ініціалізація
sei (); // дозвіл всіх переривань
while (1)
asm ( "nop");
>
>
В даному випадку таймер навіть не починає рахувати!
Підкажіть в чому проблема ??
Заздалегідь вдячний.
2. Підключаю замість консолі TeraTerm \ ttermpro.exe ». У вікні бачу щосекундне оновлення.
3. Всі закриваю, відключаю Ардуіно від USB.
4. Підключаю Ардуіно до USB. Підключаю TeraTerm \ ttermpro.exe ». У вікні бачу оновлення через 8 секуунд.
А в регістр порівняння стільки тактів, скільки треба порахувати, наприклад 500 OCR1A = 500;
І налаштувати таймер на переривання за випадковим збігом. Ось весь код настройки:
TCCR1A | = (0 <
TCNT1 = 0; // Обнуляємо значення рахункового регістра таймера / счётчіка1Схожі статті