Аппаратная шим на микроконтроллере

AVR. Аппаратный ШИМ микроконтроллера

Широтно-импульсная модуляция (pulse width modulation, PWM) часто используется в цифровой технике. AVR-микроконтроллеры имеют встроенную аппаратную возможность генерировать ШИМ-сигнал.
Особенность этого способа модуляции заключается в том, что он позволяет регулировать постоянную составляющую выходного сигнала средствами логических элементов. Другими словами можно изменять яркость светодиодов, скорость вращения коллекторных двигателей, температуру нагревателей и т.д.
Временная диаграмма ШИМ-сигнала:

Подготовка к работе

На нашей плате TutorShield есть трехцветный светодиод. Отдельные цвета подключены к выводам PB1, PB2 и PB3 на которые можно вывести ШИМ-сигнал. Для возможности управления им, установите перемычку «color» так, как показано на рисунке. Всех остальных перемычек быть не должно.

Голубой светодиод подключен к выводу PB1, оранжевый к PB2, зеленый к PB3.

Первый пример

У микроконтроллера есть встроенные таймеры, которые и управляют формированием ШИМ-сигнала. Для использования достаточно правильно настроить таймер и затем для формирования сигнала потребуется только изменять состояние одного регистра.
Вообще, таймеры в микроконтроллерах — очень полезная вещь. Они позволяют точно отмерять время, выполнять «фоновые» программы и т.д. Их полный функционал описан в datasheet от производителя микроконтроллера. В этой статье мы не будем описывать весь функционал таймера, а остановимся только на том, что понадобится нам для генерирования ШИМ-сигнала.
Прежде чем начать объяснения, давайте посмотрим как это будет выглядеть. Скомпилируйте и загрузите в память микроконтроллера следующую программу:

То что программа делает хорошо видно в функции main(). С периодичностью в 1000мс она изменяет яркость светодиода:

Теперь давайте подробно разберемся с настройкой таймера.

Настройка таймера

Вся программа сводится к тому, что необходимо правильно настроить таймер, а затем остается просто в правильный регистр записывать требуемое значение скважности сигнала. После этого вам уже не надо будет думать о том, как работать с выходом — управление им берет на себя модуль таймера.
Таймеры в микроконтроллерах — очень мощный инструмент. Сейчас мы остановимся только на том, как сконфигурировать их на генерирование ШИМ-сигнала. Более подробно о работе с таймерами мы расскажем в следующих статьях. Исчерпывающую информацию о работе таймеров можно получить из даташита.
Вернемся к нашей программе. В ней первым делом настраиваются сразу все нужные выводы на выход, а затем происходит инициализация таймера. По порядку рассмотрим в каких регистрах и какие функции включены в нашей программе:

  1. Timer/Counter 1 Control Register A – TCCR1A. Бит COM1A1 это регистра отвечает за сброс таймера при совпадении. Бит WGM11 связан с битами WGM12 и WGM13 следующего регистра.
  2. Timer/Counter 1 Control Register B – TCCR1B. Биты WGM11, WGM12, WGM13, выставленные одновременно, переводят таймер в режим генерирования ШИМ-сигнала. Бит CS10 задает скорость счета таймера одновременно запускает таймер и задает делитель частоты тактового сигнала. Если не задать никакой делитель — таймер будет остановлен. С битом CS10 делитель будет равен единице, то есть таймер будет тактироваться от кварца.
  3. Timer/Counter 1 – TCNT1H и TCNT1L. В этих двух регистрах хранится состояние таймера. Именно в них с каждым «тиком» кварца увеличивается хранимое значение. Обнулим его, на всякий случай
  4. Input Capture Register 1 – ICR1H и ICR1L. Это период следования импульсов. То есть, когда содержимое регистра TCNT1 достигнет значения 0xFF начнется следующий период сигнала
  5. Output Compare Register 1A — OCR1AH и OCR1AL. Задает скважность. То есть пока в регистре TCNT1 значение меньше OCR1A, то на выводе «1», а после этого «0»

Все это гораздо проще понять по следующей картинке:

Диаграмма работы таймера

Мы предположим, в регистр OCR1A записано значение «100».
Тактовый сигнал у нас задан без делителя. Период следования тактовых импульсов 1/16МГц = 62,5нс. С каждым новым тактом, состояние регистра TCNT1 увеличивается на единицу. При это постоянно происходит его сравнение с регистрами OCR1A и ICR1. Как только он досчитывает до OCR1A происходит переключение состояния вывода из «1» в «0». При достижении значения ICR1 состояние TCNT1 сбрасывается в ноль, на выводе снова выставляется «1» и начинается следующий период сигнала.
Несложно посчитать период следования импульсов в нашем проекте: 255*62,5 = 15937,5нс. Примерно 16мкс. Частота при этом 62,5кГц. Это очень большая частота и снизить ее можно увеличив делитель или/и значение ICR1.
В итоге, чтобы изменить скважность сигнала остается только записать новое значение в регистр OCR1. Мы переопределили его директивой

В бесконечном цикле программа именно это и происходит: устанавливаем относительную скважность 200, ждем 1с, скважность 50, ждем 1с. Осталось только самое простое — понять на каком выводе будет этот сигнал. Изменить это нельзя и формироваться он будет на выводе OC1A, который в микроконтроллере Atmega8 подключен к 13му пину PB1 (или D9 выводу Arduino).

