Программирование AVR Fast PWM на Arduino Leonardo Thu, March 28 2024  

Поделиться

Нашли опечатку?

Пожалуйста, сообщите об этом - просто выделите ошибочное слово или фразу и нажмите Shift Enter.

Fast PWM на Arduino Leonardo Печать
Добавил(а) microsin   

Платы Arduino предоставляют псвевдоаналоговые выходы с помощью функции analogWrite(). Эта функция доступна не для всех портов, а только для тех, которые помечены символом ~. Функция analogWrite не предоставляет реального аналогового выхода, вместо этого эмулируя аналоговый сигнал с помощью ШИМ (PWM).

Leonardo common view

Leonardo pinout

[Что такое ШИМ]

Сигнал широтно-импульсной модуляции ШИМ (английская аббревиатура PWM, обозначающая Pulse Width Modulation) это сигнал, состоящий из последовательности специально сформированного двоичного сигнала. Термин "двоичный" означает, что сигнал может иметь только два состояния "HIGH" (лог. 1) и "LOW" (лог. 0). Аналоговая информация передается не уровнями сигнала, а соотношением между лог. 1 и лог. 0 (скважностью) генерируемых импульсов.

Если устройство, подключенное к выводу импульсов ШИМ, имеем меньшую полосу передачи частот, чем частота ШИМ, то получается результат фильтра низких частот (ФНЧ), и тогда ШИМ передает усредненное значение, воспринимаемой устройством как аналоговый сигнал. Выводы PWM платы Arduino Leonardo используют частоты модуляции 488 Гц или 976 Гц. Когда Вы используете функцию analogWrite, нацеленную на управление светодиодом (LED). то у светодиода полоса частот включения и выключения обычно заведомо превышает 1 кГц. Однако наши глаза имеют максимально распознаваемую частоту пульсацию не выше 100 Гц. Так как полоса частот мерцаний LED значительно превышает полосу воспринимаемых частот для глаза человека, то мы видим только среднее значение импульсов PWM (среднюю яркость свечения), не замечая того факта, что светодиод полностью включается и выключается за короткие промежутки времени импульсов PWM.

Тот же самый принцип действует, когда мы используем сигнал PWM для управления мотором. Обычные моторы постоянного тока из-за своей инерции и индуктивности обмоток имеют полосу пропускания ниже полосы PWM программ Arduino, поэтому мотор работает от импульсов PWM так же, как если бы питался от постоянного напряжения. Фактически PWM даже на низких частотах позволяет улучшить работу мотора на низких скоростях.

В целом частоты PWM в диапазоне от 500 Гц до 1 кГц коробочного Arduino вполне адекватны для управления моторами. Однако если мы хотим генерировать звуковой сигнал, то функция analogWrite не будет работать. Люди слышат частоты в диапазоне до примерно 20 кГц, что намного выше, чем частота Arduino PWM. Обычные динамики, если на них подать сигнал PWM, будут выдавать слышимый тональный звук с частотой PWM.

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

[Возможности ШИМ плат Arduino Leonardo]

Давайте рассмотрим, как формируется ШИМ на платах Arduino Leonardo. Большинство плат Arduino генерирует сигналы ШИМ с помощью таймеров. Периферийное устройство таймера предоставляет аппаратную генерацию ШИМ, не вовлекающую вычисления CPU для непосредственного формирования импульсов ШИМ. Каждый таймер имеет ограниченное количество сигналов ШИМ, которые можно генерировать аппаратно.

Плата Arduino Leonardo использует микроконтроллер ATmega32U4. У него на кристалле имеется 4 таймера: Timer 0, Timer 1, Timer 3 и Timer 4. Таймеры 1 и 3 одинаковые, однако остальные таймеры несколько отличаются. Другие платы Arduino используют другие таймеры, которые есть в наличии у микроконтроллера, установленного на плате.

В следующей таблице показано использование таймеров для генерации ШИМ платой Arduino Leonardo.

Порт Arduino Таймер, канал Частота ШИМ, Гц Режим
3 Timer 0, B 976 Single Slope (Fast PWM)
5 Timer 3, A 488 Dual Slope (Phase Corrected)
6 Timer 4, D 488 Dual Slope (Phase Corrected)
9 Timer 1, A 488 Dual Slope (Phase Corrected)
10 Timer 1, B 488 Dual Slope (Phase Corrected)
11 Timer 0, A 976 Single Slope (Fast PWM)
13 Timer 4, A 488 Dual Slope (Phase Corrected)

Arduino использует таймеры и для других функций. Например, Timer 0 также используется для записи прошедшего времени, что необходимо для работы функций millis(), micros(), delay() и delayMicroseconds(). Не забывайте о том, что работа Timer 0 может нарушить все другие функции времени.

Некоторые библиотеки Arduino также используют таймеры. Библиотека Servo на плате Leonardo использует Timer 1, то время как библиотека MsTimer2 использует Timer 4. Вам следует знать требования используемых библиотек к таймерам, поскольку они могут повлиять на генерацию ШИМ, связанную с их таймером.

Есть два основных способа создать сигнал ШИМ с помощью таймера. Если нужны дополнительные подробности по устройству таймера 4, см. [2].

[Single Slope PWM]

Работа таймеров основана на счетчике. У счетчика есть тактовый вход, и с каждым активным перепадом уровня на этом входе счетчик меняет свое состояние. Самый типовой режим работы - увеличение значения счетчика на единицу с каждым активным тактовым перепадом, пока счетчик не достигнет максимального значения. Как только это максимальное значение достигнуто, счетчик возвращает свое значение к нулю, и процесс счета импульсов тактов повторяется. Это дает пилообразную диаграмму отображения значения счетчика, что показано на картинке ниже, так называемый односкатный ШИМ (Single Slope PWM). Один полный цикл пилы (зуб) требует Count Max + 1 тактовых импульсов (здесь Count Max это максимальное значение счетчика).

FastPWM Single Slope

Периферийное устройство таймера также включает в себя несколько регистров захвата/сравнения. Чтобы создать сигнал ШИМ, регистр сравнения связывается с аппаратным выходом микроконтроллера таким образом, что значение на этом выходе лог. 1, пока значение счетчика меньше или равно значению регистра сравнения. Это дает сигнал ШИМ для каждого регистра сравнения, где скважность сигнала ШИМ зависит от значения в регистре сравнения.

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

Функция Arduino analogWrite() работает с Timer 0 микроконтроллера ATmega32u4 по принципу одного наклона пилы (single slope). Используется тактовая частота 250 кГц, полученная делением на 64 системной тактовой частоты 16 МГц. В результате получается частота импульсов ШИМ 976 Гц.

У Timer 0 есть два канала сравнения A и B, связанные с двумя регистрами сравнения OCR0A и OCR0B. Эти два канала имеют два аппаратных выхода OC0A и OC0B, использующие выводы 11 и 3 платы Arduino.

[Dual Slope PWM]

Другой способ генерировать ШИМ состоит в конфигурации счетчика для счета вперед и назад. Счетчик увеличивается с каждым тактом, и когда достигнет максимального значения, начинает уменьшаться на каждом такте. Уменьшение происходит до момента достижения счетчиком нуля, после чего опять начинается счет на увеличение. Это дает треугольную форму диаграммы изменения состояния счетчика вместо пилообразной, получается так называемый двухскатный ШИМ (Dual Slope PWM).

CenteredPWM Dual Slope

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

Способ генерации ШИМ Dual Slope более точен, и поэтому лучше подходит для управления моторами. Однако его частота получается в 2 раза ниже, чем у Single Slope. В любом случае, частота ШИМ будет одинаковой у всех каналов сравнения, когда они используют один и тот же таймер.

Функция Arduino analogWrite() в режиме Dual Slope работает на микроконтроллере ATmega32U4 на таймерах 1, 3 и 4. Причина того, что Timer 0 не работает Dual Slope возможно в том, что Timer 0 используется для отслеживания реального времени, поэтому было бы сложно реализовать и на нем двухскатный принцип формирования ШИМ. В режиме двухскатного ШИМ все выводы, связанные с этим ШИМ, работают на половине частоты Timer 0, 488 Гц.

