Главная » Микроконтроллеры
Призовой фонд
на октябрь 2020 г.
1. 1500 руб
Сайт Паяльник
2. Тестер компонентов MG328
Сайт Паяльник
3. 150 руб.
От пользователей

Похожие статьи:



RGB катодные светодиоды

mikroPascal for AVR. Урок 7. Аппаратный ШИМ

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

Итак, что же такое ШИМ? На английском это сокращение звучит иначе - PWM, что расшифровывается как pulse-width modulation (широтно-импульсная модуляция). Вся суть ШИМа в изменении скважности импульсов, что позволяет изменять среднее напряжение на нагрузке. Всего различают три вида ШИМ: аналоговый, двоичный (наш вариант) и троичный.


Рис 1.1. Пример ШИМ.

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

Подведем промежуточные итоги: мы знаем что в МК фирмы Atmel есть аппаратный ШИМ (зачастую не один, а несколько), а так же знаем, что собственно он собой представляет. Но как им управлять?

Оказывается все довольно просто. Для управления ШИМом в mikroPascal есть специальные процедуры, с помощью которых можно инициализировать ШИМ, запустить/остановить и задать длительность импульсов. Далее, предлагаю вашему вниманию простой пример, в котором мы просто запустим ШИМ с заданной длительностью импульса и частотой.

program PWM_mega8_1_2_3ch_def;                                                                          //Самый простой метод работы с ШИМом в mikroPascal.
                                                                                                        //Достаточно просто инициализировать модуль ШИМ и просто
                                                                                                        //забыть про него.

procedure Init();                                                                                       //Для простоты вынес инициализацию в отдельную процедуру.
begin                                                                                                   //В этом примере это не существенно, но далее тк будет проще.
     DDRB := 0xFF;                                                                                      //Для правильной работы ШИМа необходимо настроить порт "на выход".
     PWM16bit_Init(_PWM16_FAST_MODE_8BIT, _PWM16_PRESCALER_16bit_8, _PWM16_NON_INVERTED, 200, _TIMER1); //Инициализация 16 битного ШИМа (OCR1A, OCR1B).
     PWM2_Init(_PWM2_FAST_MODE, _PWM2_PRESCALER_8, _PWM2_NON_INVERTED, 200);                            //Тоже самое, но для 8-ми битного модуля (OCR2).
end;

begin
     Init();
     while TRUE do begin
     end;
end.

Думаю вас заинтересовали функции "PWM16bit_Init" и "PWM2_Init". Это функции из стандартной библиотеки mikroPascal, которая так и называется - PWM Library. Советую вам все-таки почитать даташит для ATmega8 (для демонстрации примеров будет использоваться именно этот доступный МК). И как из последнего следует, в ATmega8 есть три канала ШИМ: один 8-ми битный и два 16-ти битных. Первый работает за счет таймера/счетчика 2, а второй - таймера/счетчика 1. К сожалению, для T0 такой опции нет.

Теперь немного о самих функциях инициализации.

procedure PWM16bit_Init(тип генерации : byte; предделитель : byte; инверсия : byte; длительность импульса : word; используемый таймер : byte);

Для PWM2 отличий мало:

procedure PWM2_Init(тип генерации : byte; предделитель : byte; инверсия : byte; длительность импульса : word);

Отсутствует только выбор таймера. Что касается выбора параметров, то для этого нужно открыть help. Там все неплохо расписано, хоть и на английском (в статье я это приводить не буду, уж больно много места это займет).

Теперь можно посмотреть, что получилось в итоге. Для этого запускаем Proteus, выбираем МК.. ну и так далее. Вот результат:

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

program PWM_mega8_1_2_3ch_def_adv;

procedure Init();                                                                                       //Инициализация ШИМа в этом примере ничем не отличается от прошлого примера.
begin
     DDRB := 0xFF;
     PWM16bit_Init(_PWM16_FAST_MODE_8BIT, _PWM16_PRESCALER_16bit_8, _PWM16_NON_INVERTED, 200, _TIMER1);
     PWM2_Init(_PWM2_FAST_MODE, _PWM2_PRESCALER_8, _PWM2_NON_INVERTED, 200);
