Использование ШИМ функции таймеров AVR микроконтроллеров
Пример реализации широтно-импульсной модуляции на МК Atmega8. Плавно меняем скважность выходных импульсов.
Давайте будем считать, что предыдущую страницу мы расшифровали, основные регистры счётчиков, встроенных в микроконтроллер, идентифицировали –
пришло время для совместных действий и практической реализации полученных знаний.
И начнём мы с такой распространённый функции МК, как широтно-импульсная модуляция (ШИМ), тем более что, как мы помним, данная функция
является штатной для всех таймеров-счётчиков AVR микроконтроллеров.
Не вдаваясь в подробности: широтно-импульсная модуляция (ШИМ) – это способ управления уровнем мощности, подводимой к нагрузке, посредством
изменения скважности управляющего импульса.
А скважность – это безразмерная величина, равная отношению периода импульса к его длительности, то есть:
S = T/ t
Начнём с рисунка, который демонстрирует работу нашего подопытного микроконтроллера Atmega8 в программе симуляции работы МК
– Proteus (Рис.1).

Рис.1 Пример реализации широтно-импульсной модуляции на МК Atmega8
Ну что ж, пришло время Atmel Studio и программы прошивки, которую мы по традиции будем писать на языке СИ. Озвучим поэтапно каждый
оператор программы прошивки.
Для начала – всё стандартно и аналогично предыдущим проектам:
#include <avr/io.h>
#define F_CPU 8000000UL // На этот раз выбираем частоту МК 8 МГц
#include <util/delay.h> // Включаем функцию задержек
int main(void)
{
// Начало основной программы
В качестве шим-контроллера используем один из трёх таймеров-счётчиков Atmega8 – 8-битный таймер Т2. Тем более что именно его описание, а
также настройки регистров были выбраны в качестве примера и подробно рассмотрены на предыдущей странице.
Выходным пином для данного таймера-счётчика является вывод МК OC2, он же третий разряд порта В – PB3. Его надо обязательно назначить как
выход, ну и для блезиру назначить ему какое-нибудь значение:
DDRB |= ( 1 << 3 ); // Конфигурируем вывод порта PB3 как выход
PORTB &= ~(1 << PB3); // Устанавливаем 0 на его выходе
Теперь надо инициировать таймер-счётчик Т2 посредством настройки его регистров:
TCCR2=0b01101001;
/* 1. Режим быстрой ШИМ (Fast PWM) (6 и 3 разряды TCCR2 – 1,1).
2. Регистр асинхронного состояния настроен на работу от внутреннего тактового
генератора, делитель частоты отключён – таймер тикает с тактовой частотой
(2,1,0 разряды TCCR2 – 0,0,1). Это означает, что частота ШИМ равна 8000000/256 =
31250Гц.
3. На выходе PB3 устанавливается "0" при совпадении TCNT2 и OCR2, и "1" при сбросе
счётчика (5,4 разряды TCCR2 – 1,0) */
OCR2=0x00;
/* Регистр сравнения. Зададим его начальное значение равным 0. Когда счётчик
досчитает до значения OCR2, напряжение на выходе PB3 изменится с 1 на 0 */
С описаниями регистров на этом закончим, так как все остальные их настройки, находящиеся в состоянии "по умолчанию", нас вполне
могут устроить.
А теперь давайте введём переменную, которую используем в ходе выполнения программы, и которая будет принимать всего два значения: либо +1,
либо -1, в зависимости от требуемого знака приращения скважности выходного сигнала:
short st = 1; // Объявляем переменную st и записываем в неё число 1
Теперь, когда все подготовительные работы у нас проведены, можно смело приступать к основной программе:
while (1)
{ // начало цикла
В принципе, всё необходимое программное воплощение функции ШИМ мы уже осуществили настройками регистров таймера-счётчика Т2.
Всё что теперь остаётся – это обеспечить постепенное наращивание содержимого регистра сравнения OCR2 (скважность будет уменьшаться),
а затем, когда она станет равной 0, обеспечить такое же постепенное снижение содержимого, пока скважность не примет максимальное
значение.
OCR2=OCR2+st; /* С каждым циклом прибавляем (или вычитаем) к содержимому регистра сравнения
единицу, тем самым уменьшая (увеличивая) скважность */
if (OCR2 > 254) st = -1 ; /* Как только счётчик досчитает до максимального значения 255,
поменяем знак st на минусовой
if (OCR2 < 1) st = 1 ; /* Как только счётчик опустится до нуля,
меняем минусовой знак st на плюсовой
_delay_ms(5); // Тормозим на 5мс начало выполнения следующего цикла
Всё, что теперь остаётся – это опять вернуться к началу цикла и продолжить выполнение программы:
} // конец цикла
} // конец программы
Теперь сгруппируем всё воедино и получим искомый код на языке Си:
#include <avr/io.h>
#define F_CPU 8000000UL // На этот раз выбираем частоту МК 8 МГц
#include <util/delay.h> // Включаем функцию задержек
int main(void)
{
// Начало основной программы
DDRB |= ( 1 << 3 ); // Конфигурируем вывод порта PB3 как выход
PORTB &= ~(1 << PB3); // Устанавливаем 0 на его выходе
TCCR2=0b01101001;
/* 1. Режим быстрой ШИМ (Fast PWM) (6 и 3 разряды TCCR2 – 1,1).
2. Регистр асинхронного состояния настроен на работу от внутреннего тактового
генератора, делитель частоты отключён – таймер тикает с тактовой частотой
(2,1,0 разряды TCCR2 – 0,0,1). Это означает, что частота ШИМ равна 8000000/256 =
31250Гц.
3. На выходе PB3 устанавливается "0" при совпадении TCNT2 и OCR2, и "1" при сбросе
счётчика (5,4 разряды TCCR2 – 1,0) */
OCR2=0x00;
/* Регистр сравнения. Зададим его начальное значение равным 0. Когда счётчик
досчитает до значения OCR2, напряжение на выходе PB3 изменится с 1 на 0 */
short st = 1; // Объявляем переменную st и записываем в неё число 1
while (1)
{ // начало цикла
OCR2=OCR2+st; /* С каждым циклом прибавляем (или вычитаем) к содержимому регистра сравнения
единицу, тем самым уменьшая (увеличивая) скважность */
if (OCR2 > 254) st = -1 ; /* Как только счётчик досчитает до максимального значения 255,
поменяем знак st на минусовой */
if (OCR2 < 1) st = 1 ; /* Как только счётчик опустится до нуля,
меняем минусовой знак st на плюсовой */
_delay_ms(5); // Тормозим на 5мс начало выполнения следующего цикла
} // конец цикла
} // конец программы
Теперь, так же как и в предыдущих примерах, нужно перенести готовый код в Atmel Studio и скомпилировать его. Для этого необходимо
кликнуть по кнопке Build и в выпавшем меню выбрать Build Solution.
Если ошибок нет, то файл успешно скомпилируется, а в нижней части экрана появится надпись:
==== Build: 1 succeeded or up-to-date, 0 failed, 0 skipped ====
Далее нам надо войти в папку, в которой мы сохранили наш проект, найти там ещё одну папку с названием Debug и убедиться в
существовании файла с расширением HEX.
При помощи этого файла может производиться как прошивка микроконтроллера, так и проверка его
работоспособности в программе для автоматизированного проектирования Proteus.
При работе в Протеусе важно в свойствах ATMEGA8 в графе CKSEL Fuses: задать "Int. RC 8MHz". В противном случае моделирование будет
проводиться из расчёта тактовой частоты МК 1МГц.
Скачать файл shim.hex можно по ссылке – скачать файл
|