/* Beispielprogramm fuer PWM-Ausgabe bei AVR-Controllern (hier AT90S8515). Das PWM-Intervall betraegt 256 * 32ęs -> 8,192ms. In diesem Intervall werden moeglichst viele nicht zusammenhaengende Einzelimpulse erzeugt, sodass bei einem Ausgabewert von 127 pro Intervall 127 Einzelimpulse mit ca. 15 kHz ausgegeben werden. Bei geringer Abstufung muss der Ausgabewert auf die moeglichen 256 Schritte skaliert werden z.B.: 0, 32, 64, 96, 128, 160, 192, 224, 255 Michael Nowak, www.mino-elektronik.de Alle Angaben ohne Gewaehr ! */ /* AT90S8515 register */ #define RAMEND 0x25f sfrb DDRA = 0x1A; /* Data Direction Register, Port A */ sfrb PORTA = 0x1B; /* Data Register, Port A */ sfrb TCCR0 = 0x33; /* Timer/Counter 0 Control Register */ sfrb TIMSK = 0x39; /* Timer/Counter Interrupt MaSK register */ sfrb SPL = 0x3D; sfrb SPH = 0x3E; sfrb SREG = 0x3F; /* Status Register */ #define RESET_vect (0x00) #define TIMER0_OVF0_vect (0x0E) rseg DATA0 pwm_wert: ds 8 ;0-7 pwm_summ: ds 8 ;zum aufsummieren aseg rjmp reset ;start org TIMER0_OVF0_vect rjmp timer0_int rseg CODE timer0_int: ; 6 + max. 4 fuer akt. Befehl push r0 ; 2 push r16 ; 2 push r17 ; 2 push r18 ; 2 in r0,SREG ; 1 ; 19 Taktzyklen ; clr r16 ; bei 8 bits nicht notwendig lds r17,pwm_wert+7 lds r18,pwm_summ+7 add r18,r17 rol r16 sts pwm_summ+7,r18 lds r17,pwm_wert+6 lds r18,pwm_summ+6 add r18,r17 rol r16 ;bei Ueberlauf ist C=1 sts pwm_summ+6,r18 lds r17,pwm_wert+5 lds r18,pwm_summ+5 add r18,r17 rol r16 ;bei Ueberlauf ist C=1 sts pwm_summ+5,r18 lds r17,pwm_wert+4 lds r18,pwm_summ+4 add r18,r17 rol r16 ;bei Ueberlauf ist C=1 sts pwm_summ+4,r18 lds r17,pwm_wert+3 lds r18,pwm_summ+3 add r18,r17 rol r16 ;bei Ueberlauf ist C=1 sts pwm_summ+3,r18 lds r17,pwm_wert+2 lds r18,pwm_summ+2 add r18,r17 rol r16 ;bei Ueberlauf ist C=1 sts pwm_summ+2,r18 lds r17,pwm_wert+1 lds r18,pwm_summ+1 add r18,r17 rol r16 ;bei Ueberlauf ist C=1 sts pwm_summ+1,r18 lds r17,pwm_wert+0 ; 2 lds r18,pwm_summ+0 ; 2 add r18,r17 ; 1 rol r16 ; 1 sts pwm_summ+0,r18 ; 2 ; 8 Takzyklen / Ausgabebit int_ende: out PORTA,r16 ; 1 fertiges bitmuster ausgeben ; weitere Interrupts (Rx/Tx) am besten hier abfragen ! ; z.B. teste Rx-Int und speichere Zeichen in Puffer out SREG,r0 ; 1 pop r18 ; 2 pop r17 ; 2 pop r16 ; 2 pop r0 ; 2 reti ; 4 ; 14 Taktzyklen ; konstante Gesamtbelastung des Prozessors mit diesem Interrupt: ; 19 + (8 * 8) + 14 -> 97 Taktzyklen; somit etwa (97/256*100%) 38% ! reset: ldi r16,LOW(RAMEND) out SPL,r16 ldi r16,HIGH(RAMEND) out SPH,r16 ldi r16,1 ;timer 0 mit vollem CPU-Takt out TCCR0,r16 ldi r16,2 out TIMSK,r16 ;overflow INT freigeben ser r16 out DDRA,r16 ;alles Ausgaenge ldi r16,16 sts pwm_wert+0,r16 ; Muster an PORTA.0 ! ldi r16,32 sts pwm_wert+1,r16 ldi r16,64 sts pwm_wert+2,r16 ldi r16,128 sts pwm_wert+3,r16 ldi r16,255 sts pwm_wert+4,r16 clr r16 sts pwm_wert+5,r16 sts pwm_wert+6,r16 sts pwm_wert+7,r16 sei ;int zulassen loop: nop rjmp loop end