Страница 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.

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