Mal die Timer 2 Idee:

Du initialisierst den Timer2, damit er mit einem Teilerfaktor von 1024 von der Taktfrequenz des Controllers läuft.
Du gibst den Output Comparematch 2 interrupt frei.
Du setzt das OCR2 Register auf 1.
Du gibst mit SEI alle Interrupts frei.

Das war schon mal die Initialisierung.

Jetzt musst Du noch die OCR Interrupt Routine schreiben.

1. Alle verwendeten Register + SREG auf dem Stack sichern "PUSH"

2. Du liest das OCR2 Register aus und vergleichst mit diesem Wert deine gewünschten PWM Werte.
Ist der OCR Wert kleiner oder gleich wird der entsprechende Kanal angeschaltet.
Ist der OCR Wert größer wird der entsprechende Kanal abgeschaltet.

3. Nun noch den OCR Wert um 1 erhöhen und schauen ob er nun den Wert 0 hat (läuft nach 256 Zyklen wieder auf 0, da ja nur 8 Bit).

4. Den OCR Wert in das OCR2 Register schreiben.

5. Hat der OCR Wert den Wert 0, nochmals um 1 erhöhen und in das OCR2 Register des Timers 2 zurückschreiben.

6. Gesicherte Register + SREG mit POP wieder zurückschreiben.


Codeschnipsel:
Code:
PUSH r16
IN r16,SREG
PUSH r16
PUSH r17
IN r16,OCR2
LDS r17,pwm1
CP r17,r16
BRCC k1ein
CBI PORTB,0 ; 1.Kanal aus
RJMP k2
k1ein:
SBI PORTB,0 ; 1. Kanal ein

k2:
LDS r17,pwm2
CP r17,r16
BRCC k2ein
CBI PORTB,1 ; 2.Kanal aus
RJMP k3
k2ein:
SBI PORTB,1 ; 1. Kanal ein

k3:
usw, usw, für alle PWM Kanäle......

INC r16
BRNE writeocr2
INC r16
writeocr2:
OUT OCR2,r16

POP r17
POP r16
OUT SREG,r16
POP r16
RETI
Das wars, deine Software PWM ist fertig.

Welche Register für die benötigten Teilerfaktoren, Interruptfreigaben wie beschrieben werden müssen, müsste ich jetzt selber im Datenblatt nachschauen, aber das kannst Du ja selber auch machen.

Hinweis:
Das mit dem 2x Erhöhen beim Wert 0 brauchst Du um die LED's auch mal ganz abschalten zu können, bei OCR2=0 und PWM Wert 0 würde sonst der entsprechende Kanal kurz eingeschaltet.