Программная реализация нескольких каналов ШИМ на микроконтроллере. Теория. Генерация аналоговых сигналов микроконтроллером. Ч1

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

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

Таким образом, для одного канала ШИМ нам нужно знать правила, которыми определяется коэффициент заполнения (с этим проблем нет, мы их сами устанавливаем), и, кроме того, отсчитывать два момента времени от начала импульса: во-первых, сколько сигнал находится в состоянии высокого уровня и во-вторых, общее время импульса. Отлично, значит всё, что нам нужно для реализации одного ШИМ — это два счётчика. Алгоритм получится такой: запускаем оба счётчика, переключаем выход в "1". По прерыванию от первого счётчика (время высокого уровня) переключаем выход в "0", выключаем счётчик и ждём прерывание от второго счётчика. По прерыванию от второго счётчика (общее время импульса) — повторяем всё с начала.

Соответственно, для трёх каналов ШИМ нам нужно 3*2=6 счётчиков. Но, допустим у PIC12F629, есть только 2 счётчика, что же делать? Во-первых, сделаем одинаковым общее время импульса для всех каналов ШИМ (пусть все три канала работают с одной частотой), это уже минус два счётчика. Осталось только отсчитывать время высокого уровня для каждого из каналов ШИМ. Итого, осталось 4 счётчика. Не намного, но легче.

Теперь давайте вспомним, что контроллер, это не аналоговая микросхема, а цифровая, и моменты времени он отсчитывает дискретно. Все три времени высокого уровня (для каждого из каналов ШИМ) будут кратны какому-то общему кванту времени. Длительность этого кванта определяется разрядностью ШИМ и частотой импульсов. В случае, когда все каналы работают на одной частоте и имеют одинаковую разрядность, этот квант времени будет равен: T 1 =1/(f*(2 n -1)) , где n-разрядность ШИМ, f — частота импульсов.

Если ШИМ 8-ми битный и работает на частоте 100 Гц, то длительность кванта равна (1/100)/(2 8 -1)=39 мкс — общее время импульса (1/f), делённое на число возможных моментов переключения (2 n) минус 1 (если на прямой поставить N точек, то они образуют N-1 интервалов).

То есть, нам достаточно одного аппаратного счётчика, который будет отсчитывать интервалы T 1 . Далее, создаем программный счётчик, который будет подсчитывать количество таких интервалов, и задаём четыре уставки. Одна уставка определяет, — сколько нужно отсчётов программного счётчика чтобы отсчитать время высокого уровня для первого канала ШИМ, вторая — тоже самое для второго канала, третья — для третьего, четвертая соответствует общему времени импульса, а операции сравнения, переключения, увеличения или обнуления программного счётчика будем
делать по прерыванию от аппаратного счётчика.

Основной недостаток такого метода в том, что вместо (n+1) прерываний за период, мы будем обрабатывать (2 n -1) прерываний.

Давайте прикинем, какой может быть максимальная частота ШИМ при такой реализации? Очевидно, что при максимальной частоте, времени у контроллера хватает только на обработку прерывания. То есть, весь квант времени Т 1 контроллер занят обработкой прерывания, как только он выходит из прерывания — тут же происходит ещё одно.

Если обозначить максимальное число машинных циклов, за которое выполняется подпрограмма, N max — то, с учётом выражения для T 1 , получаем уравнение: N max *4/fosc=1/(f max *(2 n -1)) . Отсюда, максимальная частота ШИМ: f max =fosc/(4*N max *(2 n -1)) . Естественно, полученная формула просто оценочная, потому что мы допускали, что подпрограмма занимает всё время T 1 , но если после выполнения подпрограммы останется время для выполнения 2-х, 3-х команд, то это в общем-то тоже не сильно нас устроит. Что можно сделать в 3 команды? По нормальному, если мы хотим ещё что-то делать, например, обмениваться инфой с компом, то подсчитанное значение частоты нужно поделить ещё минимум вдвое.

От чего зависит максимальное время выполнения подпрограммы прерывания? Ну, во-первых конечно, от степени криворукости программиста, и во-вторых — от количества каналов ШИМ, которые мы хотим реализовать.