У Timer 1 есть три канала сравнения A, B и C, и соответствующие регистры сравнения OCR1A, OCR1B, OCR1C, связанные с входами OC1A, OC1B и OC1C. Программное обеспечение Arduino использует только каналы A и B, подключенные к портам Arduino 9 и 10. Канал C и его выход OC1C связан с тем же самым портом 11 Arduino, который управляется от Timer 0. По какой-то причине разработчики библиотек Arduino предпочли назначить управление выводом 11 через Timer 0 по принципу Single Slope вместо использования для этого порта Timer 1 в режиме Dual Slope.

Timer 3 имеет только один аппаратный выход OC3A на порту 5 Arduino, связанный с регистром сравнения OCR3A.

Timer 4 особенный, но в контексте ШИМ он работает в Dual Slope так же, как и таймеры 1 и 3. У Timer 4 есть аппаратные выходы OC4A, OC4B и OC4D, связанные с регистрами сравнения OCR4A, OCR4B и OCR4D. Библиотеки Arduino используют каналы A и D, связанные с выводами портов 13 и 6. Канал B связан с тем же самым портом, что и OC1B Timer 1. Разработчики Arduino выбрали управление этим выводом от Timer 1 вместо Timer 4.

Все это дает 7 выводов ШИМ, управляемых библиотеками Arduino.

[Fast PWM на Timer 1]

Если частоты 976 Гц, которую предлагает analogWrite из библиотек Arduino, недостаточно, то нам придется самостоятельно реализовать не низком уровне управление ШИМ. Timer 1 хороший кандидат, так как у него есть 3 канала сравнения, и он не будет пересекаться с функциями задержки Arduino. Следует иметь в виду, что библиотека Servo также использует Timer 1, поэтому при её использовании лучше выбрать другой таймер для ШИМ.

Timer 1 основан на 16-разрядном счетчике. Это означает, что он может считать от 0 до 65535 до возникновения переполнения. Этот таймер имеет несколько режимов работы, включая 12 режимов PWM. Самый быстрый PWM доступен в режиме Single Slope с разрядностью 8 бит, когда таймер считает от 0 до 255. Поскольку Single Slope быстрее, чем Dual Slope, этот режим также называется быстрым ШИМ (Fast PWM).

Вы также можете использовать режимы PWM разрядностью 9 и 10 бит (счет до 511 и до 1023 соответственно), которые могут работать в односкатном и двухскатном режимах. Три режима разрядности 8, 9 и 10 бит для Single Slope PWM и Single Slope PWM дают 6 режимов ШИМ. Еще 6 дополнительных режимов ШИМ дает программирование предельного счета до любого 16-разрядного значения, не ограничиваясь 255, 511 или 1023.

Таймер получает тактирование от глобального прескалера тактов микроконтроллера, что дает 5 вариантов частот тактирования, получаемых от системной частоты (у Arduino Leonardo это 16 МГц). Прескалер может делить системную частоту на 1 (т. е. нет деления), 8, 64, 256 и 1024. В таблице ниже показаны варианты частот тактирования и получающихся частот ШИМ для режима при использовании стандартных разрядностей 8, 9 и 10 бит:

Делитель 1 8 64 256 1024 Макс.
значение
счета
Частота тактов, Гц 16000000 2000000 250000 62500 15625
8 бит Fast PWM, Гц 62500 7812.5 976.6 244.1 61 256
9 бит Fast PWM, Гц 31250 3906.3 488.3 122.1 30.5 512
10 бит Fast PWM, Гц 15625 1953.1 244.1 61.0 15.3 1024
8 бит Dual Slope PWM, Гц 31250 3906.3 488.3 122.1 30.5 256
9 бит Dual Slope PWM, Гц 15625 1953.1 244.1 61.0 15.3 512
10 бит Dual Slope PWM, Гц 7812.5 976.6 122.1 30.5 7.6 1024

В режиме двухскатного ШИМ (Dual Slope PWM) максимальная частота ШИМ будет в 2 раза меньше. Из предыдущей таблицы мы видели, что максимальная частота ШИМ у Timer 1 составляет 62.5 кГц (Single Slope PWM). Это достаточно высокая частота для генерации аудиосигнала с помощью ШИМ.

Чтобы сконфигурировать Timer 1, мы должны запрограммировать регистры TCCR1A и TCCR1B.

№ разрядов 7 6 5 4 3 2 1 0
Имена бит COM1A1
COM1A0 COM1B1 COM1B0 COM1C1 COM1C0 WGM11 WGM10
Чтение/запись rw rw rw rw rw rw rw rw
Нач. значение 0 0 0 0 0 0 0 0

• Bit 7:6 – COM1A1:0: Compare Output Mode for Channel A
• Bit 5:4 – COM1B1:0: Compare Output Mode for Channel B
• Bit 3:2 – COM1C1:0: Compare Output Mode for Channel C

Биты COM1A1:0, COM1B1:0 и COM1C1:0 управляют поведением выводов сравнения (OC1A, OC1B и OC1C соответственно). Если один или оба бита COM1A1:0 установлены в лог. 1, то выход OC1A заменяет обычный функционал порта GPIO на функционал ШИМ. То же самое относится и к битам COM1B1:0 и COM1C1:0, они по тому же самому принципу переназначают функционал портов GPIO для выводов, к которым относятся сигналы OC1B и OC1C. Однако имейте в виду, что регистр направления (Data Direction Register, DDR) должен иметь в лог. 1 биты, соответствующие разрядам OCnA, OCnB или OCnC, чтобы разрешить работу выходного драйвера для сигналов ШИМ.

Когда сигналы OC1A, OC1B или OC1C подключены к выводу порта, функция бит COM1A1:0, COM1B1:0 или COM1C1:0 зависит от настройки бит WGM13:0. Таблица 14-1 показывает функциональность бит COM1x1:0, когда биты WGM13:0 установлены в режим Normal или CTC (режимы не PWM).

Таблица 14-1. Compare Output Mode, не PWM.

COM1A1, COM1B1, COM1C1 COM1A0, COM1B0, COM1C0 Поведение выходов OC1A, OC1B, OC1C
0 0 Обычная работа порта, сигнал ШИМ отключен от OC1x.
0 1 Переключение в противоположное состояние OC1x при Compare Match.
1 0 Очистка OC1x при Compare Match (сброс в лог. 0).
1 1 Установка OC1x при Compare Match (установка в лог. 1).

Таблица 14-2 показывает функционал бит COM1x1:0, когда биты WGM13:0 установлены в режим Fast PWM.

Таблица 14-2. Compare Output Mode, Fast PWM(1).

COM1A1, COM1B1, COM1C1 COM1A0, COM1B0, COM1C0 Поведение выходов OC1A, OC1B, OC1C
0 0 Обычная работа порта, сигнал ШИМ отключен от OC1x.
0 1 При битах WGM13:0 в значении 14 или 15: переключение OC1A при Compare Match, OC1B и OC1C отключены (обычная работа порта GPIO). Для всех других настроек WGM1 обычная работа порта, сигналы ШИМ отключены от OC1x. См. таблицу 14-4.
1 0 Очистка OC1x при Compare Math, установка при достижении TOP.
1 1 Установка при Compare Match, очистка при достижении TOP.

Примечание (1). Специальный случай возникает, когда значение OCR1A, OCR1B, OCR1C равно TOP, и установлены биты COM1A1, COM1B1, COM1C1. В этом случае событие совпадения (Compare Match) игнорируется, но установка или очистка осуществляется на значении TOP. Подробнее см. описание "Fast PWM Mode" в даташите на микроконтроллер ATmega32U4.

Таблица 14-3 показывает функционал бит COM1x1:0, когда биты WGM13:0 установлены в режим Phase Correct and Frequency Correct PWM.

Таблица 14-3. Compare Output Mode, Phase Correct and Phase and Frequency Correct PWM(1).

COM1A1, COM1B1, COM1C1 COM1A0, COM1B0, COM1C0 Поведение выходов OC1A, OC1B, OC1C
0 0 Обычная работа порта, сигнал ШИМ отключен от OC1x.
0 1 При битах WGM13:0 в значении 8, 9. 10 или 11: переключение OC1A при Compare Match, OC1B и OC1C отключены (обычная работа порта GPIO). Для всех других настроек WGM1 обычная работа порта, сигналы ШИМ отключены от OC1x. См. таблицу 14-4.
1 0 Очистка OC1x при Compare Math, когда идет счет вверх. Установка OC1x при Compare Math, когда идет счет вниз.
1 1 Установка OC1x при Compare Match, когда идет счет вверх. Сброс при Compare Math, когда идет счет вниз.

