Технический Портал Левши Пятница, 29.03.2024, 18:47
| RSS
[ Новые сообщения · Участники · Правила форума · Поиск · RSS ]
  • Страница 1 из 1
  • 1
Модератор форума: terpelivi, VasylYE  
ТЕХНИЧЕСКИЙ ФОРУМ » ЭЛЕКТРОНИКА » МИКРОКОНТРОЛЛЕРЫ » Простой программный ШИМ на несколько каналов (Принципы построения программного ШИМ)
Простой программный ШИМ на несколько каналов
VasylYEДата: Воскресенье, 12.10.2008, 23:41 | Сообщение # 1
Рядовой
Группа: Проверенные
Сообщений: 263
Награды: 1
Статус: Offline
В одной из тем поднимался вопрос насчет ШИМ. Что делать, если МК имеет один таймер без встроенного ШИМ? Это можно решить программно.
Для начала построим одноканальный ШИМ в котором для лучшей наглядности скважность импульсов будет периодически изменяться программой.
Суть програмнмного ШИМ заклчючается в следующем. У нас есть регистр или переменная, которая увеличивается через определенный период времени. Назовем ее Counter0 (счетчик для нулевого канала, так как в перспективе количество аканалов можно нароситить). Также у нас есть другой регистр или переменная, которая отчвечает за скважность импульсов или коеффициент модуляции. Назовем ее Capture0 (может название и невсовсем удачное, но все же). Во время увеличения переменной Counter0 происходит сравнение ее значения со значением, записанным в Capture0. Если они равны, то на выходе канала устанавливаем высокий уровень.
В момент переполнения переменной Counter0 (для простоты у нас переменные 8-битные, что для не очень сложных приложений польностью достаточно), она обнуляется, также на выходе канала устанавливаем низкий уровень. Для большей наглядности в это же время изменяем Capture0 (в реальном приложении она должна изменяться в зависимости от того, что мы хотим получить).
Code

; ******************************************************
; Простой генератор ШИМ
; ******************************************************
.include "C:\VMLAB\include\m16def.inc"
; Здесь определяем переменные  и символьные имена
;
.def  temp  =r16
.def temp1 =r17

.EQU PortLoad    =PORTB    ;Символьное имя для порта
     ;к которому подключены нагрузки
.EQU Ch_0    = 0  ;канал 0

.EQU period = 0xF0    ;Определяем счетчик для  Т0

.EQU Capt0start = 0x8F    ; Начальный коэффициент ШИМ для нулевого канала

; Вектора сброса и прерываний
;
.ORG 0x0000
reset:
jmp start

.ORG OVF0addr
jmp T0_overflow

.ORG 0x002A
; Отсюда программа начинает работу после сброса  или вкюлючения питания
;
start:
  ldi temp, HIGH(RAMEND) ; инициализация стека
  out SPH, temp
  ldi temp, LOW(RAMEND)
  out SPL, temp
   
; К порту PORTB подключаются нагрузкри
; настраиваем его на выход, нагрузки инвертированы
  ldi temp, 0xFF
  out PortLoad, temp
  out DDRB, temp
   
;Инициализация программных таймеров

;Инициализация таймера Т0
  ldi temp, period
  out TCNT0, temp  ;Загрузка таймера Т0
   
  ldi temp, (1<<TOIE0)
  out TIMSK, temp  ;Разрешаем прерывания по
         ;переполнению Т0
   
  ldi temp, (1<<CS01)
  out TCCR0, temp  ;делитель /8

;Обнуление регистров программного ШИМ
  ldi temp, 0x00
  sts Counter0, temp
  ldi temp, Capt0start
  sts Capture0, temp
   

;Разрешаем глобальные прерывания
  sei

forever:
    nop
    nop       ; Бесконечный цикл
    nop       ;
    nop       ;
rjmp forever

