Воскресенье, 14 октября 2012 04:44

Программирование c нуля в AVRStudio 5 (ч.10) Featured

Written by
Rate this item
(0 votes)

eyecatcher thumb  ШИМ – это широтно-импульсная модуляция, или PWM — Pulse Width Modulation метод, позволяющий из цифровых импульсов получить аналоговый сигнал, а так-же один из способов регулирования мощности в нагрузке. Предположим, что у нас, есть генератор прямоугольных импульсов с постоянной амплитудой (размахом) и определенной частотой. Частота (Гц – герц) представляет собой количество импульсов в секунду и обратно пропорциональна периоду – (Т) времени, за которое появляется новый импульс; F= 1/T

 

 

 

 

alt

Период состоит из двух участков, положительного и нулевого, которые могут отличаться по времени.

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

alt

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

alt

а уменьшить мощность можно удлинением отрицательного участка периода.

Именно по этому принципу работает ШИМ.

alt

В импульсной технике нередко можно встретить слова скважность, меандр, коэффициент заполнения. Определимся с терминологией.

Отношение периода к длительности импульса называется скважностью. Величина обратная скважности называется периодом заполнения.

S=T/т=1/D; где

S-скважность, T-период, т-длительность импульса, D-коэфициент заполнения.

Скважность определяет соотношение между пиковой и средней мощностью импульсов напряжения или тока.

Сигнал со скважностью, равной двум — называется меандр.

В меандре есть положительный и нулевой полупериоды, которые равны по времени.

В микроконтроллерах с помощью таймеров или подпрограмм задержек мы можем сформировать сигнал с произвольным периодом, притом положительный и нулевой участки, с разными значениями.

Существуют два режима ШИМ:

Fast PWM (быстрый ШИМ)

Phase Correct PWM (ШИМ с точной фазой)

В микроконтроллерах AVR, частота ШИМ определяется тактовой частотой процессора и разрядностью таймера/счетчика. Регистр сравнения OCR определяет скважность выходного сигнала.

В режиме Fast PWM период начинается с положительного значения сигнала, до тех пор пока значение TCNT не совпадет со значением регистра OCR, когда значение счетчика/таймера TCNT станет равным значению регистра сравнения OCR, происходит спад сигнала до нуля, и продолжается до начала нового периода.

Как правило, ШИМ в микроконтроллерах построен на 8-битном счетчике/таймере TCNT, который считает от 0 до 256, период которого равен T=256/Fcpu, (Fcpu –тактовая частота процессора). Например, при тактовой частоте процессора в 1 МГц, период работы счетчика составит 256 микросекунд, а частота 3906Гц. Повышение разрядности счетчика вполне возможно, но это приводит к снижению частоты ШИМ, что само по себе не желательно.

Частоту ШИМ можно определить, разделив тактовую частоту процессора на 256. Например при тактовой частоте процессора 8 МГц, частота ШИМ составит 31250Гц.

Недостатком этого режима считается смещение фазы сигналов при изменении скважности.

alt

В режиме Phase Correct PWM недостаток смещения фаз при изменении скважности устранен, за счет использования двух периодов, т.е. частота меньше в два раза в сравнении с режимом Fast PWM.

alt

В режиме Phase Correct PWM счетчик/таймер TCNT сначала считает от 0 до 256. При совпадении со значением регистра OCR, сигнал на выходе сбрасывается, затем счет в счетчике/таймере TCNT идет в обратном порядке от 256 до 0, а при совпадении значения TCNT со значением регистра OCR, сигнал на выходе устанавливается в единичное состояние.

Для того чтобы задать ШИМ в микроконтроллере нам нужно определить несколько параметров, из описания понятно, что нужно:

задать вид ШИМ и разрядность с помощью регистров WGM ,

прописать значение регистра OCR,

выставить режим работы выхода сигнала ШИМ с помощью регистров COM.

установить делители счетчика/таймера TCNT равным 1:1с помощью регистров CS

