Простой программный ШИМ на несколько каналов
|
|
VasylYE | Дата: Воскресенье, 12.10.2008, 23:41 | Сообщение # 1 |
Рядовой
Группа: Проверенные
Сообщений: 263
Статус: 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
А нам своє робить!
|
|
| |
ЛЕВША | Дата: Понедельник, 13.10.2008, 17:47 | Сообщение # 2 |
Admin
Группа: Администраторы
Сообщений: 1923
Статус: Offline
| круто! ждем продолжения! я сейчас на пиках без ШИМ-а, пытаюсь сделать пошаговый ШИМ програмно, если получится поделюсь.
упростить - улучшить! если ВЫ хотите помочь сайту в развитии, наши счета: Z789673670495 ($) R806233314616 ® 41001205775274(yand)
|
|
| |
VasylYE | Дата: Вторник, 14.10.2008, 01:20 | Сообщение # 3 |
Рядовой
Группа: Проверенные
Сообщений: 263
Статус: 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 будет считать до переполнения (для пиков нужно прописать соответствующий регистр). После этого идет бесконечный цикл, в котором мк ничего не делает (для нашего примера, на самом деле туда можно набросать что угодно ). Основной цикл программы Когда мы создали новый макрос, у нас появилось еще одно окно со структурой BEGIN-END. Это и будет обработчик прерываний. Первым делом нам нужно перезагрузить регистр таймера Т0, что и делаем в блоке С код (TCNT0 = 0xF8;). Далее увеличиваем значение переменной Counter0 на единицу (в блоке Calculation). потом идет проверка - равно ли значение Counter0 значению переменной Capture0? если ответ верный, тогда на порту PORTB0 устанавливаем высокий уровень. потом еще одна проверка - если значение Counter0 равно 0 (наступило переполнение), тогда на порт PORTB0 выставляем низкий уровень. К сожалению, симуляция в фловкоде идет очень медленно, поэтому приходится долго ждать. лучше получить хекс файл и загнать его в протеус. Обработчик прерывания
А нам своє робить!
|
|
| |
VasylYE | Дата: Вторник, 14.10.2008, 01:25 | Сообщение # 4 |
Рядовой
Группа: Проверенные
Сообщений: 263
Статус: Offline
| В архиве собственно проект Flowcode (мега16, но главное, как уже говорилось, принцип). Для получения нескольких каналов ШИМ нужно создать соотв. пары CounterN и CaptureN, и в обработчике прерывания аналогично их использовать. Для изменения коеф. модуляции нужно изменять переменную CaptureN для соотв. канала. Позже покажем, как это делать.
А нам своє робить!
|
|
| |
любитель | Дата: Вторник, 17.02.2009, 19:45 | Сообщение # 5 |
Лейтенант
Группа: Проверенные
Сообщений: 44
Статус: Offline
| случайно попал в эту ветку.сразу замечание.желательно в названии темы упомянуть.что и для Flowcode это тоже подходит.а то тем много, а нужное можно и прохлопать.
|
|
| |
nicolasomsk | Дата: Суббота, 14.01.2012, 17:35 | Сообщение # 6 |
Рядовой
Группа: Пользователи
Сообщений: 1
Статус: Offline
| Ясно:( Добавлено (14.01.2012, 17:35) --------------------------------------------- Воссоздал в железе шим на одном СД понял ка им управлять, но мозг вскипел, когда потребовалось изготовить казалось бы детскую игрушку- бегущий туда-сюда огонь, естественно необходимо плавно нарастить и уменьшить шим (как буд-то конденсаторы в параллели стоят) С нетерпением жду продолжения:)
|
|
| |
VasylYE | Дата: Вторник, 17.01.2012, 19:57 | Сообщение # 7 |
Рядовой
Группа: Проверенные
Сообщений: 263
Статус: Offline
| Для построения гирлянды с бегущим огнем, нужно несколько выходов, коэффициент модуляции для которых изменяется периодически, и для каждого канала в каждый момент времени он разный:
код добавлю позже
А нам своє робить!
|
|
| |
VasylYE | Дата: Среда, 01.02.2012, 13:43 | Сообщение # 8 |
Рядовой
Группа: Проверенные
Сообщений: 263
Статус: Offline
| Для упрощения программы число каналов лучше выбирать как степень 2: - 4,8,16 для этого примера взято 4 канала.
Алгоритм такой: Для каждого канала коэффициент ШИМ записан в соответствующую ячейку памяти CaptureХ Содержимое этих ячеек циклически изменяется. Скорость изменения является скоростью передвижения бегущего огня (хранится в переменной speed)
Для изменения скорости в работе - можно использовать АЦП, подавая напряжение на него с переменного резистора, и в зависимости от полученного значения изменять переменную speed
код на ассемблере в архиве
сигнал на выходах РВ0 РВ1 РВ2 РВ3
В архиве проект для VMLAB для FLOWCODE сделаем позже
А нам своє робить!
|
|
| |
|