Примечание (1). Специальный случай возникает, когда значение OCR1A, OCR1B, OCR1C равно TOP, и установлены биты COM1A1, COM1B1, COM1C1. Подробнее см. описание "Phase Correct PWM Mode" в даташите на микроконтроллер ATmega32U4.

• Bit 1:0 – WGM11:0: Waveform Generation Mode

Вместе с битами WGM13:2, которые находятся в регистре TCCR1B (см. врезку ниже), эти биты управляют последовательностью счета, источником максимального значения (TOP) счетчика, и какой будет использоваться тип генерации формы сигнала, см. таблицу 14-4. Режимы работы, поддерживаемые таймером/счетчиком: Normal mode (счетчик), Clear Timer on Compare match (CTC) mode (сброс таймера при совпадении), и три типа режимов ШИМ (Pulse Width Modulation, PWM). Подробнее см. "Modes of Operation" в даташите на микроконтроллер ATmega32U4.

Таблица 14-4. Описание бит режимов генерации (Waveform Generation).

Mode WGM13:10 Режим работы таймера/счетчика TOP Когда произойдет обновление OCR1x Когда установится флаг TOV1
0 0000 Normal 0xFFFF Немедленно MAX
1 0001 PWM, Phase Correct, 8-bit 0x00FF TOP BOTTOM
2 0010 PWM, Phase Correct, 9-bit 0x01FF TOP BOTTOM
3 0011 PWM, Phase Correct, 10-bit 0x03FF TOP BOTTOM
4 0100 CTC OCR1A Немедленно MAX
5 0101 Fast PWM, 8-bit 0x00FF TOP TOP
6 0110 Fast PWM, 9-bit 0x01FF TOP TOP
7 0111 Fast PWM, 10-bit 0x03FF TOP TOP
8 1000 PWM, Phase and Frequency Correct ICR1 BOTTOM BOTTOM
9 1001 PWM, Phase and Frequency Correct OCR1A BOTTOM BOTTOM
10 1010 PWM, Phase Correct ICR1 TOP BOTTOM
11 1011 PWM, Phase Correct OCR1A TOP BOTTOM
12 1100 CTC ICR1 Немедленно MAX
13 1101 Зарезервировано - - -
14 1110 Fast PWM ICR1 TOP TOP
15 1111 Fast PWM OCR1A TOP TOP

Примечание: имена бит CTC1 и PWM11:0 устарели. Используйте вместо них имена WGM12:0. Однако функциональность этих бит и их размещение в регистрах совместимы с предыдущими версиями таймера.

№ разрядов 7 6 5 4 3 2 1 0
Имена бит ICNC1 ICES1  -  WGM13 WGM12 CS12 CS11 CS10
Чтение/запись rw rw rw rw rw rw rw rw
Нач. значение 0 0 0 0 0 0 0 0

• Bit 7 – ICNCn: Input Capture Noise Canceler

Установка этого бита в лог. 1 активирует подавитель шума на входе захвата (Input Capture Noise Canceler). Когда активирован Noise Canceler, то сигнал с вывода Input Capture Pin (ICP1) проходит через цифровой фильтр. Функция фильтра требует, чтобы на входе появились друг за другом 4 одинаковые выборки уровня, чтобы было определено действительное изменение ICP1. Таким образом, захват по входу в случае фильтрации срабатывает с задержкой 4 такта системных тактов.

• Bit 6 – ICESn: Input Capture Edge Select

Этот бит выбирает, какой перепад на Input Capture Pin (ICP1) используется для срабатывания события захвата. Когда бит ICES1 записан в лог. 0, в качестве активного перепада используется переход логического уровня из 1 в 0, и когда ICES1 установлен в лог. 1, активным будет перепад нарастания (0 -> 1).

Когда сработал захват в соответствии с установкой бита ICES1, значение счетчика копируется в регистр захвата Input Capture Register (ICR1). Это событие также установит бит Input Capture Flag (ICF1), и это вызовет прерывание Input Capture Interrupt, если оно разрешено.

Когда ICR1 используется в качестве значения TOP (см. описание бит WGM13:0, которые находятся в регистрах TCCR1A и TCCR1B), то ICP1 отключается, и соответственно функция захвата по входу запрещена.

• Bit 5 – Reserved Bit

Этот бит зарезервирован для использования в будущем. Чтобы обеспечить совместимость с будущими микроконтроллерами, в него следует записывать 0, когда записывается регистр TCCR1B.

• Bit 4:3 – WGM13:2: Waveform Generation Mode

См. информацию по этим битам в описании регистра TCCR1A (врезка выше, таблица 14-4).

• Bit 2:0 – CS12:0: Clock Select

Эти три бита выбирают тактовую частоту для таймера счетчика, см. рис. 13-8 и 13-9 в даташите на микроконтроллер ATmega32U4.

Таблица 14-5. Описание бит выбора тактов.

CS12 CS11 CS10 Asynchronous Clocking Mode
0 0 0 Timer/Counter1 остановлен
0 0 1 clkI/O/1 (прескалер отключен)
0 1 0 clkI/O/8 (от выхода прескалера)
0 1 1 clkI/O/64 (от выхода прескалера)
1 0 0 clkI/O/256 (от выхода прескалера)
1 0 1 clkI/O/1024 (от выхода прескалера)
1 1 0 Внешний сигнал тактирования, поданный на вывод T1. Активный перепад 1->0.
1 1 1 Внешний сигнал тактирования, поданный на вывод T1. Активный перепад 0->1.

Если используется внешний вывод для тактирования Timer/Counter1, то перепады на выводе T1 все равно будут подсчитаны счетчиком, даже если T1 сконфигурирован как выход. Эта функция дает возможность программно управлять счетом.

Биты 0, 1 и 2 регистра TCCR1B (CS10, CS11 и CS12) управляют опциями тактирования таймера 1, как это показано в таблице 14-5 (см. выше врезку с описанием регистра TCCR1B).

Биты 0 и 1 регистра TCCR1A (WGM10, WGM11) и биты 3 и 4 (WGM12, WGM13) регистра TCCR1B конфигурируют вид формы генерации сигнала. Соответствующие настройки показаны в таблице 14-4 (см. описание регистра TCCR1A во врезке выше). Режимы 1, 2, 3, 5, 6 и 7 из таблицы 14-4 соответствуют стандартным режимам ШИМ.

После того, как таймер сконфигурирован в один из режимов ШИМ, каждый из трех каналов сравнения A, B и C можно разрешить для генерации сигнала PWM. Для этого нужно сконфигурировать биты COM1x0 и COM1x1 (x заменяется на A, B или C) регистра TCCR1A в соответствии с таблицей 14-2 (см. описание регистра TCCR1A).

Значение сравнения ШИМ для каждого канала следует запрограммировать в регистры OCR1A, OCR1B и OCR1C.

Конфигурирования бит TCCR1A недостаточно, чтобы сигналы ШИМ появились на выводах микроконтроллера. Нам также нужно сконфигурировать их в режим выхода. По цоколевке ATmega32U4 можно увидеть, что выходы OC1A, OC1B и OC1C связаны с разрядами портов PB5, PB6 и PB7 (соответствуют портам Arduino 9, 10 и 11). Таким образом, нужно настроить эти ножки портов как выходы, что делается программирование в лог. 1 разрядов PB5, PB6 и PB7 регистра DDRB.

[Fast PWM на Timer 4]

Используя таймеры 0, 1 или 3 мы можем получить сигналы ШИМ частотой импульсов до 62.5 кГц, но максимальной частоты ШИМ можно достичь только с помощью Timer 4.

Timer 4 это 10-разрядный таймер, который может работать на очень высокой скорости счета, потому что для него есть дополнительные варианты тактирования.

В микроконтроллере ATmega32U4 имеется периферийное устройство USB. Этот периферийное устройство требует для своей работы частоты 48 МГц, которая генерируется из 16 МГц системной частоты с помощью встроенной ФАПЧ (соответствующий английский аналог этого термина Phase Locked Loop, сокращенно PLL). В плате Arduino Leonardo PLL получает на входе 16 МГц системной тактовой частоты, и умножением на 6 получает 96 МГц.

Имейте в виду, что неправильная конфигурация PLL микроконтроллера Arduino Leonardo нарушит обмен данными через её интерфейс USB. Вам всего лишь следует знать, что PLL может предоставлять свой выходной сигнал для тактирования Timer 4.

Регистр PLLFRQ, управляющий конфигурацией PLL, имеет много других установок, но нас интересуют только биты PLLTM0 и PLLTM1, которые определяют входную тактовую частоту для Timer 4.

№ разрядов 7 6 5 4 3 2 1 0
Имена бит PINMUX PLLUSB PLLTM1 PLLTM0 PDIV3 PDIV2 PDIV1 PDIV0
Чтение/запись rw rw rw rw rw rw rw rw
Нач. значение 0 0 0 0 0 1 0 0

• Bit 7– PINMUX: PLL Input Multiplexer

Этот бит выбирает входную тактовую частоту для PLL:

PINMUX = 0: вход PLL подключен к PLL Prescaler, который получает в качестве источника главную системную частоту (Primary System Clock).

PINMUX = 1: вход PLL напрямую подключен к внутреннему калиброванному RC-генератору 8 МГц. Этот режим позволяет работать USB Low Speed без использования внешнего кварцевого резонатора, или при использовании внешнего резонатора на частоту, отличающуюся от 8 или 16 МГц.

• Bit 6– PLLUSB: PLL Postcaler for USB Peripheral

Этот бит выбирает коэффициент деления между выходной частотой PLL и входной частотой модуля USB:

PLLUSB = 0: нет деления прямое подключение (если PLL Output = 48 МГц).

PLLUSB = 1: частота PLL Output делится на 2, и передается в модуль USB (если PLL Output = 96 МГц).

• Bit 5:4 – PLLTM1:0: PLL Postcaler for High Speed Timer

Эти биты кодируют коэффициент деления между выходной частотой ФАПЧ (PLL Output) и тактовым входом высокоскоростного таймера (High Speed Timer).

Имейте в виду, что коэффициент деления 1.5 вводит некоторый дополнительный джиттер в тактовую частоту, но связанная с этим ошибка близка к нулю, поскольку средняя скважность тактов 50% (см. рис. 6-7).

PLLTM1 PLLTM0 Коэффициент постскалера PLL для высокоскоростного таймера
0 0 0 (отключено)
0 1 1
1 0 1.5
1 1 2

ATmega TC4 PLL Postcaler operation with division factor1 5 fig6.07

Рис. 6-7. Работа PLL Postcaler с коэффициентом деления 1.5.

• Bit 3:0 – PDIV3:0 PLL Lock Frequency

Эти биты конфигурируют опорную частоту внутреннего генератора ФАПЧ, управляемого напряжением (PLL internal VCO clock reference) в соответствии с требуемой выходной частотой.

PDIV3 PDIV2 PDIV1 PDIV0 Выходная частота PLL
0 0 0 0 Не допускается
0 0 0 1 Не допускается
0 0 1 0 Не допускается
0 0 1 1 40 МГц
0 1 0 0 48 МГц
0 1 0 1 56 МГц
0 1 1 0 Не допускается
0 1 1 1 72 МГц
1 0 0 0 80 МГц
1 0 0 1 88 МГц
1 0 1 0 96 МГц
1 0 1 1 Не допускается
1 1 0 0 Не допускается
1 1 0 1 Не допускается
1 1 1 0 Не допускается
1 1 1 1 Не допускается

Оптимальная конфигурация PLL на 5V (выделено в таблице жирным шрифтом): PLL output = 96 МГц, поделенная на 1.5 для генерации тактов 64 МГц для High Speed Timer, и деленная на 2 для генерации тактовой частоты 48 МГц блока USB.

Есть 4 опции тактирования: не использовать PLL для тактирования таймера (тогда он будет получать системные такты), или использовать выход PLL, поделенный на 1, 1.5 или 2. Последние 3 варианта дадут тактовые частоты 96, 64 или 48 МГц.

У Timer 4 есть дополнительный делитель, конфигурируемый битами CS40 .. CS43 регистра TCCR4B (см. таблицу 15-14 из врезки ниже).

№ разрядов 7 6 5 4 3 2 1 0
Имена бит PWM4X   PSR4  DTPS41 DTPS40  CS43   CS42   CS41   CS40 
Чтение/запись rw rw rw rw rw rw rw rw
Нач. значение 0 0 0 0 0 0 0 0

• Бит 7 - PWM4X: PWM Inversion Mode

Когда этот бит установлен в лог. 1, выбирается режим инверсии ШИМ (PWM Inversion Mode), и инвертируются выходы Dead Time Generator, OC4x и ~OC4x.

• Бит 6 - PSR4: Prescaler Reset Timer/Counter4

Когда этот бит установлен в лог. 1, прескалер Timer/Counter4 будет сброшен (без влияния на TCNT4). Этот бит очистится аппаратно после завершения выполнения этой операции сброса прескалера. Запись в лог. 0 этого бита не оказывает никакого эффекта. Этот бит всегда читается как 0.

• Биты 5,4 - DTPS41, DTPS40: Dead Time Prescaler

Отдельный прескалер Dead Time, установленный перед Dead Time Generator, может делить частоту тактов Timer/Counter4 (PCK или CK) на коэффициенты 1, 2, 4 или 8, предоставляя тем самым большой диапазон регулировки интервалов мертвого времени. Прескалер Dead Time управляется двумя битами DTPS41 и DTPS40 регистра Dead Time Prescaler. Эти биты определяют коэффициент деления прескалера Dead Time (см. таблицу 15-13).

Таблица 15-13. Коэффициенты деления прескалера мертвого времени.

DTPS41 DTPS40 Коэффициент, на который прескалер делит частоту тактов Timer/Counter4
0 0 1 (нет деления частоты)
0 1 2
1 0 4
1 1 8

• Биты 3..0 - CS43, CS42, CS41, CS40: Clock Select

Эти биты определяют источник тактирования и коэффициент предделителя Timer/Counter4 (см. таблицу 15-14).

Таблица 15-14. Timer/Counter4 Prescaler Select.

CS43 CS42 CS41 CS40 Asynchronous Clocking Mode Synchronous Clocking Mode
0 0 0 0 Timer/Counter4 остановлен
0 0 0 1 PCK CK
0 0 1 0 PCK/2 CK/2
0 0 1 1 PCK/4 CK/4
0 1 0 0 PCK/8 CK/8
0 1 0 1 PCK/16 CK/16
0 1 1 0 PCK/32 CK/32
0 1 1 1 PCK/64 CK/64
1 0 0 0 PCK/128 CK/128
1 0 0 1 PCK/256 CK/256
1 0 1 0 PCK/512 CK/512
1 0 1 1 PCK/1024 CK/1024
1 1 0 0 PCK/2048 CK/2048
1 1 0 1 PCK/4096 CK/4096
1 1 1 0 PCK/8192 CK/8192
1 1 1 1 PCK/16384 CK/16384

Настройка, указанная в первой строке таблицы 15-14, предоставляет возможность запрета таймера.

Таким образом, с помощью PLL и делителей Timer 4 можно получить входные частоты таймера между 96 МГц и 5859 Гц.

Так же, как это делалось для Timer 1, для Timer 4 нужно выбрать форму генерации выходного сигнала битами WGM40 и WGM41 регистра TCCR4D.

№ разрядов 7 6 5 4 3 2 1 0
Имена бит FPIE4 FPEN4 FPNC4 FPES4 FPAC4 FPF4 WGM41 WGM40
Чтение/запись rw rw rw rw rw rw rw rw
Нач. значение 0 0 0 0 0 0 0 0

• Бит 7 - FPIE4: Fault Protection Interrupt Enable

Установка этого бита в лог. 1 разрешает прерывание Fault Protection.

• Бит 6– FPEN4: Fault Protection Mode Enable

Установка этого бита в лог. 1 активирует Fault Protection Mode.

• Бит 5 – FPNC4: Fault Protection Noise Canceler

Установка этого бита в лог. 1 активирует Fault Protection Noise Canceler (подавитель помех сигнала срабатывания защиты). Когда подавитель помех активирован, вход вывода Fault Protection (INT0) проходит через цифровой фильтр. Эта функция требует четырех одинаковых значений, появившихся на выводе INT0, чтобы был обнаружен сигнал. Таким образом, срабатывание защиты Fault Protection имеет задержку на 4 такта системного генератора, когда функция подавителя помех активирована.

• Бит 4 – FPES4: Fault Protection Edge Select