Второй пример

Теперь сделаем циклическое изменение яркости. Для потребуется только добавить цикл, перебирающий возможные значения скважности от 0 до 255. Сделаем его при помощи простой функции for().

Если все сделано правильно — то работа будет выглядеть вот так:

Третий пример

Всего в микроконтроллере Atmega8 два аппаратных таймера — 16ти-битный и 8ми-битный. Причем в первом есть сразу два модуля сравнения и он может формировать одновременно два разных ШИМ-сигнала. Третий ШИМ-сигнал может быть сформирован при помощи второго таймера. То есть всего на трех выводах может быть сгенерирован аппаратный ШИМ. Это выводы МК PB1, PB2 и PB3. Именно этим обусловлены ограничения функции Arduino analogWrite().
В этом разделе настроим еще два канала и будем управлять остальными светодиодами.
Для этого потребуется только дополнительно выставить бит COM1B1 и начать управлять регистром OCR1B. На эти действия будет реагировать оранжевый светодиод, подключенный к выводу PB2.
Для использования третьего канала придется вставить дополнительную функцию timer2_init() для запуска второго таймера.

Второй таймер имеет гораздо меньше функций и настраивать его проще. Бит COM21 выводит сигнал на ногу. Биты WGM21 и WGM20 переводят таймер в режим формирования ШИМ. CS20 задает делатель тактового сигнала, равный нулю. Как видите, тут изменять частоту получится только при помощи делителя.
Вот видео работы этого примера:

AVR Урок 13. ШИМ. Мигаем светодиодом плавно. Часть 1

Сегодня мы изучим возможность использования широтно-импульсной модуляции в микроконтроллере AVR, или, как говорят в народе, ШИМ.

В технической документации мы будем видеть чаще аббревиатуру PWM или pulse-width modulation, что преводится имено также.

Что же такое вообще широтно-импульсная модуляция.

ШИМ – это управление свечением светодиодов, вращением двигателей, и прочими устройствами необычным способом, при котором данное управление осуществляется не приложенным напряжением к контактам, а квадратными импульсами. При этом напряжение будет только двух видов – высокое (1) и низкое (). При данном способе результирующее напряжение вычисляется как среднее по времени между временем высокого состояния в одном импульсе и временем низкого состояния. Мы вычисляем отношение времени (или широты) высокого состояния к общему периоду импульса. Называем мы это скважностью импульса. То есть чем больше в периоде напряжение находилось в высоком состоянии, тем больше скважность, а, следовательно, тем больше и результирующее среднее напряжение. То есть, чтобы найти результирующее напряжение, нам необходимо и достаточно вычисленную скважность умножить на напряжение и разделить на 100, так как скважность как правило измеряется в процентах. Например, если у нас в квадратном импульсе широта логического нуля равна широте логической единицы, то скважность у нас будет 50 процентов, и, если напряжение будет 5 вольт, то среднее результирующее напряжение мы получим равное 2,5 вольт и т.д. Лучшую картину объяснения данной ситуации мы можем увидеть, посмотрев видеоурок, ссылка на который дана в конце данной статьи.

Это конечно очень упрощённое понятие ШИМ. Есть более серьёзные разъяснение данной технологии, но нам для наших экспериментов этого будет вполне достаточно.

То есть, подведя итоги объяснению, мы управляем результирующим напряжением, а также и свечением светодиода, угловой скоростью электродвигателя и прочими значениями за счёт изменения скважности импульсов.

Но всё-таки самое интересное, как же всё-таки всё это организовано в нашем микроконтроллере?

В микроконтроллере AVR широтно-импульсную модуляцию можно организовать как программно, так и аппаратно.

Программная организация ШИМ – это когда мы включим на определённое время на ножке контроллера логическую единицу, а затем на определённое время – логический ноль и так по циклу. Плюсы данного способа – это то, что мы можем организовать ШИМ на абсолютно любой ножке любого порта контроллера, а минусом – то, что всё это будет связано с немалыми затратами на процессорное время, и возможно даже будет сопряжено с какими-то ошибками, вытекающими из этого.

Поэтому всегда в любой технологии мы стараемся придерживаться всё-таки именно аппаратного способа реализации.

Аппаратная организация ШИМ в МК AVR происходит на уровне таймера 2.

Как мы помним из предыдущего занятия, таймеров в конкретном нашем микроконтроллере Atmega8 три. И таймеры 0 и 2 являются восьмибитными. Но на уровне 2-го таймера как раз и организована широтно-импульсная модуляция.

Давайте посмотрим вот такую вот картину

Здесь иллюстрируется то, какие мы должны включить биты в регистре TCCR второго таймера, чтобы запустить широтно-импульсную модуляцию.

Читайте также  Фонарик с беспроводным зу

Биты WGM как раз и включают таймер в резим PWM (ШИМ). С остальными битами разберёмся позже, если это потребуется.

А сейчас, чтобы это всё прочувствовать, нам необходим проект, который мы и создадим сейчас.