end;

begin
     Init();
     delay_ms(1000);                                                                               //Выставляем задержку 1с
     PWM2_Set_Duty(128);                                                                           //Изменяем скважность импульсов для второго модуля ШИМ.
     delay_ms(1000);                                                                               //Еще 1с задержки. Далее изменяем скважность уже для 1-го модуля ШИМ.
     PWM16bit_Change_Duty(128, _TIMER1_CH_A);                                                      //Очень интересный момент! Подробнее смотрите в видео!
     while TRUE do begin

     end;
end.

Теперь, как вы видите, через 1с после запуска программы изменится длительность импульсов на выходе OC2, а еще через 1с - на выходе OC1A.

Но можно еще немного усложнить программу. Например, добавим выключение ШИМа через 3с после старта.

delay_ms(1000);                                                                               //Допишем еще три строчки, которые будут отключать ШИМ (оба канала),
PWM2_Stop;                                                                                    //через 1с.
PWM16bit_Stop(_TIMER1_CH_A);

Этот кусочек кода вставьте перед бесконечным циклом. И вот результат:

Использование библиотек, конечно удобно. Но в любом случае, необходимо уметь работать с регистрами напрямую, что бы не зависеть от других разработчиков (которые как раз и пишут эти библиотеки).

Так как мы используем в качестве "наглядного пособия" микроконтроллер ATmega8, то у ШИМ тут относятся следующие регистры: OCR1AL, OCR1AH, OCR1BL, OCR1BH, OCR2, TCCR1A, TCCR1B, TCCR2. Регистры OCRx служат для записи значения, до которого будет считать таймер, и соответственно это определяют длительность импульса на выходе. Регистры TCCRx служат для настройки режимов ШИМ, настройки таймеров и их предделителей.

В прикрепленном файле TCCR.rar (скачать в конце статьи) привожу "расшифровку" вышеупомянутых регистров

Зададим такие же параметры ШИМ как и в первом примере.

Начнем с TCCR2. Для этого нам нужно:

  • Установить режим Fast PWM. Это можно сделать, выставив биты 3 и 6 (WGM21 и WGM20).
  • Кроме того, не забываем про бит 5 (COM21), для не инвертированного режима.
  • И устанавливаем предделитель на 8 - это бит 1 (CS21).

Должно получиться так: 01101010 (нулевой бит справа).

Далее конфигурируем регистры TCCR1A и TCCR1B.

  • В TCCR1A нужно записать такую последовательность: 10100001;
  • А в TCCR1B нужно записать: 00001010.
  • Что я предлагаю вам туда записать, посмотрите в даташите или картинках выше.

Ниже представлен полный код:

program PWM_1_2_3ch_reg_adv;                                      //В этом примере рассмотрим
                                                                  //"ручную" настройку ШИМа для
                                                                  //популярного микроконтроллера ATmega8.
var i: byte;

procedure Init();
begin
     DDRB := 0xFF;                                                //Привычно настраиваем порт на выход.
     OCR2 := 200;                                                 //Но теперь, уже простого заглядывания в "магический" help не будет.
     OCR1AH := 0x0;                                               //Нужно брать в руки даташит на тот контроллер, под который вы пишите программу и
     OCR1AL := 200;                                               //выискивать раздел с описанием регистров для таймеров.
     OCR1BH := 0x0;                                               //В данном случае, нужно было найти информацию по регистрам TCCR2, TCCR1A и TCCR1B.
     OCR1BL := 200;                                               //В регистры OCRx записывается число, с которым потом будет сравниваться значение
     TCCR2 := %01101010;                                          //таймера, и которое, соответственно будет определять длительность (заполнение) импульсов.
     TCCR1A := %10100001;
     TCCR1B := %00001010;
end;

begin
     Init();
     while TRUE do begin

     end;
end.