Для того, чтобы было понятно, о каких величинах идёт речь, рассчитаем конкретный пример: пусть контроллер работает на частоте fosc=4 МГц, мы написали подпрограмму, которая выполняется максимум за 40 машинных циклов и хотим получить разрядность ШИМ 8 бит. Тогда максимальная частота ШИМ будет равна 4000000/(4*40*255)=98 Гц. Как видите, при таком способе реализации, всё достаточно ограничено, но для RGB хватит. Между прочим, при 8-ми битах на цвет мы получим общее количество цветов, равное 2 8 *2 8 *2 8 =16 млн и вообще стоит подумать — надо ли нам столько?

При разрядности 2 бита на канал и той же тактовой частоте можно получить максимальную частоту ШИМ, равную 4000000/(4*40*3)=8,3 кГц, при этом будет 2 2 *2 2 *2 2 =64 различных сочетания коэффициентов заполнения (в случае с RGB это 64 цвета). Такую частоту уже можно юзать не только для RGB.

Ну вот, на этом с теорией всё.

Мы затронули тему использования счётчика/таймера 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 ).

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

  • 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 ).

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

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

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

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

Отличительные особенности:

  • Генерация аналоговых сигналов с помощью ШИМ
  • Высокочастотная масштабируемая синхронизация ШИМ

Введение

Данные "Рекомендации…" являются руководством по использованию высокочастотного широтно-импульсного модулятора (ШИМ), который присутствует в некоторых микроконтроллерах AVR. В состав "Рекомендаций…" входит пример ассемблерного кода, который демонстрирует, как использовать высокочастотный ШИМ микроконтроллера ATtiny26. Таймер с высокочастотным ШИМ также имеется в ATtiny15.

Для генерации импульсов используется режим быстрой ШИМ с переменным заполнением импульсов на выходе OC1A (PB1). Для получения из цифрового ШИМ-сигнала сигнала синусоидальной формы на выходе должен быть предусмотрен аналоговый фильтр.

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

1. Принцип действия

ШИМ в сочетания с аналоговым фильтром может использоваться для генерации аналоговых выходных сигналов, т.е. в качестве цифро-аналогового преобразователя (ЦАП). В качестве основы используется последовательность прямоугольных импульсов с постоянным периодом следования (фиксированная частота преобразования). Для генерации различных аналоговых уровней регулируется заполнение импульсов и, таким образом, изменяется длительность импульсов. Если необходимо сформировать высокий аналоговый уровень, то длительность импульса увеличивают и наоборот.

Усреднение аналогового сигнала за один период (с помощью аналогового фильтра) позволяет сгенерировать аналоговый сигнал. При заполнении импульсов 50% аналоговый сигнал равен половине напряжения питания, а при 75%-ом заполнении импульсов - аналоговый сигнал равен 75% от напряжения питания. Примеры фильтрации выходных сигналов показаны в конце данного документа.

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

Рисунок 1. Низкочастотный RC-фильтр

Если аналоговый сигнал поступает к низкоомному входу, то между выходом фильтра и нагрузкой должен быть включен буферный усилитель. Это предотвращает нагружение конденсатора и появление пульсирующего напряжения.

На рисунке 2 показана реальная осциллограмма ШИМ-сигнала с переменным заполнением импульсов.


Рисунок 2. ШИМ-сигнал с переменным заполнением импульсов

В микроконтроллерах AVR для генерации ШИМ-сигналов используются таймеры-счетчики. Для изменения несущей частоты ШИМ изменяется частота синхронизации таймера и вершина счета. Повышение частоты синхронизации и/или снижение вершины счета приводят к повышению частоты переполнения таймера и, как следствие, увеличивается частота ШИМ. Максимальной разрешающей способности (вершина счета 255) соответствует максимальная частота ШИМ 250 кГц. Дальнейшее увеличение частоты ШИМ возможно путем уменьшения разрешающей способности, но в этом случае сокращается количество шагов при установке заполнения импульсов от 0 до 100%.

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


Рисунок 3. Значения счетчика и ШИМ-выход

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

2. Альтернативные области применения

Высокоскоростной таймер может также использоваться для генерации высокочастотных цифровых сигналов, которые в свою очередь используются для синхронизации других цифровых каскадов. При установке очень малой вершины счета можно генерировать сигналы с очень высокой частотой.

