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