Этот бит выбирает, какой перепад на выводе Fault Protection (INT0) будет использоваться как событие сигнала для срабатывания защиты. Когда в бит FPES4 записан лог. 0, активным сигналом будет спад уровня, и когда в бит FPES4 записана лог. 1, активным сигналом будет нарастание уровня.

• Бит 3 - FPAC4: Fault Protection Analog Comparator Enable

Когда в этот бит записана лог. 1, то разрешена функция Fault Protection для Timer/Counter4, срабатывающая от выхода аналогового компаратора. В этом случае выход этого компаратора напрямую подключается ко входу логики Fault Protection, при этом сигнал от компаратора использует те же функции подавителя помех и выбора перепада, как это работало со входом INT0. Когда в этот бит записан лог. 0, то между функцией Fault Protection и аналоговым компаратором соединение отсутствует. Чтобы компаратор вызвал срабатывание прерывания Timer/Counter4 Fault Protection, должен быть установлен бит FPIE4 регистра управления Timer/Counter4 Control Register D (TCCR4D).

• Бит 2 - FPF4: Fault Protection Interrupt Flag

Когда бит FPIE4 установлен в лог. 1, разрешено прерывание Fault Protection. Активность на этом выводе в любом случае вызовет запрос на прерывание, даже если вывод Fault Protection сконфигурирован как выход. Прерывание, соответствующее запросу Fault Protection Interrupt, запустится по адресу Fault Protection Interrupt Vector. Бит FPF4 очищается аппаратно, когда выполняется соответствующий вектор прерывания. Альтернативно FPF4 очищается после такта синхронизации путем записи лог. 1 в этот флаг. Когда когда установлен бит I регистра SREG, а также биты FPIE4 и FPF4, запустится обработчик прерывания Fault Protection.

• Биты 1:0 - WGM41, WGM40: Waveform Generation Mode

Эти биты связаны с битом PWM4x для совместного управления последовательностью счета таймера и типом формируемого сигнала (см. таблицу 15-18).

Режимы работы, поддерживаемые Timer/Counter4: Normal mode (обычный режим, счетчик), Fast PWM Mode (быстрый ШИМ), Phase and Frequency Correct PWM (ШИМ повышенного качества) и PWM6 (режим для управления трехфазными бесколлекторными двигателями BLDC).

Таблица 15-18. Описание бит настройки режима Waveform Generation.

PWM4x WGM41:40 Режим работы таймера/счетчика TOP Когда произойдет обновление OCR4x Когда установится флаг TOV4
0 00 Normal OCR4C Немедленно TOP
1 00 Fast PWM OCR4C TOP TOP
1 01 Phase and Frequency Correct PWM OCR4C BOTTOM BOTTOM
1 10 PWM6 / Single-slope OCR4C TOP TOP
1 11 PWM6 / Dual-slope OCR4C BOTTOM BOTTOM

Доступны опции Fast PWM, Phase and Frequency Correct PWM, PWM6 Single Slope и PWM6 Dual Slope (см. таблицу 15-18 врезки выше).

Обратите внимание, что для сигнала ШИМ максимальное значение счета определяется регистром OCR4C. Так как регистр OCR4C связан с пределом счета, он не зависит от выхода канала C ШИМ (у Timer 4 вообще нет канала C для ШИМ).

PWM6 это специальный режим PWM, который для управления BLDC двигателем использует сразу 3 канала ШИМ, A, B и D (подробнее см. [2]).

После конфигурирования входных тактов каждый из каналов x = A, B и D таймера 4 можно сконфигурировать своими отдельными битами COM4x0, COM4x1 и PWM4x, которые находятся в регистрах TCCR4A и TCCR4C. Как уже упоминалось, канал C использует для задания предела счета, и у него нет блока выхода для генерации сигнала ШИМ.

№ разрядов 7 6 5 4 3 2 1 0
Имена бит COM4A1
COM4A0 COM4B1 COM4B0 FOC4A FOC4B PWM4A PWM4B
Чтение/запись rw rw rw rw w w rw rw
Нач. значение 0 0 0 0 0 0 0 0

• 7, 6 – COM4A1, COM4A0: Comparator A Output Mode

Эти биты управляют поведением выхода генератора сигналов Waveform Output (OCW4A) и подключением вывода Output Compare (OC4A). Если установлены оба бита COM4A1:0, то выход OC4A отменяет обычный функционал порта GPIO, к которому OC4A подключен. Комплементарный выход ~OC4A подключается только в режимах PWM, когда биты COM4A1:0 установлены в 01. Обратите внимание, что биты регистра направления (DDR), соответствующие сигналам OC4A и ~OC4A, должны быть установлены, чтобы заработал выходной драйвер этих сигналов.

Функция бит COM4A1:0 зависит от настроек бит PWM4A, WGM40 и WGM41. Таблица 15-5 показывает функциональность бит COM4A1:0, когда установлен бит PWM4A, в обычном режиме (Normal Mode, не PWM).

Таблица 15-5. Compare Output Mode, Normal Mode (не PWM).

COM4A1 COM4A0 Поведение OCW4A Выв. OC4A Выв. ~OC4A
0 0 Обычная работа порта Отключен Отключен
0 1 Переключение при Compare Match Подключен Отключен
1 0 Очистка при Compare Match Подключен Отключен
1 1 Установка при Compare Match Подключен Отключен

Таблица 15-6 показывает функциональность бит COM4A1:0, когда биты PWM4A, WGM40 и WGM41 установлены в режим быстрого ШИМ.

Таблица 15-6. Compare Output Mode, Fast PWM Mode.

COM4A1 COM4A0 Поведение OCW4A Выв. OC4A Выв. ~OC4A
0 0 Обычная работа порта Отключен Отключен
0 1 Очистка при Compare Match, установка при TCNT4=0x000 Подключен Подключен
1 0 Подключен Отключен
1 1 Установка при Compare Match, очистка при TCNT4=0x000 Подключен Отключен

Таблица 15-7 показывает функциональность бит COM4A1:0, когда биты PWM4A, WGM40 и WGM41 установлены в режим Phase and Frequency Correct PWM.

Таблица 15-7. Compare Output Mode, Phase and Frequency Correct PWM Mode.

COM4A1 COM4A0 Поведение OCW4A Выв. OC4A Выв. ~OC4A
0 0 Обычная работа порта Отключен Отключен
0 1 Очистка при Compare Match и счете вверх, установка при Compare Match и счете вниз Подключен Подключен
1 0 Подключен Отключен
1 1 Установка при Compare Match и счете вверх, очистка при Compare Match и счете вниз Подключен Отключен

Таблица 15-8 показывает функциональность бит COM4A1:0, когда биты PWM4A, WGM40 и WGM41 установлены в односкатный режим PWM6. В режиме PWM6 используется один и тот же сигнал Waveform Output (OCW4A) для генерации всех сигналов, и значения Output Compare OC4A и ~OC4A подключены к выводам OC4A, ~OC4A, OC4B, ~OC4B, OC4D и ~OC4D.

Таблица 15-8. Compare Output Mode, Single-Slope PWM6 Mode.

COM4A1 COM4A0 Поведение OCW4A Выв. OC4A Выв. ~OC4A
0 0 Обычная работа порта Отключен Отключен
0 1 Очистка при Compare Match, установка при TCNT4=0x000 OC4A ~OC4A
1 0 OC4A OC4A
1 1 Установка при Compare Match, очистка при TCNT4=0x000 OC4A OC4A

Таблица 15-9 показывает функциональность бит COM4A1:0, когда биты PWM4A, WGM40 и WGM41 установлены в двухскатный режим PWM6.

Таблица 15-9. Compare Output Mode, Dual-Slope PWM6 Mode.

COM4A1 COM4A0 Поведение OCW4A Выв. OC4A Выв. ~OC4A
0 0 Обычная работа порта Отключен Отключен
0 1 Очистка при Compare Match и счете вверх, установка при Compare Match и счете вниз OC4A ~OC4A
1 0 OC4A OC4A
1 1 Установка при Compare Match и счете вверх, очистка при Compare Match и счете вниз OC4A OC4A

• Биты 5,4 - COM4B1, COM4B0: Comparator B Output Mode

Эти биты управляют поведением выхода генератора сигнала Waveform Output (OCW4B), и подключается в ножке Output Compare (OC4B). Если один или оба бита COM4B1:0 установлены, то выход OC4B отменяет нормальный функционал порта GPIO вывода микроконтроллера, к которому подключен OC4B. Комплементарный выход ~OC4B подключен только в режимах PWM, когда биты COM4B1:0 установлены в 01. Обратите внимание, что биты регистра направления (DDR), соответствующие сигналу OC4B, должны быть установлены, чтобы разрешить работу выходного драйвера.