Максимальная тактовая частота таймера микроконтроллера ATtiny26 равна 64 МГц (без предварительного деления). При частоте ШИМ 16 МГц (вершина счета 3) в регистр OCR можно записать значение 0, 1 (заполнение 25%), 2 (заполнение 50%, рисунок 4а) или 3 (заполнение 100%). Этим показывается, что снижением вершины счета увеличивается несущая частота ШИМ.

Для достижения максимальной выходной частоты от таймера его необходимо перевести в режим без ШИМ. Вершина счета и содержимое OCR должны быть равны 0. Счетчик в этом случае зависает на 0. Установка действия по совпадению равным "toggle output" (инвертирование выхода) приводит к инвертированию (переключению) выхода каждый такт таймера. В результате достигается частота 32 МГц (рисунок 4б).


Рисунок 4. Высокочастотный цифровой выход

3. Пример применения

Рисунок 4 иллюстрирует, как генерировать синусоидальный сигнал из высокочастотного ШИМ-сигнала.

Программный код состоит из 3 частей: инициализация, процедура обработка прерывания по переполнению таймера 1 и цикл в режиме сна. В данном примере полагается, что микроконтроллер работает на тактовой частоте 8 МГц.


Рисунок 5. Блок-схема основного цикла программы генерации синусоидального сигнала

3.1. Инициализация

Выход компаратора таймера 1 (OC1A) необходимо настроить на вывод.

Далее выполняется установка таймера 1: подготавливается тактовый источник таймера - запускается схема ФАПЧ, которая должна войти в синхронизм (захват) с системной частотой синхронизации. ФАПЧ требует порядка 100 мс для захвата с системной синхронизацией и, поэтому, перед выполнением последующих действий необходимо подождать установку флага захвата ФАПЧ. Как только ФАПЧ захватывается его необходимо выбрать в качестве тактового источника таймера.

Далее выбирается режим ШИМ с инвертированием вывода OC1A по совпадению и устанавливается вершина счета равной 0xFF. Значение вершины счета определяет разрешающую способность и несущую частоту ШИМ- чем выше значение вершины, тем выше разрешающая способность и ниже несущая частота.

Теперь таймер готов к запуску: установка предделителя приводит к запуску таймера. В завершении разрешается прерывание по переполнению таймера.


Рисунок 6. Процедура инициализации (инициализирует вывод и таймер 1 для работы в режиме быстрой ШИМ)

3.2. Процедура обработки прерывания

Когда таймер 1 достигает значения из OCR1C (0xFF) вызывается процедура обработки прерывания по переполнению таймера. Поскольку значение OCR1C - константа, то и данное событие возникает с постоянной периодичностью. Данный период определяет несущую частоту выходного ШИМ-сигнала.

В процедуре обработки прерывания реализована таблица для генерации синусоидального сигнала. При каждом входе в процедуру увеличивается указатель для доступа к таблице, чтобы всякий раз загружались новые значения. Значение, считанное из таблицы, записывается в регистр OCR1A. Таким образом, генерируемая последовательность импульсов может быть преобразована в синусоидальный сигнал. Обратите внимание, что регистр OCR1A буферизован и что перезапись из буферного регистра в действительный регистр OCR1A происходит при переполнении таймера.

Для выполнения процедуры обработки прерывания необходимо 13 тактов. На вызов процедуры и возврат из нее также затрачивается время - всего потребуется 21 такт. Поскольку таймер 1 является 8-разрядным, то прерывание возникает каждые 256/(Частота_ШИМ/Системная_частота) тактов. В данном примере полагается тактирование внутренним RC-генератором частотой 8 МГц. Если используется максимальная тактовая частота ШИМ 64 МГц, то переполнение таймера возникает каждые 32 системных такта.

Несмотря на возможность тактироваться максимальной частотой 64МГц, в данном примере частота синхронизации таймера принята 4…16 МГц, чтобы дополнительно продемонстрировать работу с предварительным делителем.


Рисунок 7. Блок-схема процедура обработки прерывания по переполнению таймера

3.3. Холостой ход

