Урок 13
Часть 1
ШИМ. Мигаем светодиодом плавно
Сегодня мы изучим возможность использования широтно-импульсной модуляции в микроконтроллере AVR, или, как говорят в народе, ШИМ.
В технической документации мы будем видеть чаще аббревиатуру PWM или pulse-width modulation, что преводится имено также.
Что же такое вообще широтно-импульсная модуляция.
ШИМ — это управление свечением светодиодов, вращением двигателей, и прочими устройствами необычным способом, при котором данное управление осуществляется не приложенным напряжением к контактам, а квадратными импульсами. При этом напряжение будет только двух видов — высокое (1) и низкое (0). При данном способе результирующее напряжение вычисляется как среднее по времени между временем высокого состояния в одном импульсе и временем низкого состояния. Мы вычисляем отношение времени (или широты) высокого состояния к общему периоду импульса. Называем мы это скважностью импульса. То есть чем больше в периоде напряжение находилось в высоком состоянии, тем больше скважность, а, следовательно, тем больше и результирующее среднее напряжение. То есть, чтобы найти результирующее напряжение, нам необходимо и достаточно вычисленную скважность умножить на напряжение и разделить на 100, так как скважность как правило измеряется в процентах. Например, если у нас в квадратном импульсе широта логического нуля равна широте логической единицы, то скважность у нас будет 50 процентов, и, если напряжение будет 5 вольт, то среднее результирующее напряжение мы получим равное 2,5 вольт и т.д. Лучшую картину объяснения данной ситуации мы можем увидеть, посмотрев видеоурок, ссылка на который дана в конце данной статьи.
Это конечно очень упрощённое понятие ШИМ. Есть более серьёзные разъяснение данной технологии, но нам для наших экспериментов этого будет вполне достаточно.
То есть, подведя итоги объяснению, мы управляем результирующим напряжением, а также и свечением светодиода, угловой скоростью электродвигателя и прочими значениями за счёт изменения скважности импульсов.
Но всё-таки самое интересное, как же всё-таки всё это организовано в нашем микроконтроллере?
В микроконтроллере AVR широтно-импульсную модуляцию можно организовать как программно, так и аппаратно.
Программная организация ШИМ — это когда мы включим на определённое время на ножке контроллера логическую единицу, а затем на определённое время — логический ноль и так по циклу. Плюсы данного способа — это то, что мы можем организовать ШИМ на абсолютно любой ножке любого порта контроллера, а минусом — то, что всё это будет связано с немалыми затратами на процессорное время, и возможно даже будет сопряжено с какими-то ошибками, вытекающими из этого.
Поэтому всегда в любой технологии мы стараемся придерживаться всё-таки именно аппаратного способа реализации.
Аппаратная организация ШИМ в МК AVR происходит на уровне таймера 2.
Как мы помним из предыдущего занятия, таймеров в конкретном нашем микроконтроллере Atmega8 три. И таймеры 0 и 2 являются восьмибитными. Но на уровне 2-го таймера как раз и организована широтно-импульсная модуляция.
Давайте посмотрим вот такую вот картину
Здесь иллюстрируется то, какие мы должны включить биты в регистре TCCR второго таймера, чтобы запустить широтно-импульсную модуляцию.
Биты WGM как раз и включают таймер в резим PWM (ШИМ). С остальными битами разберёмся позже, если это потребуется.
А сейчас, чтобы это всё прочувствовать, нам необходим проект, который мы и создадим сейчас.
Проект создаем таким же образом, как и на прошлых занятиях. Назовём его Test10, создадим и добавим файлы PWM.c и PWM.h, последний автоматически оформится при создании соответствующими директивами прероцессора. А в главном файле Test01.c мы напишем стандартный код
#include «main.h»
//—————————————-
void port_ini(void)
{
PORTB=0x00;
DDRB=0x08;
}
//—————————————-
int main(void)
{
port_ini();
while(1)
{
}
}
Как мы видим в коде, в порте B мы включили на выход 3 ножку. В распиновке контроллера мы видим, что у данной ножки есть ещё альтернативное обозначение OC2, которое и означает возможность этой ножки работать непосредственно с ШИМ
Файл main.h мы можем даже подключить с прошлого занятия по LCD и немного исправим код, подключив туда уже новый наш модуль PWM
#ifndef MAIN_H_
#define MAIN_H_
#define F_CPU 8000000UL
#include <avr/io.h>
#include <avr/interrupt.h>
#include <util/delay.h>
#include <stdio.h>
#include <stdlib.h>
#include «PWM.h»
#endif /* MAIN_H_ */
Ну и теперь начнём писать код в новую библиотеку для работы непосредственно с ШИМ — в файл PWM.c.
Там мы также подключим заголовочный файл и создадим каркас функции для работы с ШИМ
#include «PWM.h»
void init_PWM_timer(void)
{
}
А в заголовочный файл нашей библиотеки мы добавим прототип данной функции, а также подключим библиотеку для работы с прерываниями
#ifndef PWM_H_
#define PWM_H_
#include <avr/interrupt.h>
void init_PWM_timer(void);
#endif /* PWM_H_ */
И вызовем сразу эту функцию в main()
port_ini();
init_PWM_timer();
Начнём теперь писать код непосредственно в функцию. Сначала запишем все нули в регистр ASSR, который существует у таймера, но мы его никак не используем
void init_PWM_timer(void)
{
ASSR=0x00;
Дальше уже займёмся управляющим регистром нашего таймера. Назначение битов WGM и то, какие именно из них мы включим, мы разобрали. Теперь биты COM20 и COM21, отвечающие за режим самого ШИМ. Мы выберем вот такой режим и соответственно ему и включим данные биты
А включим мы режим, при котором при начале счёта напряжение на ножке OC2 будет находиться в высоком логическом состоянии, а как только мы досчитаем до определённой цифры, то ножка перейдёт в низкое состояние и будет в нём находиться до окончания счёта. И так по кругу.
И останется нам только настроить делитель. Слишком большая частота нам не нужна. Но когда была слишком маленькая, также было заметно мерцание, поэтому давайте включим следующую величину
Поэтому мы включим все три бита.
В итоге значение регистра станет вот таким
ASSR=0x00;
TCCR2=0b01101110; //Fast PWM, Clear OC2 on Compare Match, clkT2S/256 (From prescaler) (реальная частота получится 8мгц/256 = 31250 гц)
Теперь попробуем собрать проект. Проект нормально собрался. В следующей части мы продолжим работать с ШИМ.
Предыдущий урок Программирование МК AVR Следующая часть
Купить программатор можно здесь (продавец надёжный) USBASP USBISP 2.0
Смотреть ВИДЕОУРОК (нажмите на картинку)
эта команда TCCR2=0b01101110; из этой TCCR2|=(1<<CS22)|(1<<CS21); ???
Спасибо Вам за труды! Это самые доступные в понимании и освоении уроки.
У меня ничего не работало, пока не исправил main.h — #include «PWM.c»
Раньше Cube не создавал самостоятельно не создавались, теперь создаются и файлы, которые создавались в более ранних проектах, портятся. Так что косяк не мой. Я не мог предупредить об этом. Об этом никто не знал. Как только такое появилось, я в нескольких уроках объяснял, как это исправляется.
Здраствуйте. Прошел Ваш урок по ШИМ, очень познавательно спасибо большое!
И у меня возник вопрос, возможно ли лавно изменять не только скважность ШИМ, а и период, или при апаратном таймере возможно регулировать период только делителем ?
Просто я когда делал проект в FLprog (это FBD генератор кода для ардуино) там с помощью готового блока у меня получалось сделать плавную регулировку. Это очень критично при реализации плавной регулировки скорости (с помощью твердотельного реле) вентилятора (улитки) на 220В.
Тоесть я увеличивал период паузы и уменьшал скважность, а при средних скоростях я увеличивал скважность и уменьшал период.
Здравствуйте.
Я как-то на этот счёт не заморачивался.
Но скорей всего можно. Но если у таймера, используемого с ШИМ, есть возможность плавно менять период, то менять его можно.
Конечно, не все таймеры умеют это.
Период это и есть частота на которой работает ШИМ и она ПОСТОЯННАЯ и плавно не меняется.
Вы ещё напишите возможно ли заставить микроконтроллер работать сначала на частоте 1 мегагерц а потом её плавно увеличивать до 8, а потом снова уменьшать до 1 мегагерца. Такое не возможно!
Добрый день. Скважность в аппаратном ШИМ регулировать возможно, но для этого необходима более тонкая настройка управляющих регистров таймера. Дело в том что существуют несколько режимов работы ШИМ. А для регулировки периода необходимо выбрать соответствующий режим. Выдержка из описания Atmega328P:
В режиме Clear Timer on Compare или CTC регистр OCR0A используется для управления разрешением счетчика: счетчик очищается до ноля, когда значение счетчика (TCNT0) соответствует OCR0A. OCR0A определяет верхнее значение для счетчика, а значит и его разрешение. Этот режим позволяет контролировать выходную частоту ШИМ.
Здраствуйте приведите пожалуйста пример как сделать так чтобы на соседней ножке того же порта загорался светодиод но с задержкой в половину длины импульса
Цитата — «Мы вычисляем отношение времени (или широты) высокого состояния к общему периоду импульса. Называем мы это скважностью импульса.»
По определению это Коэффициент заполнения.
«То есть, чтобы найти результирующее напряжение, нам необходимо и достаточно вычисленную скважность умножить на напряжение и разделить на 100, так как скважность как правило измеряется в процентах»
Разве среднеквадратичекое значение не равно Urms = Uamp*корень(Ti/T)? Поясните, пожалуйста
Среднеквадратичное значение — для вычисления теплового действия переменного электрического тока; а среднее за период значение переменного тока — эквивалентное ему значение постоянного тока за то же время (импульс прямоугольной формы заменяется на постоянный ток; площадь прямоугольного импульса равняется при этом площади прямоугольника между линией постоянного тока и осью времени).