Функция бит COM4B1:0 зависит от настроек бит PWM4B и WGM40.

Таблица 15-10 показывает функциональность бит COM4B1:0, когда бит PWM4B установлен в режим Normal (не PWM).

Таблица 15-10. Compare Output Mode, Normal Mode (не PWM).

COM4B1 COM4B0 Поведение OCW4B Выв. OC4B Выв. ~OC4B
0 0 Обычная работа порта Отключен Отключен
0 1 Переключение при Compare Match Подключен Отключен
1 0 Очистка при Compare Match Подключен Отключен
1 1 Установка при Compare Match Подключен Отключен

Таблица 15-11. Показывает функциональность бит COM4B1:0, когда биты PWM4B и WGM40 установлены в режим Fast PWM.

Таблица 15-11. Compare Output Mode, Fast PWM Mode.

COM4B1 COM4B0 Поведение OCW4B Выв. OC4B Выв. ~OC4B
0 0 Обычная работа порта Отключен Отключен
0 1 Очистка при Compare Match, установка при TCNT4=0x000 Подключен Подключен
1 0 Подключен Отключен
1 1 Установка при Compare Match, очистка при TCNT4=0x000 Подключен Отключен

Таблица 15-12 показывает функциональность бит COM4B1:0, когда биты PWM4B и WGM40 установлены в режим Phase and Frequency Correct PWM.

Таблица 15-12. Compare Output Mode, Phase and Frequency Correct PWM Mode.

COM4B1 COM4B0 Поведение OCW4B Выв. OC4B Выв. ~OC4B
0 0 Обычная работа порта Отключен Отключен
0 1 Очистка при Compare Match и счете вверх, установка при Compare Match и счете вниз Подключен Подключен
1 0 Подключен Отключен
1 1 Установка при Compare Match и счете вверх, очистка при Compare Match и счете вниз Подключен Отключен

• Бит 3 - FOC4A: Force Output Compare Match 4A

Бит FOC4A активен только когда бит PWM4A задает режим не PWM.

При записи лог. 1 в этот бит принудительно меняется сигнал Waveform Output (OCW4A) и вывод Output Compare (OC4A) в соответствии со значениями, уже установленными в COM4A1 и COM4A0. Если COM4A1 и COM4A0 записаны в том же цикле, что и FOC4A, то будут использоваться новые установки. Бит Force Output Compare может использоваться для изменения значения выходного вывода, не обращая внимание на значение таймера. Произойдет автоматическое действие, запрограммированное COM4A1 и COM4A0, как если бы произошло событие совпадения, но при этом не будет сгенерировано прерывание.

Бит FOC4A всегда читается как 0.

• Бит 2 - FOC4B: Force Output Compare Match 4B

Бит FOC4B активен только когда бит PWM4B задает режим не PWM.

При записи лог. 1 в этот бит принудительно меняется сигнал Waveform Output (OCW4B) и вывод Output Compare (OC4B) в соответствии со значениями, уже установленными в COM4B1 и COM4B0. Если COM4B1 и COM4B0 записаны в том же цикле, что и FOC4B, то будут использоваться новые установки. Бит Force Output Compare может использоваться для изменения значения выходного вывода, не обращая внимание на значение таймера. Произойдет автоматическое действие, запрограммированное COM4B1 и COM4B0, как если бы произошло событие совпадения, но при этом не будет сгенерировано прерывание.

Бит FOC4B всегда читается как 0.

• Бит 1 - PWM4A: Pulse Width Modulator A Enable

Когда этот бит установлен в лог. 1, то разрешается режим PWM, основанный на компараторе OCR4A.

• Бит 0 - PWM4B: Pulse Width Modulator B Enable

Когда этот бит установлен в лог. 1, то разрешается режим PWM, основанный на компараторе OCR4B.

№ разрядов 7 6 5 4 3 2 1 0
Имена бит COM4A1S COM4A0S COM4B1S COMAB0S COM4D1 COM4D0 FOC4D PWM4D
Чтение/запись rw rw rw rw rw rw rw rw
Нач. значение 0 0 0 0 0 0 0 0

• Биты 7,6 - COM4A1S, COM4A0S: Comparator A Output Mode

Эти биты затеняют биты COM4A1 и COM4A0, как это указано в описании регистра TCCR4A – Timer/Counter4 Control Register A (см. врезку выше).

• Биты 5,4 - COM4B1S, COM4B0S: Comparator B Output Mode

Эти биты затеняют биты COM4B1 и COM4B0, как это указано в описании регистра TCCR4A – Timer/Counter4 Control Register A (см. врезку выше).

• Биты 3,2 - COM4D1, COM4D0: Comparator D Output Mode

Эти биты управляют поведением выхода генератора сигнала Waveform Output (OCW4D) и подключением к выводу Output Compare (OC4D). Если один или оба бита COM4D1:0 установлены, то выход OC4D отменяет функциональность ножек порта GPIO, к которым подключается сигнал OC4D. Комплементарный выход ~OC4D подключается только в режимах PWM, когда биты COM4D1:0 установлены в 01. Обратите внимание, что биты регистра направления (DDR), соответствующие ножкам OC4D, должны быть установлены, чтобы разрешить работу выходного драйвера.

Функция бит COM4D1:0 зависит от настроек бит PWM4D и WGM40.

Таблица 15-15 показывает функционал бит COM4D1:0, когда бит PWM4D установлен в режим Normal (не PWM).

Таблица 15-15. Compare Output Mode, Normal Mode (не PWM).

COM4D1 COM4D0 Поведение OCW4D Выв. OC4D Выв. ~OC4D
0 0 Обычная работа порта Отключен Отключен
0 1 Переключение при Compare Match Подключен Отключен
1 0 Очистка при Compare Match Подключен Отключен
1 1 Установка при Compare Match Подключен Отключен

Таблица 15-16 показывает функционал бит COM4D1:0, когда биты PWM4D и WGM40 установлены в режим быстрого ШИМ.

Таблица 15-16. Compare Output Mode, Fast PWM Mode.

COM4D1 COM4D0 Поведение OCW4D Выв. OC4D Выв. ~OC4D
0 0 Обычная работа порта Отключен Отключен
0 1 Очистка при Compare Match, установка при TCNT4=0x000 Подключен Подключен
1 0 Подключен Отключен
1 1 Установка при Compare Match, очистка при TCNT4=0x000 Подключен Отключен

Таблица 15-17 показывает функциональность бит COM4D1:0, когда биты PWM4D и WGM40 установлены в режим Phase and Frequency Correct PWM.

Таблица 15-17. Compare Output Mode, Phase and Frequency Correct PWM Mode.

COM4D1 COM4D0 Поведение OCW4D Выв. OC4D Выв. ~OC4D
0 0 Обычная работа порта Отключен Отключен
0 1 Очистка при Compare Match и счете вверх, установка при Compare Match и счете вниз Подключен Подключен
1 0 Подключен Отключен
1 1 Установка при Compare Match и счете вверх, очистка при Compare Match и счете вниз Подключен Отключен

• Бит 1 - FOC4D: Force Output Compare Match 4D

Бит FOC4D активен только когда бит PWM4D задает режим не PWM.

При записи лог. 1 в этот бит принудительно меняется сигнал Waveform Output (OCW4D) и вывод Output Compare (OC4D) в соответствии со значениями, уже установленными в COM4D1 и COM4D0. Если COM4D1 и COM4D0 записаны в том же цикле, что и FOC4D, то будут использоваться новые установки. Бит Force Output Compare может использоваться для изменения значения выходного вывода, не обращая внимание на значение таймера. Произойдет автоматическое действие, запрограммированное COM4D1 и COM4D0, как если бы произошло событие совпадения, но при этом не будет сгенерировано прерывание.

Бит FOC4D всегда читается как 0.

• Бит 0 - PWM4D: Pulse Width Modulator D Enable

Когда этот бит установлен в лог. 1, то разрешается режим PWM, основанный на компараторе OCR4D.

Чтобы один канал x заработал в режиме ШИМ, нужно установить в лог. 1 соответствующий бит PWM4x. После этого биты COM4x0 и COM4x1 будут определять режим работы ШИМ. В случае канала A режим Fast PWM можно выбрать по таблице 15-6 (см. выше врезку с описанием регистра TCCR4A).