Проект создаем таким же образом, как и на прошлых занятиях. Назовём его Test10, создадим и добавим файлы PWM.c и PWM.h, последний автоматически оформится при создании соответствующими директивами прероцессора. А в главном файле Test01.c мы напишем стандартный код

void port_ini ( void )

Как мы видим в коде, в порте B мы включили на выход 3 ножку. В распиновке контроллера мы видим, что у данной ножки есть ещё альтернативное обозначение OC2, которое и означает возможность этой ножки работать непосредственно с ШИМ

Файл main.h мы можем даже подключить с прошлого занятия по LCD и немного исправим код, подключив туда уже новый наш модуль PWM

#define F_CPU 8000000UL

#include «PWM.h»

Ну и теперь начнём писать код в новую библиотеку для работы непосредственно с ШИМ – в файл PWM.c.

Там мы также подключим заголовочный файл и создадим каркас функции для работы с ШИМ

#include «PWM.h»

void init_PWM_timer ( void )

А в заголовочный файл нашей библиотеки мы добавим прототип данной функции, а также подключим библиотеку для работы с прерываниями

void init_PWM_timer ( void );

И вызовем сразу эту функцию в main()

init_PWM_timer ();

Начнём теперь писать код непосредственно в функцию. Сначала запишем все нули в регистр ASSR, который существует у таймера, но мы его никак не используем

void init_PWM_timer ( void )

ASSR =0x00;

Дальше уже займёмся управляющим регистром нашего таймера. Назначение битов WGM и то, какие именно из них мы включим, мы разобрали. Теперь биты COM20 и COM21, отвечающие за режим самого ШИМ. Мы выберем вот такой режим и соответственно ему и включим данные биты

А включим мы режим, при котором при начале счёта напряжение на ножке OC2 будет находиться в высоком логическом состоянии, а как только мы досчитаем до определённой цифры, то ножка перейдёт в низкое состояние и будет в нём находиться до окончания счёта. И так по кругу.

И останется нам только настроить делитель. Слишком большая частота нам не нужна. Но когда была слишком маленькая, также было заметно мерцание, поэтому давайте включим следующую величину

Поэтому мы включим все три бита.

В итоге значение регистра станет вот таким

TCCR2 =0b01101110; //Fast PWM, Clear OC2 on Compare Match, clkT2S/256 (From prescaler) (реальная частота получится 8мгц/256 = 31250 гц)

Теперь попробуем собрать проект. Проект нормально собрался. В следующей части мы продолжим работать с ШИМ.

Купить программатор можно здесь (продавец надёжный) USBASP USBISP 2.0

Смотреть ВИДЕОУРОК (нажмите на картинку)

AVR Lab устройства на микроконтроллерах AVR

Форум по AVR

  • не работает программа из примера про пролистывания меню
  • sinaprog не работает
  • Пароль к архивам на сайте
  • Пароль
  • HDD и прерывания — доработка программы из статьи /node/220

Аппаратная ШИМ в микроконтроллере ATmega8

  • atmega8
  • avr
  • PWM
  • ШИМ

В этой заметке я постараюсь немного затронуть тему аппаратной ШИМ (широтно-импульсной модуляции, англ. PWM — Pulse-width modulation) в микроконтроллерах семейства AVR на примере микроконтроллера ATmega8. Классический ШИМ сигнал представляет собой цифровой сигнал, определенной постоянной частоты.

Меняться в нем может скважность — длительность состояния логической единицы в периоде сигнала. Например, на рисунке внизу показаны разные ШИМ сигналы, скважность которых увеличивается с верхнего графика к нижнему:

ШИМ совместно с RC цепочкой используется для генерации аналогового сигнала, а если позволяет частота – то я для воспроизведения звука. Мое первое столкновения с ШИМ произошло, когда я захотел плавно менять яркость мощного одноваттного светодиода. После ШИМ помогла решить проблему управления скоростью вращения двигателя постоянного тока, и управления цветом RGB светодиода.

Для демонстрации работы с ШИМ напишем программу, которая будет плавно менять яркость светодиода от нуля до максимума, а потом плавно ее снижать. То есть нам нужно сгенерировать примерно такой ШИМ сигнал (масштаб не соблюден):

Генерировать сигнал будем аппаратными средствами микроконтроллера ATmega8. Можно конечно сгенерировать все и программно, но это не экономично и неудобно, если микроконтроллер должен выполнять что-то еще, кроме генерации ШИМ сигнала. Принципиальная схема макета:

На схеме показана стандартная обвязка ATmega8. Q1 — любой pnp транзистор, способный выдержать ток 500мА, я использовал биполярный pnp транзистор ZXTN19020, так как у него очень малое сопротивление открытого канала коллектор-эмиттер, всего 18 миллиом и при токах 500ма он не будет ощутимо греться. Транзисторный ключ открывается при высоком уровне на PB1 и пропускает через цепочку резистор R4-коллектор-эмиттер-светодиод ток, который по закону Ома равен I=5B/R4. (сопротивлением светодиода в рабочем состоянии и канала коллектор-эмиттер на транзисторе Q1 мы пренебрежем).