;Обработчик прерывания по переполнению
;таймера Т0 (аппаратный таймер)
T0_overflow:
  ldi temp, period
  out TCNT0, temp  ;перезагрузка таймера Т0
   
  ;Увеличиваем Счетчик нулевого канала
  lds temp, Counter0    ;Загружаем во временный регистр значение
         ;счетчика нулевого канала
  inc temp             ;увеличиваем на единицу
  breq Cnt0_ovf        ;проверяем на переполнение
    sts Counter0, temp    ;Если не переполнение, сохраняем назад в SRAM

  ;Загружаем в регистр temp1 значение для сравнения
  lds temp1, Capture0
  ;Сравниваем значения счетчика и заданного значения коеф. ШИМ
  cp temp, temp1
  breq Set_Ch0    ;Если равно, переходим к включению соотв. канала
reti    ; иначе выходим из прерывания  

Cnt0_ovf:    ;Сюда попадаем, если переполнился счетчик нулевого канала
  ldi temp, 0x00
  sts Counter0, temp
  sbi PortLoad, Ch_0    ;отключаем нулевой канал

;Для большей наглядности, изменяем коеффициент ШИМ
  lds temp, Capture0
  dec temp
  sts Capture0, temp

reti    ;    end

Set_Ch0:
    cbi PortLoad, Ch_0   ; Включаем нулевой канал (Инвертирован!)
reti

;Инициализация программных счетчиков в SRAM
.DSEG
Counter0:    .BYTE    1    ;Счетчик 0 для нулевого канала ШИМ
Capture0:    .BYTE    1    ;Регистр захвата для нулевого канала ШИМ

Позже постараюсь слепить аналогичныей пример для FlowCode
Здесь же важно пронять сам принцип Также на будущее увеличим число каналов и возможность изменять коэфф. модуляции для каждого канала отдельно например переменными резисторами.
в архиве - проект VMlab

На рисунке - момент перехода каоэфф. модуляции от при уменьшении от 0 до 255

Прикрепления: simple_pwm.rar (9.7 Kb) · 3806288.gif (11.0 Kb)


А нам своє робить!
 
ЛЕВШАДата: Понедельник, 13.10.2008, 17:47 | Сообщение # 2
Admin
Группа: Администраторы
Сообщений: 1923
Награды: 2
Статус: Offline
круто! ждем продолжения! smile
я сейчас на пиках без ШИМ-а, пытаюсь сделать пошаговый ШИМ програмно, если получится поделюсь.


упростить - улучшить!
если ВЫ хотите помочь сайту в развитии,
наши счета:
Z789673670495 ($)
R806233314616 ®
41001205775274(yand)
 
VasylYEДата: Вторник, 14.10.2008, 01:20 | Сообщение # 3
Рядовой
Группа: Проверенные
Сообщений: 263
Награды: 1
Статус: Offline
То же самое только для FlowCode. Используется таймер Т0 только для отсчета временных интервалов (подойдет любой МК). Выходом для нулевого канала у нас служит PORTB0. Соответственно, первым делом, устанавливаем его равным 1 (пункт сразу после BEGIN). Далее у нас идет блок Calculation, в котором мы создаем две переменные Counter0 и Capture0 байтового типа и проводим их инициализацию. Следующим шагом происходит инициализация таймера Т0 (блок Interrupt). В нем делаем разрешение прерывания по переполнению таймера Т0, при прерывании будет вызываться макрос, назовем его T0overflow (при нажатии на кнопку Create New Macro). Далее идет немножко С кода (в соотв. блоке). Вот что мы там напишем
Code

#include "iom16.h";
TCNT0 = 0xF8;

Файл iom16.h содержит символьное описание узлов выбранного нами МК, и его нужно подбросить в тот каталог, где сохранен файл фловкода. TCNT0 = 0xF8 задает число, от которого таймер Т0 будет считать до переполнения (для пиков нужно прописать соответствующий регистр).
После этого идет бесконечный цикл, в котором мк ничего не делает (для нашего примера, на самом деле туда можно набросать что угодно smile ).

Основной цикл программы

