ШИМ (PWM) — широтно-импульсная модуляция. Не нужно пугаться данного термина. Это всего навсего способ регулирования напряжения. Допустим подсветка монитора горит слишком ярко, вы меняете яркость. А что же происходит в этот момент на самом деле?
Представим себе, что подсветка монитора это несколько светодиодов. Питается все это дело от постоянного напряжения. Но вот нам понадобилось уменьшить яркость монитора. Логично ответить, что это можно сделать переменным резистором. На маленьких токах — возможно. Но на больших, резистор будет сильно греться. Сильно возрастут габариты, потери, энергопотребление.
Поэтому люди придумали схему на транзисторах, которая делает из постоянного напряжения пульсирующее. Оказывается, пульсирующее напряжение, в зависимости от заполнения периода будет эквивалентно постоянному напряжению. Т.е. если в течение периода напряжение 50% времени было включено, 50% выключено, то эквивалент постоянного напряжения будет равен 50% от номинального.
В цифрах это просто — было 5В постоянного напряжения прогнали через ШИМ — получили 2,5В. Если заполнение импульса равно 75%, то эквивалентное постоянное напряжение будет 3,75В. Думаю идея понятна.
Теперь приступим к практической реализации. Будем при помощи микроконтроллера изменять заполнение от 0 до 100%, потом от 100% до нуля. Конечный результат должен выглядеть так:
Чтобы было более наглядно, подключим светодиод. В результате у нас будет плавно включаться и отключаться светодиод.
Запускаем наш любимый CodeVision. Создаем проект при помощи мастера. В разделе таймеров (Timers), выбираем Timer 2 и выставляем настройки как на рисунке.
Если попробовать сгенерировать проект, то прога может ругнуться. Соглашаемся, ведь у нас нога 3 порта В должна быть настроена как выход.
Приводим код к следующему виду:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 | #include <mega8.h> void main(void) { PORTB=0x00; DDRB=0x08; // Timer/Counter 2 initialization ASSR=0x00; TCCR2=0x6C; TCNT2=0x00; OCR2=0x00; TIMSK=0x00; while (1) { }; } |
Уделим внимание строке OCR2=0x00; Эта переменная как раз и отвечает за величину заполнения импульса. Изменяется данная величина от 0 до 255(0хFF), т.е. 255 соответствует 100% -му заполнению (постоянный ток). Следовательно, если нужно 30% заполнение (255/100)*30=77. Далее 77 переводим в шестнадцатеричную систему OCR2=0x4D;
TCCR2=0x6C; Изменяя данную величину мы можем регулировать частоту ШИМ. Величина частоты работы ШИМ кратна частоте, на которой работает микроконтроллер. В проекте использована частота микроконтроллера 8 МГц, частоту ШИМ использовали 125кГц, следовательно делитель равен 8/125=64
0x6C в двоичной системе счисления 1101100, открываем даташит на Atmega8 и видим описание регистра TCCR2, так вот 1101100 последние цифры 100 и отвечают за выбор частоты работы ШИМ
Приступим непосредственно к программе:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 | #include <mega8.h> #include <delay.h> void main(void) { PORTB=0x00; DDRB=0x08; ASSR=0x00; TCCR2=0x6C; TCNT2=0x00; OCR2=0x00; TIMSK=0x00; while (1) { while(OCR2<0xff) { OCR2=OCR2+0x01; delay_ms(5); } while(OCR2>0x00) { OCR2=OCR2-0x01; delay_ms(5); } }; } |
Код прост до безобразия: сначала в цикле увеличиваем заполнение от 0 до 255(ff), потом уменьшаем от 255 до 0.
И напоследок видосик, как это все должно работать. Успехов в изучении)
помогите пожалуйста я хочу включить проект 2 кнопки с одной кнопки начинается цикл нажатие другой кнопки цикл шел наоборот уменьшить свечение светодиода
спасибо заранее
if((PINB.0==0)&&(OCR2<0xff))
{
OCR2=OCR2+0x01;
delay_ms(5);
}
if((PINB.1==0)&&(OCR2>0x00))
{
OCR2=OCR2-0x01;
delay_ms(5);
}
спасибо за внимание и за помощь. я учусь и простите за глупые вопросы значит получится так да?
#include
#include
void main(void)
{
PORTB=0x00;
DDRB=0x08;
ASSR=0x00;
TCCR2=0x6C;
TCNT2=0x00;
OCR2=0x00;
TIMSK=0x00;
if((PINB.0==0)&&(OCR20?00))
{
OCR2=OCR2-0?01;
delay_ms(5);
}
нет, опрос кнопок должен быть внутри бесконечного цикла
Спасибо автору, сегодня сделал свою первую работу на МК, именно по вашей теме ШИМ)) ЗАРАБОТАЛО!!!!! Только делал на tiny13,пришлось чуть переделать настройки- и даже так получилось!! Ну я ГИГАНТ))))
Огромное спасибо тем,кто доступно объясняет материал!
Подаскажите пожалуйста, что даёт строчка «ASSR=0x00», а то пишу под тини2313 в Atmel Studio
Регистр относится к настройке асинхронного таймера, в тиньке я этой фичи не заметил. Вообще можно писать в атмел студии, но никто не запрещает вам пользоваться CAVR как генератором кода. Названия регистров то те же.
Так и сделал. Настройку таймеров взял из генератора и вуаля, всё заработало. И вправду, в тини нету такого.
Народ, помогите пожалуйста с программным ШИМ ,как его сделать, читал литературу, как то заумно написано, да и еще плохо объяснимо что от куда и куда… Расскажите пожалуйста в его реализации. Весьма благодарен!
Я себе представляю себе программный шим так: вначале нужно определиться с частотой, на которой работает ШИМ. Для некоторых проектов она критична, для некоторых нет, надо смотреть задачу. Допустим взяли абстрактную частоту 1кГц. Период длится 1/1000=1мс. Далее стоит определиться с шагом регулирования, пускай 10%, т.е. мы можем получить 10 ступеней напряжения. К примеру, если в течение 0,1мс сигнал будет 5В а остальные 0,9мс, будет 0, то это соответствует 10% напряжения, если 0,2мс сигнал есть, 0,8 его нет, это будет 20% и т.д. Нам остается настроить таймер с прерыванием каждые 0,1мс, зашли в прерывание, включили ножку посмотрели сколько процентов от номинального напряжения нужно, допустим 30, значит пока прибавили к нулю 10%, записали в переменную и вышли из прерывания. В следующий раз прибавили еще 10… наконец 30%, выключаем ножку, прибавляем 10 и так до 100. На сотке обнулились и начали цикл заново.
Так, пока спасибо, буду мудрить, если что отпишусь))
TCCR2=0x6C; Изменяя данную величину мы можем регулировать частоту ШИМ. -що это значит ???
если врема импульса зависит от делей, таймер ненужен??
например
OCR2=OCR2+0x01;
delay_ms(5);- зачем делей, если ми используем таймер????
1. ШИМ это способ регулирования напряжения. Основан он на том, что от скважности сигнала(заполнение импульса) напрямую зависит напряжение на выходе. Чем больше в течение периода сигнал был включен тем больше напряжение, и наоборот. Эта особенность не зависит от частоты, но частота будет влиять на скорость изменения напряжения. В некоторых случая это может быть важно.
2. Время импульса(период) не зависит от делея. Таймер нужен. Период зависит от числа записанного в регистре OCR. Максимум для 8 битного таймера 255.
3. В данной прошивке мы изменяем скважность(время заполнения) от нуля до максимума, а затем от максимума до нуля. Для этого из регистра OCR мы отнимаем или прибавляем единицу. Чтобы результат был более наглядным(не слишком быстро) мы вводим задержку после каждого изменения OCR.
Подробнее можно почитать здесь http://avr-start.ru/?p=1934
Спасибо!!
НА КАКОЙ НОГЕ БУДЕТ ЭТО ВСЁ ДЕЛО?
PB3
Вопрос отменяется разобрался, но с трудом. Получается так: регистры сравнения имеют две функции:
— Они могут вызывать прерывание
— И могут изменять состояние выводов (с 0 на 1 и обратно)
Тогда частота шим не будет равна частоте таймера, а будет равна __формуле__ в даташите.
здесь описано как это работает http://avr-start.ru/?p=1934
Здравствуйте!
А что за осциллограф вы используете? Его видно во многих ваших статьях. Он дорогой? =)
DSO Nano DSO201, самый дешевый из того что было. Низкочастотные сигналы им смотреть норм. Если деньги есть, лучше брать сразу норм осцилл.
Доброго времени, а мега ПЗУшная? То есть отключив питание и подав снова она запомнит состояние переменных, светодиод будет гореть с той же яркостью, что при выключении?
Заранее спасибо
Если записать значение переменных в EEPROM, то все будет запоминаться
Моделирует ли протеус полноценно ШИМ? Дело в том, что там светодиод просто зажигается и гаснет, как при простом включении и выключении. Плавности пока не наблюдаю. Или я в протеусе что-то не настроил? Частота мк в проекте и в протеусе совпадает — 8МГц.
Светодиод в протеусе имеет 2 состояния — включено/выключено
Понял. Дело в том, что если на светик подать синус в протеусе, то будет как раз плавное изменение яркости. Поэтому я и заинтересовался
доброго времени, подскажите можно ли как нибудь диапазону значений:
от 240 до 255 присвоить значение 255,
от 220 до 239 присвоить 230.
и так далее до 124.
суть такова, что если приходит больше 125 то работает один шим, меньше другой, и эта же переменная регулирует скважность, спасибо!
Наверно так
if(value > 240 && value <255)
{
OCRnx = 255;
}
Здравствуйте !
В atmega16. Если я хочу делать ШИМ c потров PB0,PB1, PA…(кроме PD4,PD5,PD5. там на уроке 16 у вас уже есть) или другие портов.
Пишите, пожалуйста как это делать ?
Спасибо большое !
Под аппаратный шим можно задействовать только те ножки, которые на это рассчитаны, открываете даташит на мегу16 смотрите выводы мк, там где напротив ножки написано OC0, OC1 и т.п. Если нужны произвольные ножки — пилите программный шим, см коменты выше
помогите режим фазовой корректировки включить, уже всё перепробовал. долбаный cv avr постоянно ругает что это не правильно, то не знает. а итог или неработат или такойже fast pwm
void main(void)
{
PORTD=0x00;
DDRD=0x00;
PORTB=0x00;
DDRB=0xFF;
PORTC=0x00;
DDRC=0x00;
ADMUX=FIRST_ADC_INPUT | (ADC_VREF_TYPE & 0xff);
ADCSRA=0xCB;
#asm(«sei»)
TCCR1A=0xB1;
TCCR1B=0x03;
TCNT1H=0x00;
TCNT1L=0x00;
ICR1H=0x00;
ICR1L=0x00;
OCR1AH=0x00;
OCR1AL=0x00;
OCR1BH=0x00;
OCR1BL=0x00;
ASSR=0x00;
TCCR2=0x00;
TCNT2=0x00;
OCR2=0x00;
MCUCR=0x00;
TIMSK=0x00;
ACSR=0x80;
SFIOR=0x00;
вот что здесь исправить или добавить и главное куда чтобы заработало. не могу приладить WGM и тд 😥
Предполагаю что нужно так, выход OC1A
// Timer/Counter 1 initialization
// Clock source: System Clock
// Clock value: 125,000 kHz
// Mode: Ph. correct PWM top=OCR1A
// OC1A output: Non-Inv.
// OC1B output: Discon.
// Noise Canceler: Off
// Input Capture on Falling Edge
// Timer1 Overflow Interrupt: Off
// Input Capture Interrupt: Off
// Compare A Match Interrupt: Off
// Compare B Match Interrupt: Off
TCCR1A=0x83;
TCCR1B=0x13;
TCNT1H=0x00;
TCNT1L=0x00;
ICR1H=0x00;
ICR1L=0x00;
OCR1AH=0x00;
OCR1AL=0x00;
OCR1BH=0x00;
OCR1BL=0x00;
🙁 протеус молчит с таким набором
что вы хотите для начала
управлякмый шим по адц, это получилось (хотя требует настройки по месту) и 2а выхода шим, один нормальный, другой инвертный и смещённый на 50%(ксожалению не знаю как это точно называется)
есть файл протеуса, есть целиком исходник (на половину сгенерированый cv avr и другой половиной собраный из моих старых проектов)
не думаю что всё всегда правильно делал, но по крайней мере рабочий результат был. работаю на атмега8
лучше на форуме выложите, будет проще обсуждать, и более детально опишите что и где работает а где нет
на форуме придётся всё снова объяснять и могут ещё и проигнорировать или обвинить в том что настолько ленив что не читаю даташит. но уже устал все варианты проганять, ничего не подходит. я знаю что чтото не правильно делаю. на разных форумах реакция одна и тажа. кури даташит. пожалуста, можно без форумов с надменными программистами 😥
На нашем форуме нет надменных программистов, ссылка на самом верху страницы. Просто форум более подходит для диалога на конкретную тему, да и мне телепатировать сложно, проще посмотреть ваш проект.
Тема появилась, посмотрите пожалуйста. Очень нужно разобраться, название темы на форуме «atmega8 коррекция фаз PWM» 🙂
Простите, а можно ли вывести этот шим да какую ни будь другую ногу?? Как ни будь программно задать чтобы дрыгалась другая нога а не ПБЗ, просто на ней как раз МОСИ что нужен для дисплея 😕
Можно сделать программный ШИМ, тогда можно будет юзать любую ногу, но это будет отъедать много процессорного времени