помогите сделать диммер на авр
помогите сделать диммер на авр
Всем привет! Очень нужна помощь... Нужно сделать светодиодный диммер на атмега16 на плате стк500. Собственно есть 8 светодиодов, кнопка и переменный резистор. Кнопкой нужно включать все светодиоды, а переменник нужен для того, чтобы плавно регулировать их яркость.
Кто-нибудь сможет помочь с написанием программы на ассемблере?
Кто-нибудь сможет помочь с написанием программы на ассемблере?
Re: помогите сделать диммер на авр
какой еще переменный резистор? 21 век на носу... ШИМ рулит, на шестнадцатой меги их аж 4, а вам я так понимаю один нужен для регулировки интенсивности свечения светодиодов. 

Re: помогите сделать диммер на авр
Именно! Можете помочь? Я просто совсем в этом не разбираюсь, а сделать очень нужно...
- coredumped
- Опытный кот
- Сообщения: 838
- Зарегистрирован: Вт апр 12, 2011 18:38:19
- Откуда: с Земли
Re: помогите сделать диммер на авр
Лабораторная работа?
Все будет только лучше, в крайнем случае - хуже.
Re: помогите сделать диммер на авр
coredumped, нет. Курсовой проект. Поможете?
- coredumped
- Опытный кот
- Сообщения: 838
- Зарегистрирован: Вт апр 12, 2011 18:38:19
- Откуда: с Земли
Re: помогите сделать диммер на авр
Поможем. Что именно не получается? Для начала научитесь включать и выключать светодиоды.
1. разберитесь к какому порту подключены светодиоды
2. напишите инициализацию
Если знаний вообще 0, пишите, вечером кину скелетик программки с инициализацией портов-стека-прерываний для меги16.
1. разберитесь к какому порту подключены светодиоды
2. напишите инициализацию
Если знаний вообще 0, пишите, вечером кину скелетик программки с инициализацией портов-стека-прерываний для меги16.
Все будет только лучше, в крайнем случае - хуже.
Re: помогите сделать диммер на авр
Я тут уже накидал примерный код. Не знаю, насколько правильно. Посмотрите во вложенном файле. Кто что думает по этому поводу?
- Вложения
-
- dimmer.asm
- (2.57 КБ) 356 скачиваний
- coredumped
- Опытный кот
- Сообщения: 838
- Зарегистрирован: Вт апр 12, 2011 18:38:19
- Откуда: с Земли
Re: помогите сделать диммер на авр
Вот примерчик инцнализации и запуска таймера0 в режиме Fast PWM. Это самый "правильный" метод регулирования яркости. Нужно просто занести нужное значение от 0 до 255 в регистр OCR0 и все. Все что осталось - это написать обработку нажатия кнопок (не забываем про устранение дребезга)
Светодиоды в этом примере поключены к порту A. Можете задавать вопросы, но остальное делайте сами, иначе ничему не научитесь.
Из особенностей здесь один момент - регистры, используемые в прерываниях не используются в качестве рабочих в основной программе. Это сделано для того, чтоб не сохранять их в стеке. Те в нашем примере регистр r2 не должен использоваться в основной программе - его предназначение - сохранение флагов при вызове обработчиков прерываний. Вообще, по-правильному нужно сохранять регистр флагов при вызове обработчика прерываний и регистры, которые он(обработчик) использует, если их изменение в основной программе не должно происходить. При выходе, соответственно, регистры восстанавливаются. Обычно для этого используют стек (команды push и pop). Но это не есть правило! Вы должны понимать, что делаете и для чего. Если регистров хватает, то нужно использовать их так, чтоб избегать использования RAM без особой нужды - это повысит эффективность программы.
Вот пример вызова обработчика прерывания с сохранением регистра флагов. Если флаги используются в основной программе (например переходы по условию), то сохранять их нужно обязательно, иначе обработчик прерывания может их изменить в самый неподходящий момент.
OC1B_int:
push r2 ; save r2 in stack
in r2, SREG ; save status reg in r2
push r16 ; save r16
.... обработчик
pop r16 ; restore r16
out SREG, r2 ; restore flags
pop r2 ; restore r2
reti
PS: использовать мегу16 для диммера - это расточительство. Для этого есть более дешевые tiny. Это так, мысли в слух. Для курсака конечно пофиг, а для реальной разработки - это экономическое преступление
Светодиоды в этом примере поключены к порту A. Можете задавать вопросы, но остальное делайте сами, иначе ничему не научитесь.
Код: Выделить всё
.include "m16def.inc"
; Registers aliases - для удобства восприятия
.def A = r16
.def ctrl = r17 ; здесь маска включенных светодиодов (0xff - включены все)
.def bright = r18 ; это яркость (скважность ШИМ)
.cseg
; Interrupt vectors
.org 0x0 ;Reset Vector
rjmp Reset
.org INT0addr ; External Interrupt Request 0
reti
.org INT1addr ; External Interrupt Request 1
reti
.org OC2addr ; Timer/Counter2 Compare Match
reti
.org OVF2addr ; Timer/Counter2 Overflow
reti
.org ICP1addr ; Timer/Counter1 Capture Event
reti
.org OC1Aaddr ; Timer/Counter1 Compare Match A
reti
.org OC1Baddr ; Timer/Counter1 Compare Match B
reti
.org OVF1addr ; Timer/Counter1 Overflow
reti
.org OVF0addr ; Timer/Counter0 Overflow
rjmp OVF0_int
.org SPIaddr ; Serial Transfer Complete
reti
.org URXCaddr ; USART, Rx Complete
reti
.org UDREaddr ; USART Data Register Empty
reti
.org UTXCaddr ; USART, Tx Complete
reti
.org ADCCaddr ; ADC Conversion Complete
reti
.org ERDYaddr ; EEPROM Ready
reti
.org ACIaddr ; Analog Comparator
reti
.org TWIaddr ; 2-wire Serial Interface
reti
.org INT2addr ; External Interrupt Request 2
reti
.org OC0addr ; Timer/Counter0 Compare Match
rjmp OC0_int
.org SPMRaddr ; Store Program Memory Ready
reti
Reset:
; set Stack Pointer to top of RAM
ldi A, high(RAMEND)
out SPH, A
ldi A, low(RAMEND)
out SPL, A
; initialize consts
clr r0 ; r0 = 0
clr r1
dec r1 ; r1 = 0xFF
; I/O setup
out DDRA, r1 ; set all PORTA lines as output (DDRA=0xFF)
out PORTA, r0 ;
; timer0 setup
ldi A,(1<<OCIE0)|(1<<TOIE0) ; enable timer1 interrupts
out TIMSK, A
; clear timer0 counter
out TCNT0, r0
; set 50% PWM
ldi bright, 0x7F
out OCR0, bright
; set timer0 to Fast PWM mode
ldi A, (1<<WGM01)|(1<<WGM00)|(1<<CS01)
out TCCR0, A ; Start timer0, prescaler=8
sei ; enable interrupts
ser ctrl ; switch-on all LEDs
; main loop
loop: nop
; здесь пишем остальной код - проверка нажатия кнопок, реакция на кнопки итд
rjmp loop
OVF0_int:
in r2, SREG ; save status
out PORTA, ctrl ; set all PA lines to ctrl
out SREG, r2 ; restore status
reti
OC0_int:
in r2, SREG ; save status
out PORTA, r0 ; set all PA lines to 0
out SREG, r2 ; restore status
reti
Из особенностей здесь один момент - регистры, используемые в прерываниях не используются в качестве рабочих в основной программе. Это сделано для того, чтоб не сохранять их в стеке. Те в нашем примере регистр r2 не должен использоваться в основной программе - его предназначение - сохранение флагов при вызове обработчиков прерываний. Вообще, по-правильному нужно сохранять регистр флагов при вызове обработчика прерываний и регистры, которые он(обработчик) использует, если их изменение в основной программе не должно происходить. При выходе, соответственно, регистры восстанавливаются. Обычно для этого используют стек (команды push и pop). Но это не есть правило! Вы должны понимать, что делаете и для чего. Если регистров хватает, то нужно использовать их так, чтоб избегать использования RAM без особой нужды - это повысит эффективность программы.
Вот пример вызова обработчика прерывания с сохранением регистра флагов. Если флаги используются в основной программе (например переходы по условию), то сохранять их нужно обязательно, иначе обработчик прерывания может их изменить в самый неподходящий момент.
OC1B_int:
push r2 ; save r2 in stack
in r2, SREG ; save status reg in r2
push r16 ; save r16
.... обработчик
pop r16 ; restore r16
out SREG, r2 ; restore flags
pop r2 ; restore r2
reti
PS: использовать мегу16 для диммера - это расточительство. Для этого есть более дешевые tiny. Это так, мысли в слух. Для курсака конечно пофиг, а для реальной разработки - это экономическое преступление
Все будет только лучше, в крайнем случае - хуже.
Re: помогите сделать диммер на авр
Просто у нас на кафедре есть модули STK500, там стоит мега 16) поэтому и курсач на меге 16.
Большое спасибо за ответ! Буду разбираться дальше!
Большое спасибо за ответ! Буду разбираться дальше!