Главная » Микроконтроллеры
Призовой фонд
на октябрь 2021 г.
1. Рюкзак Mean Well
Компэл
2. Инвертор авто Mean Well 150 Ватт
Компэл
3. Термос MeanWell
Компэл
4. 100 руб.
От пользователей

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


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

AVR-программатор USB ASP
AVR-программатор USB ASP
Конструктор регулируемого преобразователя напряжения LM317 Мультиметр Mastech MS8268
вверх