Назначения регистров WGM для tiny2313 мы уже рассматривали в предыдущих статьях в виде двух таблиц для TCNT0 и TCNT1.

Значения регистра OCR будем менять произвольно.

Подробнее рассмотрим назначение регистров COM.

Режим обычного таймера

alt

Режим Fast PWM для регистров COM0

alt

Режим Phase correct PWM для регистров COM0

alt

Режим Fast PWM для регистров COM1

alt

Режим Phase correct PWM для регистров COM1

alt

В этих таблицах показаны функции выходов OC0A, OC0B и OC1A, OC1B в зависимости от состояния регистров COM0 и COM1 (ATtiny2313 для Mega8 и 16 таблицы несколько отличаются)

Биты CS02:CS01:CS00 – для таймера/счетчика Т0, CS12:CS11:CS10 – для таймера/счетчика Т1. Из них нас интересует только CS00 или CS10.

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

Возьмем самую простую задачу – создать ШИМ сигнал в режиме Fast-PWM, на основе восьмибитного счетчика/таймера. Тогда нам потребуется прописать биты регистра управления таймера TCCR0A: COM0A1=1, WGM1=1, WGM0=1 и бит предделителя в регистре TCCR0B: CS00=1

 

 


 

 

;****************************************************************************************************************

; Автор:
; Дата:
; Версия:
; Название файла:
; Для AVR:  ATtiny2313
; Тактовая частота:  8МГц
; ***************************************************************************************************************
; Выполняемые функции:  Инициалицация ШИМ, управление двумя кнопками
; ==================================================
; .device                     ;
; .nolist                     ;
; .include                    ; Присоединение файла описаний
; .list                       ; Включение листинга
; =================================================== Псевдокоманды управления
.def     temp = r16           ; Определение основного рабочего регистра temp
.def     temp1 = r17          ; Определение дополнительного рабочего регистра temp1
.def     temp2 = r18          ; Определение дополнительного рабочего регистра temp2
.def     temp3 = r19          ; Определение дополнительного рабочего регистра temp4
.def     temp4 = r20
.def     temp5 = r21
.def     temp6 = r22
.equ     time = 9             ; Присвоение перменой time

; ================================================== Начало программного кода
.cseg                             ; Выбор сегмента программного кода
.org     0                        ; Установка текущего адреса на ноль

; =================================================== Начало программы
init:

; =================================================== Инициализация стека
ldi      temp,low(RAMEND)            ; Устанавливаем младший бит из значения RAMEND прописанного по
out      SPL,temp                    ; умолчанию в файле tn2313def.inc
.if      (RAMEND)>=0x0100            ; Если значение опреративной памяти превышает число 256 то,
ldi      temp,high(RAMEND)           ; Устанавливаем старший бит из значения RAMEND прописанного по
out      SPH,temp                    ; умолчанию в файле tn2313def.inc
.endif                               ; Конец условия

; =================================================== Инициализация Оперативной памяти
ldi      ZL,low(SRAM_START)          ; Устанавливаем адрес начала ОЗУ прописанного по
ldi      ZH,high(SRAM_START)         ; умолчанию в файле tn2313def.inc
clr      temp                        ; Очищаем r16
flush:
st       Z+,temp                     ; Обнуляем ячейку памяти
cpi      ZH,high(RAMEND+1)           ; Если не достигли конца старшего байта оперативной памяти
brne     flush                       ; то продолжаем обнулять
cpi      ZL,low(RAMEND+1)            ; Если не достигли конца младшего байта оперативной памяти
brne     flush                       ; то продолжаем обнулять
clr      ZL                          ; Очищаем индексы младшего
clr      ZH                          ; и старшего байтов памяти

; =================================================== Инициализация регистров общего назначения
ldi      ZL, 30                      ; Адрес самого старшего регистра
clr      ZH                          ; Обнуляем
dec      ZL                          ; Уменьшаем адрес на единицу
st       Z, ZH                       ; Записываем в регистр 0
brne     PC-2                        ; Зацикливаемся до полного обнуления