Зададимся, что наш светодиод во включенном состоянии будет питаться током 500мА (максимальный ток для светодиода Cree MC-E, используемого мною в этом макете, при последовательном соединении 4-х кристаллов составляет 2.8А), для этого вычислим номинал ограничительного резистора: R4=5В/0,5А=10 Ом. R3 номиналом 1 кОм. Следует не забывать про охлаждение светодиода, иначе очень быстро сгорит. Для небольших мощностей достаточно использовать радиоатор и термопасту. Теперь перейдем к написанию прошивки:

Рассмотрим подробнее инициализацию ШИМ.
Будем использовать так называемый Phase correct PWM на таймере 1. Счетчик TCNT1 постепенно увеличивается (согласно установленному делителю), когда его содержимое становиться равным содержимому OCR1A, то на выводе OC1A в зависимости от битов COM1A0, COM1A1 (в регистре TCCR1A), устанавливается нолик или единица. После счетчик достигает 0xFF (в зависимости от битности ШИМ) и начинает уменьшатся. Как только TCNT1 снова сравняется с OCR1A, на пине OC1A уровень меняется на противоположный. После чего счетчик достигает 0х00 и все повторяется снова.
В нашем случае COM1A1=1,COM1A0=0. И это означает, что при начале счета, на выводе OC1A устанавливается высокий уровень. При достижении счетчиком значения OCR1A при возрастании уровень на OC1A становится нулевым. А при достижении счетчиком значения OCR1A при убывании, уровень на OC1A становиться высоким, и т.д. Проще говоря: «чем больше значение OCR1A – тем больше заполнение сигнала».

Битность и режим ШИМ задается с помощью битов WGM13-WGM10 (биты WGM13,WGM12 находятся в регистре TCCR1B, а биты WGM10, WGM11 в регистре TCCR1A).

Для нашего 8-ми битного Phase correct PWM требуется, чтобы WGM10=1.


Видео работы программы:

Пример реализации аппаратной ШИМ в несколько каналов на микроконтроллере ATmega8

Аппаратная шим на микроконтроллере

Шим для начинающих — аппаратный шим, практическое применение на примере Tiny13A

Автор: asw
Опубликовано 07.09.2011
Создано при помощи КотоРед.
2011

Поздравляю кота с Днём рождения!

В данной статье будет рассмотрен вариант настройки аппаратного ШИМ сигнала в МК AVR Tiny13A, его применение на примере управления яркостью светодиодной ленты (данное устройство встроено в ТФТ монитор вместо штатной подсветки).

Часть 1. Настройка.

Для данного устройства будем использовать таймер счётчик Т0 (он тут собственно единственный, так что выбирать не приходится). Для регулировки яркости выберем режим Fast PWM (быстрый ШИМ). Как видно из даташита (стр.73) за это отвечают биты WGM00, WGM01, WGM02 регистров TCCR0A и TCCR0B. (Маленькое отступление: в ходе настройки было выявлено, что при записи 1 в бит WGM02, режим быстрого ШИМ с участием регистров сравнения OCR0A (OCR0B) не включается, на выходе присутствовал только сигнал высокого уровня. Поэтому была выбрана другая рабочая конфигурация. Если кто пояснит детальнее, буду благодарен) В биты WGM00, WGM01 записываем 1. Так же в регистре TCCR0A присутствуют биты COM0A0, COM0A1 (COM0B0, COM0B1) — они отвечают за режимы работы блоков сравнения А (В) соответственно (стр. 70 даташита). Выбираем режим сброс вывода OC0A (OC0B) в 0 при равенстве регистров TCNT0 (счётный регистр) и OCR0A (OCR0B) (регистры сравнения), получается не инвертированный ШИМ, т.е. записываем 1 в бит COM0A1 (COM0B1).

(Отступление: а почему собственно, регистры сравнения, да потому, что туда записываем нужное число, какое необходимо в конкретной задаче, в данной статье это число будет менять скважность выходного сигнала нашего устройства, а следовательно и яркость линейки светодиодов)

В коде данная строка настройки выглядит так: outi tccr0a, 0b10100011; режим fast pwm

( outi — это макрос, т.е. маленький шаблон действий, которые часто выполняются. Как известно, операции с числами производятся через регистры общего назначения, т.е. чтобы вывести число в порт, сначала его надо записать в РОН. Вот именно это и делает данный макрос.)

Без макроса так: ldi r16, 0b10100011

out tccr0a, r16

Осталось выбрать частоту работы нашего ШИМ. Её следует выбирать в данном случае такой, чтобы не было видно мерцания светодиодной ленты. Вообще частота ШИМ в данном режиме считается по формуле из даташита, стр. 66. У меня частота вышла 585гц. (частота МК 9,6 Мгц, делитель на 8 в программе и делитель на 8 во фьюзах) За выбор частоты предделителя в данном МК отвечает регистр TCCR0B. Биты — CS00, CS01, CS02. Записываем 1 в бит CS01, чем включаем делитель на 8. (стр. 73-74 даташита)

Читайте также  Малогабаритная антенна св диапазона

Код: outi tccr0b, 0b00000010; делитель на 8

Теперь сконфигурируем нужные пины МК. Используя даташит, видим, что ШИМ сигнал выводится на определённые ножки МК, OC0A и OC0B, что соответствует 5й и 6й ножке МК (стр. 2 даташита)