В процессе ожидания возникновения прерывания микроконтроллер переводится в экономичный режим сна "Холостой ход" (Idle). По завершении обработки прерывания микроконтроллер возвращается в режим сна.

4. Осциллограммы

На следующих рисунках приведены осциллограммы генерации синусоидальных сигналов с помощью микроконтроллера ATtiny26. На осциллограммах представлены два сигнала: цифровой сигнал с выхода OC1A и обработанный/фильтрованный ШИМ-сигнал. Для формирования аналогового синусоидального сигнала использовался простой RC-фильтр с параметрами R = 10 кОм и C = 100 нФ, которым соответствует настроечная частота фильтра 1 кГц. Таким образом, синусоида пропускается, а высокочастотная несущая частота подавляется.


Рисунок 8. Фильтрованный и нефильтрованный выход OC1A


Рисунок 9. Фильтрованный и нефильтрованный выход OC1A (с большим масштабом)

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

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

Для начала вспомним, что такое ШИМ. ШИМ сигнал - это импульсный сигнал определенной частоты и скважности:

Частота, это количество периодов за одну секунду. Скважность- отношение длительности импульса к длительности периода. Можно изменять и то и другое, но для управления светодиодами достаточно управлять скважностью. На картинке выше мы видим ШИМ сигнал со скважностью 50 %, так как длительность импульса (ширина импульса) ровно половина от периода. Соответственно светодиод будет ровно половину времени во включенном состоянии и половину в выключенном. Частота ШИМ очень большая и глаз не заметит мерцания светодиода из за инерционности нашего зрения, поэтому нам будет казаться, что светодиод светится на половину яркости. Если мы изменим скважность на 75%, то яркость светодиода будет на 3 четверти от полной, а график будет выглядеть так:

Получается, что мы можем регулировать яркость светодиода от 0 до 100 %. А теперь поговорим о таком параметре ШИМ, как разрешение. Разрешение- это количество градаций (шагов) регулировки скважности, мы будем рассматривать разрешение в 256 шагов.

С параметрами вроде разобрались, теперь поговорим о том, как нам получить этот самый ШИМ от микроконтроллера. Берем остро заточенный разогретый паяльник и начинаем пытать МК, одновременно подцепившись к двум его ногам осциллографом и проверяя наличие на них сигнала нужной нам скважности. В микроконтроллерах есть аппаратная поддержка ШИМ и несколько каналов для него, в нашем случае 3. За выдачу ШИМ отвечают определенные выводы МК, в нашем случае OC2, OC1A, OC1B (15,16,17 нога в DIP корпусе). Так же для этого используются таймеры микроконтроллера, в нашем случае TC1, TC2. Так как же сконфигурировать МК для выдачи сигнала необходимой скважности? Все очень просто, для начала сконфигурируем нужные нам ноги на выход:

PORTB=0x00; DDRB=0x0E; // 0b00001110

Далее начнем конфигурировать таймеры. Для таймера TC1 нам потребуются два регистра: TCCR1A и TCCR1B. Открываем даташит и читаем как настраиваются эти регистры. Я настроил его на 8 битный сигнал ШИМ, что соответствует разрешению в 256 шагов:

TCCR1A=0xA1; TCCR1B=0x09;

Для таймера TC2 мы будем использовать регистр TCCR2=0x69;. Его настройка выглядит так:

TCCR2=0x69;

Всё, таймеры сконфигурированы. Скважность будем задавать регистрами OCR1A,OCR1B, OCR2:

Зададим требуемые скважности:

OCR1A=0x32; //50 шагов OCR1B=0x6A; //106 шагов OCR2=0xF0; //240 шагов

Ну и поместим инкремент и декремент этих регистров в бесконечный цикл:

While(1) { OCR1A++; OCR1B--; OCR2++; delay_ms(50); }

Первая тестовая программа готова и выглядит для CVAVR она так:

#include "mega8.h" #include "delay.h" void main(void) { PORTB=0x00; DDRB=0x0E; // 0b00001110 TCCR1A=0xA1; TCCR1B=0x09; TCCR2=0x69; OCR1A=0x32; //50 шагов OCR1B=0x6A; //106 шагов OCR2=0xF0; //240 шагов while (1) { OCR1A++; OCR1B--; OCR2++; delay_ms(50); }; }

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