В скетче Arduino, показанном ниже, собраны все режимы генерации ШИМ на основе Fast PWM. В скетче имеется код, необходимый для работы 5 выводов портов, связанных с таймерами 1 и 4 в режимах Fast PWM. Этот скетч доступен на GitHub [3].

/**********************************************************
                Fast PWM Test
Демонстрируется генерация быстрого ШИМ на таймерах 1 и 4.
 
Состоит из двух частей кода. Одна использует TIMER1,
и генерирует ШИМ на портах 9, 10 и 11 с частотами
периода до 62 кГц. Вторая часть использует TIMER4,
формируя ШИМ на портах 6 и 13 с частотами периода
до 187 кГц.
 
История версий:
  12/12/2014 - Version 1.0.
  22/12/2014 - Добавлено пропущенное значение OCR4C. 
 
***********************************************************/
 
/**********************************************************
   Fast PWM на портах 9, 10, 11 (TIMER1)
  
    Не используйте функцию analogWrite для портов
   9, 10 или 11, если используете эти функции,
   так как analogWrite использует тот же таймер
   на этих портах.  
  
   Эти функции скорее всего будут конфликтовать
   с библиотекой servo.  
 
    Используется 5 частот ШИМ между 61 Гц и 62.5 кГц.
**********************************************************/
 
// Частотные режимы для TIMER1:
#define PWM62k   1   //62500 Гц
#define PWM8k    2   // 7812 Гц
#define PWM1k    3   //  976 Гц
#define PWM244   4   //  244 Гц
#define PWM61    5   //   61 Гц
 
// Макросы для непосредственного изменения скважности ШИМ:
#define PWM9   OCR1A
#define PWM10  OCR1B
#define PWM11  OCR1C
 
// Конфигурация тактирования ШИМ.
// В аргументе указывается один из пяти определенных
// макросами режимов (1..5).
void pwm91011configure(int mode)
{
   // Конфигурация TCCR1A
   //  00 : Канал A запрещен (порт 9)
   //  00 : Канал B запрещен (порт 10)
   //  00 : Канал C запрещен (порт 11)
   //  01 : Fast PWM 8 bit
   TCCR1A=1;
 
   // Конфигурация TCCR1B
   // Режим тактирования и Fast PWM 8 bit
   TCCR1B=mode|0x08;  
 
   // Конфигурация TCCR1C
   TCCR1C=0;
}
 
// Устанавливает ШИМ на порту 9
// В аргументе передается скважность ШИМ от 0 до 255
void pwmSet9(int value)
{
   OCR1A=value;   // Установка значения ШИМ
   DDRB|=1 << 5;  // Настройка на выход ножки порта PB5
   TCCR1A|=0x80;  // Активация канала
}
 
// Устанавливает ШИМ на порту 10
// В аргументе передается скважность ШИМ от 0 до 255
void pwmSet10(int value)
{
   OCR1B=value;   // Установка значения ШИМ
   DDRB|=1 << 6;  // Настройка на выход ножки порта PB6
   TCCR1A|=0x20;  // Активация канала
}
 
// Устанавливает ШИМ на порту 11
// В аргументе передается скважность ШИМ от 0 до 255
void pwmSet11(int value)
{
   OCR1C=value;   // Установка значения ШИМ
   DDRB|=1 << 7;  // Настройка на выход ножки порта PB7
   TCCR1A|=0x08;  // Активация канала
}
 
/**********************************************************
   Fast PWM на портах 6, 13 (High Speed TIMER4)   
   Не используйте функцию analogWrite для портов 6 или 13,
   если используете эти функции, потому что analogWrite
   использует тот же таймер для этих портов.   
 
   Эта функция будет конфликтовать с библиотекой MSTIMER2.
   Используется 7 частот ШИМ в диапазоне от 2930 Гц
   до 187.5 кГц.   
 
   TIMER4 использует для входного тактирования PLL,
   благодаря чему его тактовая частота может быть до
   96 МГц на стандартной плате Arduino Leonardo.
   Автор ограничил входную частоту значением 48 МГц
   для генерации ШИМ на частоте периода 187.5 кГц.
   Если необходимо, то частота ШИМ может быть удвоена
   и достичь 375 кГц.
**********************************************************/
 
// Частотные режимы для TIMER4
#define PWM187k 1   // 187500 Гц
#define PWM94k  2   //  93750 Гц
#define PWM47k  3   //  46875 Гц
#define PWM23k  4   //  23437 Гц
#define PWM12k  5   //  11719 Гц
#define PWM6k   6   //   5859 Гц
#define PWM3k   7   //   2930 Гц
 
// Макросы для непосредственного изменения скважности ШИМ:
#define PWM6        OCR4D
#define PWM13       OCR4A
 
// Сюда записывается предел счета:
#define PWM6_13_MAX OCR4C
 
// Конфигурация тактирования ШИМ.
// В аргументе указывается один из семи определенных
// макросами режимов (1..7).
void pwm613configure(int mode)
{
   // Конфигурация TCCR4A
   TCCR4A=0;
   // Конфигурация TCCR4B
   TCCR4B=mode;
   // Конфигурация TCCR4C
   TCCR4C=0;
   // Конфигурация TCCR4D
   TCCR4D=0;
   // Конфигурация PLL
   // Используется частота 96 / 2 = 48 МГц
   PLLFRQ=(PLLFRQ&0xCF)|0x30;
   // Этот вариант настройки удваивает все частоты:
   // PLLFRQ=(PLLFRQ&0xCF)|0x10;
   // Предел счета для ШИМ TIMER4
   OCR4C=255;
}
 
// Устанавливает ШИМ на порту 6 (канал D TIMER4)
// В аргументе передается скважность ШИМ от 0 до 255
void pwmSet6(int value)
{
   OCR4D=value;   // Установка значения ШИМ
   DDRD|=1 << 7;  // Настройка на выход ножки порта PD7
   TCCR4C|=0x09;  // Активация канала
}
 
// Устанавливает ШИМ на порту 13 (канал A TIMER4)
// В аргументе передается скважность ШИМ от 0 до 255
void pwmSet13(int value)
{
   OCR4A=value;   // Установка значения ШИМ
   DDRC|=1 << 7;  // Настройка на выход ножки порта PC7
   TCCR4A=0x82;   // Активация канала
}
 
/************** Дополнительные определения ****************/
 
// Макрос преобразует скважность в процентах (0..100)
// в значение сравнения для ШИМ (0..255)
#define DUTY2PWM(x)  ((255*(x))/100)
 
/**********************************************************/
 
// Функция первоначального запуска демонстрационного кода.
// Генерируется 4 сигнала ШИМ, два постоянных, и два
// с изменяющейся скважностью.
void setup()
{
   // Конфигурирование TIMER1 (порты 9, 10 и 11)
   // Он может генерировать ШИМ на частоте 62 кГц.
   // Допустимые параметры для настройки:
   //      PWM62k, PWM8k, PWM1k, PWM244 and PWM61
   pwm91011configure(PWM62k);
   // Конфигурирование TIMER4 (порты 6 и 13)
   // Он может генерировать ШИМ на частоте 187 кГц.
   // Допустимые параметры для настройки:
   //     PWM187k, PWM94k, PWM47k, PWM23k, PWM12k, PWM6k and PWM3k
   pwm613configure(PWM187k);
   // Запуск генерации ШИМ на порте 11 со скважностью
   // 30%. Перед этим вызовом требуется обязательно
   // вызвать pwm91011configure. Здесь демонстрируется
   // использование макроса DUTY2PWM.
   pwmSet11(DUTY2PWM(30));
   // Запуск генерации ШИМ на выводе 13 со скважностью
   // 75%. Перед этим вызовом требуется обязательно
   // вызвать pwm613configure. Здесь не используется
   // макрос DUTY2PWM для установки скважности в %,
   // вместо этого указывает прямое значение 
   // сравнения (может быть в диапазоне 0..255).
   pwmSet13(192);
   // Порты 9 и 6 будут менять значения скважности
   // в цикле loop. Здесь они предварительно
   // конфигурируются.
   // Подготовка вывода 9 для использования ШИМ.
   // Перед этим вызовом требуется обязательно
   // вызвать pwm91011configure. Здесь мы настраиваем
   // начальную скважность ШИМ 0%.
   pwmSet9(0);
   // Подготовка вывода 6 для использования ШИМ.
   // Перед этим вызовом требуется обязательно
   // вызвать pwm613configure. Здесь мы настраиваем
   // начальную скважность ШИМ 0%.
   pwmSet6(0);
}
 
