ВходНаше всё Теги codebook 无线电组件 Поиск Опросы Закон Суббота
29 июня
227816 Топик полностью
MBedder, терминатор (12.12.2010 19:42, просмотров: 151) ответил mazur на Хочется сделать для небольшой искусственной елки гирлянду из светодиодов. 8 каналов. Простое переключение мне неинтересно. Хочется чтобы менялась яркость. Попытался попробовать сделать программный ШИМ и что-то не получается. Даже не могу пока
Фтыкай. Собственно, весь алгоритм - в OC1Aisr:  ;----------------------------------------------------------------------------------------- ; ; 8 channel interrupt driven 8-bit (256 steps) software PWM implementation example. ; r3..r10 hold channel duty cycle values ; PORTB pins are PWM channels' outputs (port can be redefined via PWMPORT alias) ; ; (C) MBedder, 2007 ; .include "tn2313def.inc" .def STSAV = r2 ; SREG holding register for all non-nested interrupts .def pwm = r15 ; PWM digital sawtooth generator used in Timer 1 ISR .def tmp = r16 ; General purpose temporary register .def inttmp = r25 ; Common temporary register for all non-nested interrupts .equ pwmport = PORTB ; PWM output port .equ fosc = 16000000 ; CPU clock frequency, Hz .equ fpwm = 2000 ; Desired PWM frequency, Hz (2050 Hz max @16 MIPS) .set t1val = fosc/fpwm/256-1 ; Timer 1 TOP reload value for given FPWM and FOSC .if (t1val < 30) ; Timer 1 ISR takes up to 30 clocks to execute .warning "Selected PWM frequency is too high, forcing highest available (full CPU usage!)" .set t1val = 30 .endif .cseg ;----------------------------------------------------------------------------------------- ; Interrupt vectors: rjmp reset .org OC1Aaddr rjmp OC1Aisr ;----------------------------------------------------------------------------------------- ;----------------------------------------------------------------------------------------- reset: ldi tmp,low(RAMEND) out SPL,tmp ; Stack pointer initialization .ifdef SPH ldi tmp,high(RAMEND) out SPH,tmp .endif ldi tmp,0xFF ; Set up PB0..7 as outputs out DDRB,tmp ldi tmp,32*1 ; Initialize r3..r10 (PWM channel values) mov r3,tmp ; ldi tmp,32*2 ; mov r4,tmp ; ldi tmp,32*3 ; mov r5,tmp ; ldi tmp,32*4 ; mov r6,tmp ; ldi tmp,32*5 ; mov r7,tmp ; ldi tmp,32*6 ; mov r8,tmp ; ldi tmp,32*7 ; mov r9,tmp ; ldi tmp,32*8-2 ; mov r10,tmp ; rcall init_timer1 ; Set up Timer 1 sei ; Enable interrupts rjmp PC ; Loop forever ;----------------------------------------------------------------------------------------- ;----------------------------------------------------------------------------------------- ; Timer 1 initialization (Clear Timer on Compare match - CTC mode). ; Timer 1 runs at Fosc in CTC mode with overlow rate derived from a desired PWM frequency. init_timer1: ldi tmp,high(t1val) ; Initialize TOP register (OCR1A) and Timer 1: out OCR1AH,tmp ; High byte first out TCNT1H,tmp ; Reset Timer 1 to get correct 1st result ldi tmp,low(t1val) ; out OCR1AL,tmp ; Low byte last out TCNT1L,tmp ; ldi tmp,(1<<WGM12)|(1<<CS10) ; CTC mode, T1CLK = Fosc out TCCR1B,tmp ; in tmp,TIMSK ; Enable OC1A interrupts sbr tmp,1<<OCIE1A ; out TIMSK,tmp ; ret ;----------------------------------------------------------------------------------------- ;----------------------------------------------------------------------------------------- ; Timer1 (CTC mode) compare match ISR - single 8-bit software PWM step. ; 24 clocks, 21 program words OC1Aisr: in stsav,SREG ; Save SREG to STSAV reserved register inc pwm ; Advance PWM sawtooth generator cp r3,pwm ; CARRY = 1 if Rx <= PWM - 2 clocks per PWM channel rol inttmp ; Shift in the CARRY to an INTTMP cp r4,pwm ; CARRY = 1 if Rx <= PWM - 2 clocks per PWM channel rol inttmp ; Shift in the CARRY to an INTTMP cp r5,pwm ; CARRY = 1 if Rx <= PWM - 2 clocks per PWM channel rol inttmp ; Shift in the CARRY to an INTTMP cp r6,pwm ; CARRY = 1 if Rx <= PWM - 2 clocks per PWM channel rol inttmp ; Shift in the CARRY to an INTTMP cp r7,pwm ; CARRY = 1 if Rx <= PWM - 2 clocks per PWM channel rol inttmp ; Shift in the CARRY to an INTTMP cp r8,pwm ; CARRY = 1 if Rx <= PWM - 2 clocks per PWM channel rol inttmp ; Shift in the CARRY to an INTTMP cp r9,pwm ; CARRY = 1 if Rx <= PWM - 2 clocks per PWM channel rol inttmp ; Shift in the CARRY to an INTTMP cp r10,pwm ; CARRY = 1 if Rx <= PWM - 2 clocks per PWM channel rol inttmp ; Shift in the CARRY to an INTTMP out pwmport,inttmp ; Set PWM 1..8 pins to new states out SREG,stsav ; Restore SREG from STSAV reserved register reti ;-----------------------------------------------------------------------------------------