Страница 1 из 1

помогите сделать диммер на авр

Добавлено: Пт янв 27, 2012 19:59:44
pesn
Всем привет! Очень нужна помощь... Нужно сделать светодиодный диммер на атмега16 на плате стк500. Собственно есть 8 светодиодов, кнопка и переменный резистор. Кнопкой нужно включать все светодиоды, а переменник нужен для того, чтобы плавно регулировать их яркость.

Кто-нибудь сможет помочь с написанием программы на ассемблере?

Re: помогите сделать диммер на авр

Добавлено: Пт янв 27, 2012 21:05:05
jordan
какой еще переменный резистор? 21 век на носу... ШИМ рулит, на шестнадцатой меги их аж 4, а вам я так понимаю один нужен для регулировки интенсивности свечения светодиодов. :kill:

Re: помогите сделать диммер на авр

Добавлено: Вс янв 29, 2012 17:09:42
pesn
Именно! Можете помочь? Я просто совсем в этом не разбираюсь, а сделать очень нужно...

Re: помогите сделать диммер на авр

Добавлено: Пн янв 30, 2012 13:35:24
coredumped
Лабораторная работа?

Re: помогите сделать диммер на авр

Добавлено: Пн янв 30, 2012 21:57:24
pesn
coredumped, нет. Курсовой проект. Поможете?

Re: помогите сделать диммер на авр

Добавлено: Вт янв 31, 2012 10:45:21
coredumped
Поможем. Что именно не получается? Для начала научитесь включать и выключать светодиоды.
1. разберитесь к какому порту подключены светодиоды
2. напишите инициализацию
Если знаний вообще 0, пишите, вечером кину скелетик программки с инициализацией портов-стека-прерываний для меги16.

Re: помогите сделать диммер на авр

Добавлено: Вт янв 31, 2012 16:20:09
pesn
Я тут уже накидал примерный код. Не знаю, насколько правильно. Посмотрите во вложенном файле. Кто что думает по этому поводу?

Re: помогите сделать диммер на авр

Добавлено: Ср фев 01, 2012 00:10:13
coredumped
Вот примерчик инцнализации и запуска таймера0 в режиме Fast PWM. Это самый "правильный" метод регулирования яркости. Нужно просто занести нужное значение от 0 до 255 в регистр OCR0 и все. Все что осталось - это написать обработку нажатия кнопок (не забываем про устранение дребезга)
Светодиоды в этом примере поключены к порту 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. Это так, мысли в слух. Для курсака конечно пофиг, а для реальной разработки - это экономическое преступление :shock:

Re: помогите сделать диммер на авр

Добавлено: Ср фев 01, 2012 15:29:45
pesn
Просто у нас на кафедре есть модули STK500, там стоит мега 16) поэтому и курсач на меге 16.

Большое спасибо за ответ! Буду разбираться дальше!