Фтыкай. Собственно, весь алгоритм - в 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
;-----------------------------------------------------------------------------------------