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. Но зато при изменении скважности не смещаются центры импульсов. Основное назначение данного режима - делать многофазные ШИМ сигналы, например трехфазную синусоиду, чтобы при изменении скважности не сбивался угол фазового сдвига между двумя ШИМ сигналами.

ШИМ сигналы на выходе AVR микроконтроллера в режимах Fast PWM и Phase correct PWM
ШИМ сигналы на выходе AVR микроконтроллера в режимах Fast PWM и Phase correct PWM

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

/*
 * tiny13_board_pwm
 * Демо-прошивка отладочной платы на ATtiny13.
 * Демонстрация работы ШИМ на двух каналах:
 * неинверсный сигнал на выходе OC0A, инверсный - на выходе OC0B.
 */
 
#define F_CPU 1200000UL
#include <avr/io.h>
#include <util/delay.h>

#define LED0 PB0 // OC0A
#define LED1 PB1 // OC0B

int main(void)
{
  // Светидиоды:
  DDRB |= (1 << LED0)|(1 << LED1); // выходы = 1
  PORTB &= ~((1 << LED0)|(1 << LED1)); // по умолчанию отключены = 0
  // Таймер для ШИМ:
  TCCR0A = 0xB3; // режим ШИМ, неинверсный сигнал на выходе OC0A, инверсный - на выходе OC0B
  TCCR0B = 0x02; // предделитель тактовой частоты CLK/8
  TCNT0=0; // начальное значение счётчика
  OCR0A=0; // регистр совпадения A
  OCR0B=0; // регистр совпадения B
  
  while(1)
  {
    do // Нарастание яркости
    {
      OCR0A++;
      OCR0B = OCR0A;
      _delay_ms(5);
    }
    while(OCR0A!=255);
    _delay_ms(1000); // Пауза 1 сек.
    do // Затухание
    {
      OCR0A--;
      OCR0B = OCR0A;
      _delay_ms(5);
    }
    while(OCR0A!=0);
    _delay_ms(1000); // Пауза 1 сек.
  }
}

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

TCCR0A = 0xB1; // режим ШИМ с коррецией фазы, неинверсный сигнал на выходе OC0A, инверсный - на выходе OC0B

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

Полезные ссылки:
ATtiny13 Datasheet (официальный)
ATtiny13 Datasheet (урезанный вариант)
AVR. Учебный курс. Использование ШИМ
Таймер/счетчик T0 (8 бит)

Теги : attiny13, AVR, ШИМ, PWM, fast PWM, phase correct PWM, микроконтроллеры, программирование, си, C

Комментариев: 4

Павел
#Ответить
Не понял.
TCCR0A = 0xB3; // режим ШИМ, неинверсный сигнал на выходе OC0A, инверсный - на выходе OC0B
0xB3=b10100011, т.е. регистры COM0A1 (7) и COM0A0 (6) и Биты COM0B1 (5) и COM0B0 (4) выставлены абсолютно симметрично. Откуда различия прямой и инверсной ШИМ?
Может вы имели ввиду TCCR0A = 0xC3 = b10110011;
Павел
#Ответить
Тут немного неточно сказано:
Дело в том, что в этом режиме, даже если записать в регистр сравнения 0, при обнулении счётчика на выходе всё равно устанавливается логическая единица, которая сбрасывается в следующем такте (по совпадению с регистром сравнения).

Логическая 1 выставляется ПРИ ПЕРЕПОЛНЕНИИ таймера, т.е. при переходе 255-0, а в следующем такте при совпадении с 0 OCR0A он сбросится на 0.
Павел
#Ответить
Кстати, вопрос, как лучше бороться с этим подсвечиванием при ненадобности ШИМ. Варианты:\

1. TIMSK0 = 0; // запрет всех прерываний по таймеру
2. TCCR0A &= ~((1<<COM0A1) | (1<<COM0A0));
3. TCCR0B &= ~((1 << CS02)|(1 << CS01)|(1 << CS00)); // делитель частоты таймер выключен
4. TCCR0A &= ~((1<<WGM01) | (1<<WGM00));
TCCR0B &= ~(1<<WGM02);
OSBoy
#Ответить
Павел, по-моему Вы что-то путаете:
B3 = 10110011
C3 = 11000011
Проверьте хотя бы виндовым калькулятором в режиме "программист"...

Добавить комментарий

Отменить