; =================================================== Инициализация Главного предделителя
ldi      temp,(1<
out      CLKPR, temp                 ; регистр CLKPR
clr      temp                        ; Обнуляем регистр temp
out      CLKPR, temp                 ; Деление  тактовой частоты  в регистре CLKPR равно 1

; =================================================== Инициализация портов
ldi       temp, (1<
out      PortD,temp                  ; отключает подтягивающие резисторы портов D
com      temp
out      DDRD,temp                   ; переводит все биты порта D на вывод
ser      temp
out      DDRB,temp
clr      temp
out      PortB, temp

; =================================================== Инициализация таймера T0
ldi      temp,(1

 

; =================================================== Определение скважности ШИМ
ldi      temp2, time
Correct:
out      OCR0A, temp2

; =================================================== Начало основной программы
Sensor:                                     ; Опрос кнопок
SBIS     PinD,0                      ; опрашивает  0 бит регистра ввода
ldi      temp4,0b00000001            ; и записывает в temp4 значение 1, если 0 бит равен 0 (при нажатии)
SBIS     PinD,1                      ; опрашивает  1 бит регистра ввода
ldi      temp4,0b00000010            ; и записывает в в temp4 значение 2, если 1 бит равен 0 (при нажатии)
SBRC     temp4,0                     ; если 0 бит регистра temp4 равен 1,
rjmp     plus                        ; то переход на метку plus
SBRC     temp4,1                     ; если 1 бит регистра temp4 равен 1,
rjmp     minus                       ; то переход на метку minus
rjmp     Sensor

; =================================================== Расчет шага ШИМ
plus:
rcall    delay                       ; Переход в подпрограмму задержки
ldi      temp, 121                   ; Проверяем, нет ли переполнения  при
add      temp2, temp                 ; следующем шаге
brcs     plus_1                      ; Если переполнение есть, то переходим на метку plus_1
ldi      temp, 112                   ; Если переполнения нет, смещаемся на
sub      temp2, temp                 ; один шаг вперед, равный заданному шагу скважности
rjmp     Correct                     ; Возврат на опрос кнопок

plus_1:
ldi      temp2,135                   ; Записываем конечное положение шага
rjmp     Correct                     ; Возват на опрос кнопок

minus:
rcall    delay                       ; Переход в подпрограмму задержки
ldi      temp, 10                    ; Проверяем, нет ли переполнения (результат меньше нуля)  при
sub      temp2, temp                 ; следующем шаге
brcs     minus_1                     ; Если переполнение есть, то переходим на метку minus_1
inc      temp2                       ; Если переполнения нет, смещаемся на
rjmp     Correct                     ; один шаг назад, равный заданному шагу скважности

minus_1:
ldi      temp2, 9                    ; Записываем начальное положение шага
rjmp     Correct                     ; Возврат на опрос кнопок

; =================================================== Программная задержка
delay:
clr      temp4                       ; обнулить регистр temp1
clr      temp5                       ; обнулить регистр temp2
ldi      temp6,1                     ; записать в регистр temp3 число 1

delay1:
dec      temp4                       ; вычесть из значения  регистра temp1 единицу
brne     delay1                      ; если значение temp1 не равно 0 перейти к метке Pause1
dec      temp5                       ; вычесть из значения  регистра temp2 единицу
brne     delay1                      ; если значение temp2 не равно 0 перейти к метке Pause1
dec      temp6                       ; вычесть из значения  регистра temp3 единицу
brne     delay1                      ; если значение temp1 не равно 0 перейти к метке Pause1
ret                                  ; выйти из подпрограммы

;Не будем сильно изощряться, а используем предыдущие программы как шаблоны, а для наглядности подключим две кнопк;и для управления скважностью сигнала и светодиод в качестве нагрузки. Составим схему в протеусе и после компиляц;ии немного понажимаем на кнопки. На осциллограмме хорошо видно, как меняется скважность сигнала, соответственно ;меняется напряжение на выходе, и светодиод плавно гаснет и загорается.

; Опрос кнопок идентичен предыдущей программе и в разьясении, я думаю не нуждается.

; Инициализация ШИМ:

ldi       temp,(1< out             TCCR0A, temp
ldi      temp, (1<
out      TCCR0B, temp

; =================================================== Определение скважности ШИМ
ldi      temp2, time                 ; Запись начальной константы
Correct:
out      OCR0A, temp2                ; Скважность ШИМ

;Участок программы формирования шага ШИМ построен по принципу определения переполнения, т.е. мы прибавляем (вычит;аем)по какой то константе до тех пор, пока не произойдет переполнение. Можно сделать шаг равный 1, правда пересч;ет будет идти дольше, и будет равен 254 шагам.
.equ     time = 1                    ; Присвоение перменой time
plus:
rcall    delay                       ; Переход в подпрограмму задержки
ldi      temp, 2                     ; Проверяем, нет ли переполнения  при
add      temp2, temp                 ; следующем шаге
brcs     plus_1                      ; Если переполнение есть, то переходим на метку plus_1
ldi      temp, 1                     ; Если переполнения нет, смещаемся на
sub      temp2, temp                 ; один шаг вперед, равный заданному шагу скважности
rjmp     Correct                     ; Возват на опрос кнопок

plus_1:
ldi      temp2,254                   ; Записываем конечное положение шага
rjmp     Correct                     ; Возврат на опрос кнопок

minus:
rcall    delay                       ; Переход в подпрограмму задержки
ldi      temp, 2                     ; Проверяем, нет ли переполнения (результат меньше нуля)  при
sub      temp2, temp                 ; следующем шаге
brcs     minus_1                     ; Если переполнение есть, то переходим на метку minus_1
inc      temp2                       ; Если переполнения нет, смещаемся на
rjmp     Correct                     ; один шаг назад, равный заданному шагу скважности

minus_1:
ldi      temp2, 1                    ; Записываем начальное положение шага
rjmp     Correct                     ; Возврат на опрос кнопок

;Или более простой вариант:

plus:
rcall     delay                     ; Переход в подпрограмму задержки
clz                                 ; Очистить флаг нуля
inc       temp2                     ; Переходим на один шаг и проверяем, не равен ли результат нулю
breq      plus_1                    ; Если равен, то переходим на метку plus_1
rjmp      Correct                   ; Возват на опрос кнопок

plus_1:
dec       temp2                     ; вычитаем единицу
rjmp      Correct                   ; Возврат на опрос кнопок

minus:
rcall     delay                     ; Переход в подпрограмму задержки
clz                                 ; Очистить флаг нуля
dec       temp2                     ; Переходим на один шаг и проверяем, не равен ли результат нулю
breq      minus_1                   ; Если равен, то переходим на метку minus_1
rjmp      Correct                   ; Возврат на опрос кнопок

minus_1:
inc       temp2                     ; прибавить единицу
rjmp      Correct                   ; Возврат на опрос кнопок

 

 

Начальное значение скважности задается строкой в начале программы:

.equ      time = 9                  ; Присвоение перменой time

Программную задержку можете заменить задержкой от встроенного таймера Т1, взяв из предыдущих примеров. Если Вы собираетесь использовать другие семейства, например Mega, то внимательно изучите регистры и назначение их битов. Вы убедитесь, что разница совсем небольшая, а принципы остаются общими. Даже если Вы начнете изучать ARM, быстро убедитесь, что общие принципы сохраняются.

 

Ссылка для скачивания доступна только авторизованным пользователям сайта !

 

Read 5837 times Last modified on Среда, 03 сентября 2014 11:50

Все права принадлежат ChipMK.ru. При копировании материала ссылка обязательна. 2011-2017 © ChipMK.ru

ChipMk.ru Яндекс.Метрика
PRCY.ru