ШИМ (PWM) используется в транзисторной схеме для регулирования напряжения без механики, в свою очередь управление мощностью. Например управление яркостью светодиодов, управление яркостью подсветки на LCD-мониторе, управление двигателями и т.д. Если отобразить на рисунке, то выход с микроконтроллера примерно будет следующим, как на картинке ниже. Где видно что скважность это заполнение импульса, если вся ширина импульса это 5 В, то при 30% заполнении импульса, в среднем на выходе мы получим примерно 1,5В. В микроконтроллерах AVR ШИМ управление задается в восьмиразрядных таймерах/счетчиках T0/(T2) и шестнадцатиразрядный T1 (T3 в некоторых моделях). А также есть другие модели где битность ШИМа можно задавать, например ATmega 128. Рассмотрим настройку шестнадцатиразрядного таймера/счетчика Т1. Данные берем соответственно таблицам либо из справочника, либо из даташита (литература — статья №1).

В общем для такого счетчика в мк можно выбрать три режима: Fast PWM, Phase Correct PWM, Phase and Frequency Correct PWM (зависит от модели )

Рассмотрим второй режим - ШИМ с точной фазой . Здесь счетный регистр функционирует как реверсивный счетчик, изменения состояния которого изменяется от $0000 до максимального значения а затем обратно до $0000. Для управления таймером/счетчиком используем три регистра управления TCCR1A, TCCR1B, TCCR1C. В которых для выбора режима таймера/счетчика необходимо установить разряды WGMn1: WGMn0 и WGMn1: WGMn0. В зависимости от их установки максимальное значение счетчика(Разрешение ШИМ сигнала) является либо фиксированным значением, либо определяется содержимым определенных регистров таймера/счетчика. Разрешающая способность определяется выражением:

g = log (TOP+1)/log2, где ТОР – модуль счета, выбирается из таблицы соответственно разрешающей способности.

После того как определились с режимом работы таймера счетчика, необходимо выбрать режим работы блока сравнения COMnA1:COMnA0, COMnB1:COMnB0, COMnC1:COMnC0, который определяет поведение вывода OCnx при наступлении события “Совпадение”.

Ну и последний штрих определимся с частотой. Нам необходимо выставить разряды CSn2…CSn0 регистра TCCR1B, которые отвечают за определение источника тактового сигнала. Вот таким программным образом выглядит настройка ШИМ-управления на выходе OC1A. Например:

/*Настройки ШИМ */
TCCR1A=(1< /*На выводе OC1A единица, когда OCR1A==TCNT1, Сбрасывается в 0 при OCR1A==TCNT1 и устанавливается в 1 при достижении максимального значения восьми битный ШИМ Phase Correct PWM , номер режима 1 . модуль счета ТОР $00FF*/
TCCR1B=(1<OCR1A = 50; /* при модуле счета 255 и при напряжении 5 В на выходе OC1A получим примерно 1 В*/

Из программы видно, что для получения ШИМ используем регистр сравнения OCR1A. При достижении счетчиком максимального значения, в данном случае 255, происходит смена направления счета, но счетчик остается в этом состоянии в течении одного периода сигнала. В этом и заключается более медленная частота работы по сравнению с первым режимом. Но в этом и состоит симметричность изменения счетчика. Что более подходит для управления двигателем. В этом же такте происходит обновления содержимого регистра сравнения. При достижении счетчиком минимального значения также происходит смена направления счета и одновременно устанавливается флаг прерывания TOV1 регистра TIFR. Пр равенстве содержимого счетного регистра и какого-либо регистра сравнения устанавливается соответствующий флаг OCF1A/OCF1B/OCF1C регистра TIFR. Одновременно изменяется состояние выхода блока сравнения OCnx. Частота генерируемого сигнала fOCn= f/(2*N*TOP), где N – коэффициент деления пред делителя, f — частота кварца. Также можно посмотреть еще примеры настройки и использования ШИМ, например .

На этом сегодня все. В следующем посте рассмотрим контроллер любительского станка ЧПУ . Я постараюсь использовать предыдущие посты из этого блога для набора программы, как конструктор. Так будет более понятно когда один раз написали и его использовали в следующем проекте. Всем пока.




Top