Когда мы создали новый макрос, у нас появилось еще одно окно со структурой BEGIN-END. Это и будет обработчик прерываний. Первым делом нам нужно перезагрузить регистр таймера Т0, что и делаем в блоке С код (TCNT0 = 0xF8;).
Далее увеличиваем значение переменной Counter0 на единицу (в блоке Calculation).
потом идет проверка - равно ли значение Counter0 значению переменной Capture0? если ответ верный, тогда на порту PORTB0 устанавливаем высокий уровень.
потом еще одна проверка - если значение Counter0 равно 0 (наступило переполнение), тогда на порт PORTB0 выставляем низкий уровень.
К сожалению, симуляция в фловкоде идет очень медленно, поэтому приходится долго ждать.
лучше получить хекс файл и загнать его в протеус.

Обработчик прерывания

Прикрепления: 5411430.gif (5.8 Kb) · 2246448.gif (8.2 Kb)


А нам своє робить!
 
VasylYEДата: Вторник, 14.10.2008, 01:25 | Сообщение # 4
Рядовой
Группа: Проверенные
Сообщений: 263
Награды: 1
Статус: Offline
В архиве собственно проект Flowcode (мега16, но главное, как уже говорилось, принцип).
Для получения нескольких каналов ШИМ нужно создать соотв. пары CounterN и CaptureN, и в обработчике прерывания аналогично их использовать.
Для изменения коеф. модуляции нужно изменять переменную CaptureN для соотв. канала. Позже покажем, как это делать.
Прикрепления: simle_fcw.rar (10.7 Kb)


А нам своє робить!
 
любительДата: Вторник, 17.02.2009, 19:45 | Сообщение # 5
Лейтенант
Группа: Проверенные
Сообщений: 44
Награды: 0
Статус: Offline
случайно попал в эту ветку.сразу замечание.желательно в названии темы упомянуть.что и для Flowcode это тоже подходит.а то тем много, а нужное можно и прохлопать.
 
nicolasomskДата: Суббота, 14.01.2012, 17:35 | Сообщение # 6
Рядовой
Группа: Пользователи
Сообщений: 1
Награды: 0
Статус: Offline
Ясно:(

Добавлено (14.01.2012, 17:35)
---------------------------------------------
Воссоздал в железе шим на одном СД понял ка им управлять, но мозг вскипел, когда потребовалось изготовить казалось бы детскую игрушку- бегущий туда-сюда огонь, естественно необходимо плавно нарастить и уменьшить шим (как буд-то конденсаторы в параллели стоят) С нетерпением жду продолжения:)

 
VasylYEДата: Вторник, 17.01.2012, 19:57 | Сообщение # 7
Рядовой
Группа: Проверенные
Сообщений: 263
Награды: 1
Статус: Offline
Для построения гирлянды с бегущим огнем, нужно несколько выходов, коэффициент модуляции для которых изменяется периодически, и для каждого канала в каждый момент времени он разный:


код добавлю позже
Прикрепления: 9143574.gif (20.5 Kb)


А нам своє робить!
 
VasylYEДата: Среда, 01.02.2012, 13:43 | Сообщение # 8
Рядовой
Группа: Проверенные
Сообщений: 263
Награды: 1
Статус: Offline
Для упрощения программы число каналов лучше выбирать как степень 2: - 4,8,16
для этого примера взято 4 канала.

Алгоритм такой:
Для каждого канала коэффициент ШИМ записан в соответствующую ячейку памяти CaptureХ
Содержимое этих ячеек циклически изменяется.
Скорость изменения является скоростью передвижения бегущего огня (хранится в переменной speed)

Для изменения скорости в работе - можно использовать АЦП, подавая напряжение на него с переменного резистора, и в зависимости от полученного значения изменять переменную speed

код на ассемблере в архиве

сигнал на выходах РВ0 РВ1 РВ2 РВ3


В архиве проект для VMLAB
для FLOWCODE сделаем позже
Прикрепления: sim_pwm.rar (47.1 Kb) · 9118966.gif (35.0 Kb)


А нам своє робить!
 
ТЕХНИЧЕСКИЙ ФОРУМ » ЭЛЕКТРОНИКА » МИКРОКОНТРОЛЛЕРЫ » Простой программный ШИМ на несколько каналов (Принципы построения программного ШИМ)
  • Страница 1 из 1
  • 1
Поиск:

Copyright MyCorp © 2024