Как уже упоминалось, для изменения длительности импульсов на выходе достаточно просто записать другое число в регистры OCRx. Не забывайте, регистры OCR1AH и OCR1AL представляют собой "половинки" одного 16-ти битного регистра. Можно сразу "закрепить" знания, дописав немного кода:

var i: byte;
....
for i := 0 to 255 do begin                             //Просто сидеть и наблюдать за неизменной длительностью импульсов
    OCR2 := i;                                         //довольно скучно, по этому мы немного внесем разнообразия в этот проектик.
    OCR1AL := i;
    OCR1BL := i;                                       //Просто возьмем и сделаем так, чтобы сначала длительность импульсов
    delay_ms(10);                                      //увеличивалась, а потом уменьшалась.
end;                                                   //Это крайне легко сделать с помощью цикла!
for i := 255 downto 0 do begin                         //Такую конструкцию не очень часто встретишь, но слово "downto" обозначает декремент.
    OCR2 := i;
    OCR1AL := i;
    OCR1BL := i;
delay_ms(10);
end;

Объявите переменную i (byte) и вставьте код в бесконечный цикл. После запуска симуляции в Proteus, можно наблюдать такую картину:

На этой ноте я заканчиваю. Надеюсь, что вы нашли в этой статье что-то полезное для себя. Спасибо за внимание!

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

Теги:

Опубликована: Изменена: 11.05.2015 0 0
Я собрал 0 0
x

Оценить статью

  • Техническая грамотность
  • Актуальность материала
  • Изложение материала
  • Полезность устройства
  • Повторяемость устройства
  • Орфография
0

Средний балл статьи: 0 Проголосовало: 0 чел.

Комментарии (4) | Я собрал (0) | Подписаться

+1
YurkaM #
Ой, чё-то не то у вас в видео с определением скважности: "Скважность - это отношение высокого логического уровня к низкому логическому уровню".
Даже если догадаться, что сравниваются ДЛИТЕЛЬНОСТИ уровней, всё равно ваше определение в корне не верно. Скважность есть отношение периода к длительности импульса S=T/t. Ещё есть величина обратная скважности, коэффициент заполнения, он же Duty cycle (ИМХО, понятней, наглядней и удобней, чем скважность), D=t/T.
И да, что ещё за аналоговый ШИМ? Можно ссылку на описание/определение?
Ответить
0

[Автор]
zeconir #
Принял к сведению, исправлю в статье и сам исправлюсь. Тоже по-ходу учусь. Про аналоговый - наверное кривовато выразился.. Информацию взял отсюда: https://ru.wikipedia.org/wiki/%D0%A8%D0%B8%D1%80%D0%BE%D1%82%D0%BD%D0%BE-%D0%B8%D0%BC%D0%BF%D1%83%D0%BB%D1%8C%D1%81%D0%BD%D0%B0%D1%8F_%D0%BC%D0%BE%D0%B4%D1%83%D0%BB%D1%8F%D1%86%D0%B8%D1%8F
Ответить
+1
YurkaM #
Ну да, понятно, что аналоговый - это по способу формирования. Вообще, конечно, в концепции статьи эти нюансы не столь важны, главное суть ясна, а дальше - реализация. Просто фраза как-то резанула, мол всего три вида ШИМ. Как будто если он аналоговый, то не "двоичный" и не "троичный". Вот я и поинтересовался - мож маркетологи чего нового "изобрели".
Ответить
0

[Автор]
zeconir #
Да, да. Стараюсь основательно готовится к видео, но иногда бывает что "проскакивает". К сожалению, модератор сказал, что видео перезалить не удастся, но обещал хотя-бы в виде заметки к видео этот момент осветить.
Ответить
Добавить комментарий
Имя:
E-mail:
не публикуется
Текст:
Защита от спама:
В чем измеряется напряжение?
Файлы:
 
Для выбора нескольких файлов использйте CTRL

Программатор Pickit3
Программатор Pickit3
Набор для сборки - LED лампа DC-DC регулируемый преобразователь 1.5-37В 2А с индикатором
вверх