У статті описані методи запуску і формування PWM (Pulse-Width Modulation, або по-російськи ШІМ) в мікроконтролерах AVR за допомогою вбудованих таймерів / лічильників T / C0, T / C1 і T / C2. ШІМ широко застосовується для цифро-аналогового перетворення, генерації сигналів довільної форми, регулювання.
1. T / C0 є 8-восьмібітних, сам лічильник знаходиться в регістрі TCNT0. При переповненні (перехід 0xFF-> 0x00) може генеруватися переривання TIMER0_OVF (Timer / Counter0 Overflow, прапор TOV0). Це переривання забороняється (маскується) бітом TOIE0 (біт 0 регістра TIMSK). Прапор TOV0 автоматично очищається при виконанні процедури переривання.
2. Для лічильника TCNT0 визначені 3 спеціальних значення, за якими можуть відбуватися певні події:
BOTTOM == 0x00
MAX == 0xFF
TOP == MAX або OCR0
3. TCNT0 може вважати як вгору (інкрементіровать), так і вниз (декрементіроваться). Це визначається обраним режимом роботи.
4. Для TCNT0 джерело тактирования і його частота вибирається битами CS02: 0 (біти 0..2 регістра TCCR0). Можна навіть зовсім заборонити роботу TCNT0 (записавши в CS02: 0 все нулі).
5. Є 8-бітний регістр OCR0 - регістр цифрового компаратора. При збігу TCNT0 == OCR0 встановлюється Output Compare Flag (OCF0) і може генеруватися переривання TIMER0_COMP (Timer / Counter0 Compare Match). Прапор OCF0, як водиться, автоматично очищається при виконанні процедури переривання. Переривання TIMER0_COMP забороняється (маскується) бітом OCIE0 (біт 1 регістра TIMSK). Крім того, ця подія може генерувати апаратний PWM-сигнал на виводі OC0 процесора (ніжка 4 корпусу DIP40, порт PB3). Сигнал Timer / Counter0 Compare Match використовується генератором сигналу PWM.
6. Тип PWM вибирається битами Waveform Generation Mode - WGM01: 0 (біти 3 і 6 регістра TCCR0 відповідно). Від них також залежить, коли встановлюється прапор The Timer / Counter Overflow (TOV0). З цього прапору може генеруватися переривання TIMER0_OVF. Всього існує 4 режими:
Установка OC0 при подію compare match коли рахунок вгору, скидання при рахунку вниз (PWM з інверсією).
Режим відрізняється вдвічі меншою частотою PWM, але має більш високу якість формування сигналу, аж до граничних значень OCR0 (0x00 і 0xFF). Режим добре підходить для управління моторами. В цьому режимі TCNT0 спочатку вважає вгору, досягає 0xFF, потім починає вважати вниз, досягає 0x00, починає вважати вгору і процес повторюється. Timer / Counter Overflow Flag (TOV0) встановлюється кожного разу, коли TCNT0 досягає BOTTOM (0x00). Загальна формула обчислення частоти PWM:
fOC0PWM = fclk_IO / N * 510. де N рівний коефіцієнту ділення (prescale factor 1, 8, 64, 256, або 1024).
14. При роботі від внутрішньої тактової частоти 1 МГц (значення за замовчуванням) максимальна частота ШІМ в режимі fast PWM буде дорівнює
1000000/256 = 3906,25 Гц.
Така частота підійде для повільно мінливих процесів. Якщо підняти тактову частоту до 8 МГц (для цього треба записати fuses CKSEL3..0 в значення 0100), то частота ШІМ буде
8000000/256 = 31250 Гц
Така частота не чутна людським вухом, і може застосовуватися для генерації звуків.
15. Приклад настройки PWM в режимі fast PWM:
Після такого налаштування частота ШІМ на виході буде 3906.25 Гц, шпаруватість сигналу 50%.
1. Лічильник T / C1 значно відрізняється від T / C0 хоча б тим, що 16-бітний, і має два регістри цифрового компаратора OCR1A і OCR1B і 2 апаратних виходу PWM - OC1A і OC1B. і має 2 регістра управління TCCR1A і TCCR1B.
2. Для лічильника TCNT1 визначені 3 спеціальних значення, за якими можуть відбуватися певні події:
BOTTOM == 0x0000
MAX == 0xFFFF
TOP == 0x00FF, 0x01FF, 0x03FF або OCR1A або ICR1
3. До 16-бітовим регістрів (TCNT1, OCR1A, OCR1B і ICR1) потрібні спеціальні методи поводження, читаються і записуються через 2 восьмібітних операції за участю тимчасового 8-біт регістра (він загальний для всіх 16-біт регістрів одного таймера). Через цей проміжний регістр передається значення старшого байта, а звернення до молодшого (окремому для кожного 16-біт регістра) запускає виконання 16-біт операції. Не всі 16-біт регістри використовують тимчасовий регістр для high-байта, наприклад OCR1A і OCR1B.
Ось той же приклад із забороною переривань:
Якщо записується відразу кілька 16-бітових регістра з однаковим high-байтом, то high-байт можна записати тільки 1 раз.
4. Як і в T / C0, прапори переривань (ICF1, OCF1A, OCF1B, TOV1) знаходяться в регістрі Timer Interrupt Flag Register (TIFR). Як і в T / C0, кожне з переривань може маскуватися через Timer Interrupt Mask Register (TIMSK), біти маскування TICIE1. OCIE1A. OCIE1B. TOIE1.
5. Тактирование T / C1 таке ж, як і у T / C0. Джерело тактів вибирається регістром Timer / Counter Control Register B (TCCR1B).
Майже все написане раніше про T / C0 справедливо і для T / C2. оскільки відрізняються вони тільки в тому, що T / C2 має більш точний переддільник для тактової частоти (трохи по-іншому працюють біти управління предделителя CS22: 0 - біти 2..3 регістра TCCR2), а також якщо T / C0 міг тактіроваться від зовнішнього сигналу на T0, ніжка 1, порт PB0, то T / C2 може тактіроваться від додаткового кварцового генератора, так званого External 32 kHz Watch Crystal. незалежного від основної тактової частоти (чи не від ніжок XTAL2 вив. 12 і XTAL1 вив. 13, а від TOSC2 порт PC7 ніжка 29 і TOSC1 порт PC6 ніжка 28).
Припустимо, що потрібно формувати прямокутний сигнал частотою кілька десятків кілогерц, щоб генерувати негативне напруга живлення операційного підсилювача. Частота не критична, повинна бути в діапазоні 20..200 кГц. Оброблювач переривання не потрібен, формування меандру має відбуватися суто апаратно, без участі процесора. Ось кроки, які належить виконати:
Крок 1, тактова частота таймера. Потрібно підібрати значення для біт настройки предделителя тактової частоти. Це біти CS12, CS11, CS10, знаходяться вони в регістрі TCCR1B. Вибір робиться на основі тактової частоти мікроконтролера і потрібної частоти, що генерується ШІМ на виході. Т. е. Цими бітами потрібно грубо вибрати тактову частоту для таймера. Ось таблиця значень цих біт, і коефіцієнти розподілу прескалера.
Timer1 як тактів буде використовувати зовнішній сигнал, що подається на ніжку T1. Лічильник буде вважати фронти лог. рівня (переходи від 0 до 1).
Для нашого випадку підійде тактова частота 2 МГц, тому з таблиці для налаштування біт можна вибрати третю сходинку. Потрібно встановити біт CS11, а біти CS12 і CS10 повинні бути скинуті.
Примітка: вибір тактової частоти по таблиці робиться з урахуванням того, з якою частотою буде переповнюватися таймер. Частота переповнення таймера, крім частоти тактирования, також залежить від обраного значення верхньої межі рахунку і від режиму рахунку.
Крок 2, діапазон рахунку. Вибрати діапазон рахунку, т. Е. В яких межах буде вважати лічильник. Виберемо для лічильника 32 значення, межа рахунку буде визначатися значенням регістра ICR1. В цьому випадку таймер буде рахувати від 0 до 31, і ці цикли будуть повторюватися переповнюватися з частотою 2 МГц / 32 = 62,5 кГц. Якщо вибрати режим ШІМ з коректною фазою (PWM Phase Correct, про це далі), то частота на виході OC1A вийде 31.25 кГц, що цілком підходить.
Примітка: докладніше про межі рахунку Timer1 см. [3], "BOTTOM, MAX, TOP: граничні значення рахунку".
Крок 3, установка порогу рахунку. Записати в регістр OCR1A порогове значення, при досягненні якого лічильником буде змінюватися рівень на виході OC1A. Для отримання меандру це повинно бути число 16:
Крок 4, як повинен перемикатися вихід OC1A. Поведінка виходу ШІМ OC1A залежить від обраного режиму ШІМ, і від стану біт Compare Output Mode. Це біти COM1A1 і COM1A0 в регістрі TCCR1A. У таблиці нижче наведені значення біт для режимів Compare Output Mode, режими Phase Correct PWM і Phase and Frequency Correct PWM.
Примітка (1): імена біт CTCn і PWMn1: 0 застаріли. Замість них використовуйте імена WGMn2: 0. Однак функціонал і розміщення цих біт сумісний з попередньою версією таймера.
Для нашого випадку виберемо режим Phase and Frequency Correct (рядок в таблиці, відповідна Mode 8), значення для біт WGM1n == 1000b. Для цього режиму потрібно встановити біт WGM13 в регістрі TCCR1B (біт WGM12 залишиться скинутим), біти WGM11 і WGM10 в регістрі TCCR1A залишаться скинутими.
Крок 6, настройка вихідного порту для виведення ШІМ. Щоб вихідний сигнал OC1A з'явився на виведення ніжки мікроконтролера, потрібно порт PD5 налаштувати як вихід (за замовчуванням він працює як вхід):
Ось повний код процедури на мові C, яка виконує всі описані дії:
Примітка: маска, яка потрапляє в регістр, генерується операцією зсуву вліво константи номера біта. Оскільки біти можуть бути розкидані по різних регістрів, будьте обережні з операцією присвоювання маски регістру. Перше присвоювання має бути зроблено операцією =, ця операція скине всі біти регістра, які не встановлені в масці. Наступні установки біт в цьому регістрі по масці повинні робитися операцією читання-операція-запис, в даному випадку | = (читання - операція АБО - запис). Будьте уважні!