int value=0;
 
void loop()
{
   // Установка значения скважности ШИМ для портов 9 и 6:
   PWM9=value;
   PWM6=value;
  
   // Инкремент значения скважности ШИМ и переход к 0 после
   // достижения значения 255:
   value=(value+1)%256;
   // Небольшая задержка 10 мс:
   delay(10);
}

Код Timer 1. Этот код включает 4 функции и соответствующие определения. Используются все три канала сравнения Timer 1 для генерации сигналов ШИМ на портах Arduino 9, 10 и 11.

Функция pwm91011configure должна быть предварительно вызвана, чтобы можно было воспользоваться любыми другими функциями, связанными с этим таймером. Она сконфигурирует таймер для работы в режиме Single Slope Fast PWM, и установит прескалер в режим, указанный в аргументе функции. Есть 5 возможных режимов PWM62k, PWM8k, PWM1k, PWM244 и PWM61, связанных с четырьмя доступными частотами режимов Single Slope 8 bit PWM.

Функции pwmSet9, pwmSet10 и pwmSet11 конфигурируют каналы Timer 1, связанные с выводами портов 9, 10 и 11 для запуска режима ШИМ и установки значения ШИМ (от 0 до 255).

После того, как будет вызвана одна из трех вышеуказанных функций, значение ШИМ может быть быстро изменено прямым доступом к соответствующему регистру сравнения канала. Для упрощения доступа сделаны три определения PWM9, PWM10 и PWM11, связанные с регистрами OCR1A, OCR1B и OCR1C.

Код Timer 4. Этот код включает 3 функции и несколько определений. Используется два из трех доступных каналов сравнения A и D, связанных с портами Arduino 13 и 6. Канал B не используется, потому что он конфликтует с портом 10 Arduino, который используется в канале B Timer 1.

Функция pwm613configure подобна аналогичной, определенной для Timer 1. Она установит режимы PLL и PWM для правильного конфигурирования Timer 4 в высокоскоростном режиме 48 МГц PLL, и установит предел счета в регистре OCR4C установкой всех его 8 бит (значение 255).

Входной аргумент установит один из семи доступных частот прескалера для 48 МГц на тактовом входе Timer 4: PWM187k (187500 Гц), PWM94k (93750 Гц), PWM47k (46875 Гц), PWM23k (23437 Гц), PWM12k (11719 Гц), PWM6k (5859 Гц) и PWM3k (2930 Гц). Если Вы помните, у Timer 4 есть 15 опций прескалера тактов. Нижняя частота не реализована в этих определениях, поскольку она не дает никаких преимуществ перед функционалом стандартной функции analogWrite.

Функции pwmSet13 и pwmSet6 конфигурируют каналы Timer 4, связанные с портами 13 и 6 Arduino, чтобы они работали в режиме ШИМ, и устанавливает значение для ШИМ (от 0 до 255).

Подобно тому, как это делается для таймера 1, посте того, как одна из этих двух функций будет вызвана, значение ШИМ может быть быстро изменено прямым доступом к соответствующему регистру сравнения. Для этой цели сделаны два определения PWM13 и PWM6, связанные соответственно с регистрами сравнения OCR4A и OCR4D. Добавлено дополнительное определение PWM6_13_MAX для доступа к регистру OCR4C, что установит предельное значение счета ШИМ (по умолчанию установлено 255, что дает разрешающую способность ШИМ 8 бит).

Код Setup и Loop. Для проверки работы всех этих функций Timer 1 сконфигурирован в функции setup для генерации сигналов ШИМ на частоте 62.5 кГц. Timer 4 сконфигурирован на частоту 187 кГц. Генерируется 4 сигнала ШИМ. На выводах портов 11 и 13 установлены значения скважности ШИМ 11% и 75%. Для выводов портов 6 и 9 в функции loop программируется переменное значение скважности ШИМ от 0% до 100%.

Форма сгенерированных сигналов ШИМ. На следующей картинке показаны полученные сигналы ШИМ, захвачены логическим анализатором.

Arduino FastPWMtest diagram

Сигналы Timer 1 на выводах портов 9 и 11 имеют одинаковый фронт нарастания уровня, потому что они работают на одном и том же таймере и в одинаковом режиме. То же самое относится и к портам 6 и 13, сигналы на которых генерируются Timer 4. Сигналы ШИМ разных таймеров имеют разные частоту, поэтому фронт нарастания уровня сигналов ШИМ не совпадает у разных таймеров.

Это простой пример программирования микроконтроллера ATmega32U4 на языке C. Микроконтроллер установлен на плате AVR-USB32U4 [4] (аналог Arduino Leonardo). Пищалка (пьезокерамический излучатель звука) подключен к выходу канала B таймера 4, это ножки портов PB5 (~OC4B) и PB6 (OC4B).

AVR USB32U4 TC4 PWM sound gen example

Таймер 4 тактируется от системной тактовой частоты 16 МГц, поделенной на 256. ШИМ настраивается в 10-битном режиме Fast PWM, с противофазным формированием сигнала на ~OC4B и OC4B. Генерация пищания запускается функцией Beep, длительность генерации звука отслеживается обработчиком beephandler, который должен вызваться каждые 10 мс.

Заголовочный файл beep.h:

#ifndef __BEEP__
#define __BEEP__
 
#include "types.h"
 
#define BEEP_DDR     DDRB
#define BEEP_PORT    PORTB
#define BEEP_PHASE_A PB5
#define BEEP_PHASE_B PB6
 
#define BEEP_NONE       0
#define BEEP_START      1
#define BEEP_PROGRESS   2
 
void Beep (u16 hz, u16 ms);
void beephandler (void);
 
#endif

Модуль кода beep.c:

#include < avr/io.h>
#include "beep.h"
#include "pins.h"
 
static u16 beeptimems = 0;
static u8 beepstate = BEEP_NONE;
 
//Запрет таймера 4, в биты CS43, CS42, CS41, CS40 нужно записать 0000:
#define TIMER4_PWM_DISABLE() (TCCR4B &= ~((1<<CS43)|(1<<CS42)|(1<<CS41)|(1<<CS40)))
//Запуск таймера 4 от частоты F_CPU/256, в эти биты нужно записать 1001:
#define TIMER4_PWM_ENABLE() (TCCR4B |= (1<<CS43)|(0<<CS42)|(0<<CS41)|(1<<CS40))
 
void Beep(u16 hz, u16 ms)
{
   u16 val16;
   u8 hibyte, lobyte;
   //Значение TOP (OCR4C):
   val16 = (F_CPU/256)/hz;
   hibyte = val16>>8;
   lobyte = val16 & 0x00FF;
   TC4H = hibyte;
   OCR4C = lobyte;
   //Значение сравнения для переключения выхода канала B (OCR4B):
   val16 >>= 1;
   hibyte = val16>>8;
   lobyte = val16 & 0x00FF;
   TC4H = hibyte;
   OCR4B = lobyte;
   //Установка длительности и запуск пищания:
   beeptimems = ms;
   beepstate = BEEP_START;
}
 
void beephandler(void)
{
   switch (beepstate)
   {
   case BEEP_START:
      //Настройка портов ШИМ на выход:
      BEEP_DDR |= (1<<BEEP_PHASE_A)|(1<<BEEP_PHASE_B);
      //Режим Fast PWM (PWM4B=1, WGM40=0):
      TCCR4A |= (0<<COM4B1)|(1<<COM4B0)|(1<<PWM4B);
      TIMER4_PWM_ENABLE();
      beepstate = BEEP_PROGRESS;
      break;
   case BEEP_PROGRESS:
      if (0==beeptimems)
      {
         //Запрет таймера 4:
         TIMER4_PWM_DISABLE();
         beepstate = BEEP_NONE;
      }
      break;
   }
   if (beeptimems > 10)
      beeptimems -= 10;
   else
      beeptimems = 0;
}

[Ссылки]

1. Fast PWM on Arduino Leonardo site:r6500.blogspot.com.
2. 10-разрядный высокоскоростной Timer/Counter4.
3. FastPWM.ino site:github.com.
4. Макетная плата AVR-USB32U4.

 

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


Защитный код
Обновить

Top of Page