Эти выводы нужно сконфигурировать как выходы, для этого нужно записать 1 в биты 0 и 1 регистра DDRB (В — порт МК, причём единственный здесь). На выводах 7 и 2 расположены кнопки (кто-то скажет что это расточительно, но в данном случае выводов пока хватает, а вешать гирлянду на АЦП нет смысла, не говоря уже о регистрах сдвига и тп, хотя место позволяет), одна из них регулирует яркость, другая отвечает за включение и выключение. Эти выводы МК конфигурируем как входы с подтяжкой (подтяжку хорошо бы использовать внешнюю, например 4.7к с плюса питания на вывод МК), таким образов в биты 2 и 3 регистра DDRB записываем 0, после чего в регистр PORTB в эти же биты выводим 1. (что-то не хочет нгормально отображаться при публикации данный кусок, в приложении есть проект, там всё нормально)

Код:

ldi r16, (1

out ddrb, r16

ldi r16, (1

out portb, r16

Часть2. Программа.

Алгоритм таков: при нажатии на кнопку регулировки, яркость изменяется от минимума до максимума и от максимума до минимума. При первом включении яркость 0. При нажатии кнопки включения выключения соответственно светодиоды гаснут или зажигаются. После выключения питания МК запоминает текущую яркость. Пишем программу. Вначале настройка, имена регистров по вкусу (полный текст будет приведён в конце статьи):

;ШИМ с регулировкой кнопкой и сохранением яркости в EEPROM, +принудительное включение-выключение отдельной кнопкой

;путь к файлу апноута

.include «tn13adef.inc»

.cseg

.def counter=r25

;настройка портов, таймеров, предделителей

.MACRO outi // Макрос отправка константы в регистр в/в

ldi r16, @1

out @0, r16

.ENDMACRO

ldi r16,RAMEND ; инициализация стека

out SPL,r16

ldi r17, 0 ;начальное значение регистров

mov r0, r17

ldi counter, 0 ; начальное значение счётчика

outi tccr0a, 0b10100011 ; режим fast pwm

outi tccr0b, 0b00000010 ; делитель на 8

outi gtccr, 0b00000001 ; сброс предделителя

rcall EEPROM_read ; вызов функции чтения из ЕЕРROM

;out ocr0a, r21 ; начальные значения скважности канала А

;out ocr0b, r21

;mov r0, r21

out ocr0a, r0 ; начальные значения скважности канала В

out ocr0b, r0

ldi r16, (1 Часть 3. Схема и готовое устройство.

Как было сказано выше, устройство делалось для управления подсветкой ЖК монитора. В имеющемся мониторе умер инвертор, 2 лампы и что самое нехорошее, отсутствовали ВСЕ сигналы управления инвертором, ни яркости ни выключения отключения не было. Так что решено было сделать своё. В начальной версии кнопки отключения не было, так монитор и отправился к владельцу (это было безвозмездное ремонтирование, в целях обучения). Вместо ламп были применены светодиодные ленты, 2 штуки, потребление одной ленты составило 500ма (точнее отрезков ленты определённой длины). Из этого следует, что в МК будут подключены управляющие транзисторы. Питание их осуществляется от штатного источника напряжения монитора (в моей ленте применяется параллельное соединение групп последовательно соединённых по три штуки светодиодов, это для ленты на 12 вольт, группы по 3 светодиода имеют свой ограничитель тока — резистор, потом источник тока ленте не нужен). Сама схема:

Печатная плата разрабатывалась для крепление на штатное место инвертора, потому в размере не стеснялся. Вид платы:

Полевые транзисторы взяты с материнской платы, N канальные. Контроллер использовался в корпусе SO8W (он пошире чем обычный SO). Резисторы в затворах для защиты контроллера и компенсация возбуждения на высоких частотах (на печатной плате проводники от управляющей ножки МК до затвора транзистора должны быть минимальной длины). Резисторы с затвора на землю для исключения самооткрывания транзисторов. Конденсаторы на 100n обычные блокировочные, электролиты на 100мкф. Можно ещё добавить подтяжку вывода Reset к плюсу питания. Так же, если подключать светодиоды непосредственно к выводу МК, то сигнал ШИМ нужно сглаживать RC цепью. Штырьки на печатной плате сделаны для удобства внутрисхемного программирования.

Использование широтно-импульсной модуляции (ШИМ) в микроконтроллерах AVR ATmega16

Широтно-импульсная модуляция (сокр. ШИМ, от англ. PWM — Pulse Width Modulation) является технологией, позволяющей изменять ширину импульсов в то время как частота следования импульсов остается постоянной. В настоящее время она применяется в разнообразных системах контроля и управления, а также в различных приложениях, таких как, к примеру, управление скоростью вращения двигателей, измерениях, управление мощностью чего-либо, связь и др.

Также при использовании ШИМ можно генерировать аналоговые сигналы используя цифровые сигналы. В данной статье мы рассмотрим основы применения широтно-импульсной модуляции (ШИМ) в микроконтроллере ATmega16 (семейство AVR) на примере изменения интенсивности свечения светодиода. Данный пример уже рассматривался на нашем сайте в этой статье (более подробная и наглядная статья), но здесь материал изложен немного по другому – у вас есть возможность выбрать какой из этих материалов использовать.

Контакты ШИМ в микроконтроллере AVR ATmega16

Микроконтроллер Atmega16 имеет 4 контакта для использования ШИМ модуляции — PB3(OC0), PD4(OC1B), PD5(OC1A), PD7(OC2). Более наглядно они представлены на следующем рисунке.

Также ATmega16 имеет два 8-битных (Timer0 и Timer2) и один 16-битный таймер (Timer1). Для понимания принципов формирования ШИМ мы должны понимать основы работы с этими таймерами. Как известно, частота представляет собой количество циклов в секунду поэтому она однозначно связано зависимостью с временем. То есть чем более высокая частота нам нужна, тем более быстрый таймер мы должны использовать. Чем выше частота ШИМ, тем более точно мы можем управлять ее параметрами.

В данной статье для управления ШИМ в микроконтроллере ATmega16 мы будем использовать его Timer2. С его помощью можно выбрать коэффициент заполнения/скважность (duty cycle) ШИМ в широких пределах. Кратко рассмотрим основы этого процесса.

Что такое ШИМ сигнал

ШИМ – это сигнал с различными интервалами ON и OFF сигнала (различными продолжительностями включения). Время, в течение которого сигнал имеет высокий уровень, называется временем включения (“on time”), а время, в течение которого сигнал имеет низкий уровень — время выключения (“off time”). У ШИМ сигнала есть два параметра, которые мы рассмотрим далее.

Коэффициент заполнения (скважность) ШИМ

Процент времени, в течение которого ШИМ сигнал имеет высокий уровень, называется коэффициентом заполнения (скважностью). К примеру, коэффициент заполнения ШИМ сигнала с периодом (длительностью) 100 мс, в котором в течение 50 мс сигнал имеет высокий уровень и в течение 50 мс имеет низкий уровень, равен 50%. Аналогично, если для такой же длительности (100 мс) сигнал 25 мс остается на высоком уровне и 75 мс на низком, то коэффициент заполнения для такого сигнала будет равен 25%. Для его определения нам необходимо знать только длительность высокого уровня сигнала (длительность низкого уровня легко определить как разность между периодом сигнала и длительность сигнала высокого уровня). Более наглядно ШИМ сигнал представлен на следующем рисунке.

Формула для расчета коэффициента заполнения/скважности (Duty Cycle) выглядит следующим образом:

Duty Cycle (%) = On Time/(On Time + Off Time)

Таким образом, изменяя коэффициент заполнения ШИМ сигнала мы можем изменять интенсивность свечения светодиода.

Выбор режима ШИМ

После выбора нужного нам коэффициента заполнения необходимо выбрать еще режим ШИМ – то есть то, каким образом ШИМ будет работать. Существует три типа ШИМ:

  1. Быстрая ШИМ (Fast PWM).
  2. ШИМ с коррекцией фазы (Phase Correct PWM).
  3. ШИМ с коррекцией фазы и частоты (Phase and Frequency Correct PWM).

Быстрая ШИМ используется в случаях когда нам не важна фаза импульсов, например, управление скоростью вращения двигателя или яркостью свечения светодиода.

Для генерации быстрой ШИМ нам необходимо будет запустить на таймере счет и когда он досчитает до определенного значения сбрасывать значение таймера снова в ноль. Таким образом мы установим период следования ШИМ импульсов. Таким образом мы можем контролировать импульс, устанавливая высокое значение сигнала когда счетчик таймера досчитает до определенного значения. А когда счетчик будет возвращаться в 0 на это время сигнал будет низкого уровня. Таким образом, мы имеем большую гибкость в управлении ШИМ сигналом используя всего лишь один таймер.

Необходимые компоненты

  1. Микроконтроллер ATmega16 (купить на AliExpress).
  2. Программатор AVR-ISP (купить на AliExpress), USBASP (купить на AliExpress) или другой подобный.
  3. Кварцевый генератор на 16 МГц (купить на AliExpress).
  4. Конденсатор 100 нФ (2 шт.) (купить на AliExpress).
  5. Конденсатор 22 пФ (2 шт.) (купить на AliExpress).
  6. Светодиод (2 шт.) (купить на AliExpress).
  7. Кнопка.
  8. Макетная плата.
  9. Соединительные провода.
  10. Источник питания с напряжением 5 Вольт.

Схема устройства

Схема устройства приведена на следующем рисунке.

Мы будем использовать для формирования ШИМ сигнала контакт OC2 микроконтроллера ATmega16, поэтому соедините контакт Pin21 (PD7) микроконтроллера со светодиодом.

Программирование ШИМ сигнала в микроконтроллере ATmega16 на языке С (Си)

Полный текст программы приведен ниже, а в этом разделе поясним ключевые особенности программы. Видео, демонстрирующее работу схемы, приведено в конце статьи. На видео вы можете видеть как яркость свечения светодиода будет изменяться постепенно в зависимости от изменения коэффициента заполнения ШИМ.

Начать программирование ШИМ ATmega16 необходимо с установки нужного значения регистра Таймера 2 – его биты приведены на следующем рисунке. Изменяя данные биты, мы можем настраивать нужные нам параметры ШИМ.

Читайте также  Повышающий преобразователь напряжения 12в в 18в

В регистре Таймера 2 три группы битов:

  1. FOC2 (Force Output Compare for Timer2) – устанавливается когда WGM биты определяют не режим ШИМ.
  2. WGM2(Wave Generation Mode for Timer2 – режим генерации волны) – эти биты контролируют последовательность счета, максимальное значение счета (TOP counter value) и какой тип формы сигналов будет использован.
  3. COM2 (Compare Output Mode for Timer2 – режим сравнения для Таймера 2) – можно выбрать режим с инвертированием и без инвертирования.

Установим биты WGM20 и WGM21 чтобы активировать режим быстрой ШИМ.

OSBoy notes.

Записки обо всём.

ATtiny13 — реализация ШИМ

В предыдущем примере мы затронули тему использования счётчика/таймера ATtiny13 в обычном режиме и в режиме подсчёта импульсов (CTC). В этой статье я продолжаю тему таймера, но теперь мы рассмотрим его применение для реализации широтно-импульсной модуляции (ШИМ).

Все микропроцессоры работают с цифровыми сигналами, т.е. с логическим нулем (0 В), и логической единицей (5 В или 3.3 В). Но что делать, если мы хотим получить на выходе какое-либо промежуточное значение? В таких случаях применяют Широтно-импульсную модуляцию (ШИМ, англ. pulse-width modulation (PWM)) — процесс управления мощностью, подводимой к нагрузке, путём изменения скважности импульсов, при постоянной частоте.
Широтно-импульсная модуляция представляет собой периодический импульсный сигнал. Существуют цифровые и аналоговые ШИМ, однополярные и двуполярные, и т.д. Но принцип их работы остается одинаковым вне зависимости от исполнения и заключается в сравнении двух видов сигналов: опорного (пилообразные или треугольные импульсы) и входного (постоянного, либо изменяемого нужным образом, в зависимости от конкретной задачи ШИМ). Эти сигналы сравниваются и, при их пересечении, изменяется уровень сигнала на выходе ШИМ. Выходное напряжение ШИМ имеет вид прямоугольных импульсов, изменяя их длительность, мы можем регулировать среднее значение напряжения на выходе ШИМ *.

* Если на выходе ШИМ использовать интегрирующую RC-цепь, то можно вместо импульсного получить постоянное напряжение нужной величины. Но в нашем примере со светодиодами можно обойтись и без этого, так как человеческий глаз всё равно не сможет разглядеть мерцания светодиода при используемой тактовой частоте.

Параметры ШИМ

  • T — период тактирования (опорного сигнала);
  • t — длительность импулься;
  • S — скважность;
  • D — коэффициент заполнения.

Скважность определяется отношением периода к длительности импульса. Коэффициент заполнения — величина, обратная скважности (может выражаться в процентах):

S=T/t=1/D

Рассмотрим подробнее, как работает ШИМ в AVR микроконтроллерах, на примере ATtiny13.
Как уже упоминалось в предыдущем примере, в ATtiny13 реализовано две разновидности ШИМ: так называемые «Быстрая ШИМ» (Fast PWM) и «ШИМ с коррекцией фазы» (Phase correct PWM). Оба варианта основаны на использовании встроенного в МК восьмибитного счётчика/таймера T0. Таймер тут используется вместо опорного сигнала. Тактовая частота таймера задаётся предделителем тактовой частоты процессора, либо от внешнего тактового генератора. Режим тактирования задаётся битами CS02 (2), CS01 (1), CS00 (0) регистра TCCR0B:

  • 000 — таймер/счетчик T0 остановлен
  • 001 — тактовый генератор CLK
  • 010 — CLK/8
  • 011 — CLK/64
  • 100 — CLK/256
  • 101 — CLK/1024
  • 110 — от внешнего источника на выводе T0 (7 ножка, PB2) по спаду сигнала
  • 111 — от внешнего источника на выводе T0 (7 ножка, PB2) по возрастанию сигнала

Настройка таймера для ШИМ

Режим работы таймера задаётся битами WGM01 (1) и WGM00 (0) регистра TCCR0A:

  • 00 — обычный режим
  • 01 — режим коррекции фазы ШИМ
  • 10 — режим подсчета импульсов (сброс при совпадении)
  • 11 — режим ШИМ

Здесь нас интересуют варианты «01» и «11».

Биты COM0A1 (7) и COM0A0 (6) регистра TCCR0A задают, какой сигнал появится на выводе OC0A (5 ножка, PB0) при совпадении счётчика (регистр TCNT0) с регистром сравнения A (OCR0A).

В режиме «Быстрая ШИМ»:

  • 00 — вывод OC0A не функционирует
  • 01 — если бит WGM02 регистра TCCR0B установлен в 0, вывод OC0A не функционирует
  • 01 — если бит WGM02 регистра TCCR0B установлен в 1, изменение состояния вывода OC0A на противоположное при совпадении с A
  • 10 — установка 0 на выводе OC0A при совпадении с A, установка 1 на выводе OC0A при обнулении счётчика (неинверсный режим)
  • 11 — установка 1 на выводе OC0A при совпадении с A, установка 0 на выводе OC0A при обнулении счётчика (инверсный режим)

В режиме «ШИМ с коррекцией фазы»:

  • 00 — вывод OC0A не функционирует
  • 01 — если бит WGM02 регистра TCCR0B установлен в 0, вывод OC0A не функционирует
  • 01 — если бит WGM02 регистра TCCR0B установлен в 1, изменение состояния вывода OC0A на противоположное при совпадении с A
  • 10 — установка 0 на выводе OC0A при совпадении с A во время увеличения значения счетчика, установка 1 на выводе OC0A при совпадении с A во время уменьшения значения счетчика (неинверсный режим)
  • 11 — установка 1 на выводе OC0A при совпадении с A во время увеличения значения счетчика, установка 0 на выводе OC0A при совпадении с A во время уменьшения значения счетчика (инверсный режим)

Биты COM0B1 (5) и COM0B0 (4) регистра TCCR0A задают, какой сигнал появится на выводе OC0B (6 ножка, PB1) при совпадении счётчика (регистр TCNT0) с регистром сравнения B (OCR0B).

В режиме «Быстрая ШИМ»:

  • 00 — вывод OC0B не функционирует
  • 01 — резерв
  • 10 — установка 0 на выводе OC0B при совпадении с B, установка 1 на выводе OC0B при обнулении счётчика (неинверсный режим)
  • 11 — установка 1 на выводе OC0B при совпадении с B, установка 0 на выводе OC0B при обнулении счётчика (инверсный режим)

В режиме «ШИМ с коррекцией фазы»:

  • 00 — вывод OC0B не функционирует
  • 01 — резерв
  • 10 — установка 0 на выводе OC0B при совпадении с B во время увеличения значения счетчика, установка 1 на выводе OC0B при совпадении с B во время уменьшения значения счетчика (неинверсный режим)
  • 11 — установка 1 на выводе OC0B при совпадении с B во время увеличения значения счетчика, установка 0 на выводе OC0B при совпадении с B во время уменьшения значения счетчика (инверсный режим)

Быстрая ШИМ (Fast PWM)

В этом режиме счётчик считает от нуля до максимума. При установке нулевого значения счётчика — на выходе появляется импульс (устанавливается логическая единица). При совпадении с регистром сравнения — импульс сбрасывается (устанавливается логический ноль). В инверсном режиме, соответственно — наоборот.

ШИМ с коррекцией фазы (Phase correct PWM)

В этом режиме счётчик считает от нуля до максимума, а затем в обратном направлении, до нуля. При совпадении с регистром сравнения во время нарастания значения счётчика — импульс сбрасывается (устанавливается логический ноль). При совпадении во время убывания — появляется импульс (устанавливается логическая единица). В инверсном режиме, соответственно — наоборот. Недостатком данного режима является уменьшенная в два раза частота выходного сигнала по сравнению с режимом Fast PWM. Но зато при изменении скважности не смещаются центры импульсов. Основное назначение данного режима — делать многофазные ШИМ сигналы, например трехфазную синусоиду, чтобы при изменении скважности не сбивался угол фазового сдвига между двумя ШИМ сигналами.

Чтобы увидеть наглядно, как работает ШИМ, напишем небольшую программу (все опыты я провожу на своей отладочной плате, соответственно код привожу применительно к ней):

Тут мы видим, что при старте МК в регистры сравнения A и B устанавливается 0, а счётчик запускается в режиме Fast PWM, с генерацией неинверсного ШИМ сигнала на выходе OC0A и инверсного — на выходе OC0B. В основном цикле значения регистров сравнения плавно меняются от 0 до максимума и обратно. В результате, светодиоды, подключенные к выводам OC0A и OC0B, будут поочерёдно плавно загораться и гаснуть, как бы в противофазе.
Но если приглядеться внимательнее, то видим, что один из светодиодов гаснет не до конца, а продолжает тускло светиться. Эта особенность характерна для Fast PWM режима. Дело в том, что в этом режиме, даже если записать в регистр сравнения 0, при обнулении счётчика на выходе всё равно устанавливается логическая единица, которая сбрасывается в следующем такте (по совпадению с регистром сравнения). Таким образом, в каждом периоде будет проскакивать по одному короткому импульсу длительностью 1 такт, но этого достаточно для засвечивания светодиода. Этот эффект отсутствует в инверсном режиме формирования выходных импульсов, т.к. в данном случае при обнулении счётчика будет происходить не короткий импульс, а наоборот — короткий провал во время максимального заполнения ШИМ. Этот провал можно увидеть на осциллографе, но такое мерцание светодиода человеческое зрение просто не заметит. Поэтому второй светодиод загорается и гаснет полностью. В режиме ШИМ с коррекцией фазы, этот эффект отсутствует независимо, инверсный сигнал формируется на выходе или нет. Поменяем значение бита WGM01 (1) регистра TCCR0A с 1 на 0:

После перепрошивки МК можем убедиться, что оба светодиода гаснут полностью!
Эту особенность следует учитывать при разработке реальных проектов. Например, если мы захотим сделать регулятор яркости светодиодной подсветки, не следут использовать для этого ШИМ в режиме Fast PWM с неинверсной генерацией выходных импульсов.