Das folgende Codebeispiel soll als Ergänzung dienen. Oft wird gewünscht, eine LED zu dimmen. Dies ist elektronisch korrekt nur möglich, in dem die LED mit kurzen Signalimpulsen angesteuert wird: per PWM.
Der Code läßt drei LEDs an PORTD unterschiedlich schnell unterschiedlich hell und dunkel werden. 
Code:
/*
 *   Läßt drei LEDs per Software PWM hell und dunkel werden.
 *
 *   XII/2013 Florian Schäffer
 *
 *   ATmega168
 *   8 MHz Quarz
 *   avrdude -p atmega168 -P com3 -c stk500v2 -B1.5 -E -U lfuse:w:0xf7:m -U hfuse:w:0xde:m
 *
 */
#include <avr/io.h>
#include <avr/interrupt.h>
#define LED0_DDR  DDRD      // Datenrichtungsregister
#define LED0_PORT PORTD      // Datenport
#define LED0_BIT  0         // welches Bit am Port
#define LED0_min  80      // Minimale Helligkeit (0..255)
#define LED0_max  200      // Maximale Helligkeit (0..255)
#define LED0_step 30      // Schrittweite/Geschwindigkeit (1..254), je größer die Zahl, desto schneller der helligkeitswechsel
#define LED1_DDR  DDRD
#define LED1_PORT PORTD
#define LED1_BIT  1
#define LED1_min  0
#define LED1_max  255
#define LED1_step 5
#define LED2_DDR  DDRD
#define LED2_PORT PORTD
#define LED2_BIT  2
#define LED2_min  15
#define LED2_max  255
#define LED2_step 15
int main (void);
volatile uint8_t cnt = 0;
volatile int16_t led0_cnt = 0;
volatile uint8_t led0_dir = 0;
volatile int16_t led1_cnt = 0;
volatile uint8_t led1_dir = 0;
volatile int16_t led2_cnt = 0;
volatile uint8_t led2_dir = 0;
uint8_t timermin = 220;            // Timer 0 läuft von timermin bis 255, Wert beeinflußt das Flackern/die "Bildwiederholfrequenz". 200 = leichtes Flimmern. 220 = kein Flimmern
// Timer 0 Überlauf 
ISR (TIMER0_OVF_vect)
{
   cnt++;
   // LED 0
   if (cnt >= led0_cnt)
      LED0_PORT &= ~(1 << LED0_BIT);   // aus
   else
      LED0_PORT |= (1 << LED0_BIT);   // ein
   // LED 1
   if (cnt >= led1_cnt)
      LED1_PORT &= ~(1 << LED1_BIT);   // aus
   else
      LED1_PORT |= (1 << LED1_BIT);   // ein
   // LED 2
   if (cnt >= led2_cnt)
      LED2_PORT &= ~(1 << LED2_BIT);   // aus
   else
      LED2_PORT |= (1 << LED2_BIT);   // ein
   TCNT0 = timermin;
}
// Timer 1 Überlauf
ISR (TIMER1_OVF_vect)
{
   // LED 0
   if (led0_dir == 0)            // Laufrichtung 
      led0_cnt += LED0_step;      // Dunkel -> Hell
   else
      led0_cnt -= LED0_step;      // Hell -> Dunkel
   if (led0_cnt <= LED0_min)      // Laufrichtung ändern
      led0_dir = 0;            // Dunkel -> Hell
   if (led0_cnt >= LED0_max)
      led0_dir = 1;            // Hell -> Dunkel
   // LED 1
   if (led1_dir == 0)
      led1_cnt += LED1_step;
   else
      led1_cnt -= LED1_step;
   if (led1_cnt <= LED1_min)
      led1_dir = 0;
   if (led1_cnt >= LED1_max)
      led1_dir = 1;
   // LED 2
   if (led2_dir == 0)
      led2_cnt += LED2_step;
   else
      led2_cnt -= LED2_step;
   if (led2_cnt <= LED2_min)
      led2_dir = 0;
   if (led2_cnt >= LED2_max)
      led2_dir = 1;
}
// Main
int main()
{
   LED0_DDR |= (1 << LED0_BIT);
   LED0_PORT &= ~(1 << LED0_BIT);   // aus
   
   LED1_DDR |= (1 << LED1_BIT);
   LED1_PORT &= ~(1 << LED1_BIT);   // aus
   
   LED2_DDR |= (1 << LED2_BIT);
   LED2_PORT &= ~(1 << LED2_BIT);   // aus
   
   // PWD Timer
   TCNT0 = timermin;
   TIMSK0 |= (1 << TOIE0);   // Überlauf IRQ
   TCCR0B |=  (1 << CS00);   // keine Prescaler
   
   // Timer für hell dunkel
   TIMSK1 |= (1 << TOIE0);   // Überlauf IRQ
   TCCR1B |=  (1 << CS00);   // keine Prescaler
   sei();      // IRQs ein
   
   while (1) ;   // NOP endlos
   
   return 0;   // niemals
}