PWM или ШИМ (широтно импульсная модуляция) на AVR для новичков. Часть 1

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

Так как для меня самым важным было применение ШИМ именно для управления яркостью светодиодов, то именно их я и буду использовать в примерах. В качестве микроконтроллера будем использовать горячо любимый 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);       }; } 

Компилируем и пробуем в протеусе:

Как видим, программа полностью работоспособна и выполняет возложенные на нее задачи, ничего сложного в ней нет.

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

Прикрепленные файлы:

  • pwm at8.zip (15 Кб)

Теги: