Not strictly true Dwayne.

I shall play Devils Advocate... as I seem to have a habit of doing here...

A 4MHz PIC can easily handle the dimming of half a Dozen LED's, maybe more... a 20MHz PIC, pro rata can do a couple of Dozen independantly.

How?

It's all down to your eye's perception... your eye probably cannot distinguish anything over 25Hz and it blurrs into a constant. Providing you can scan your LED's at least at that rate, your eye will have the 'perception' of dimming.

There is a problem with LED's though... 80% lit might as well be 100% lit, because there's not much differentiating the two as far as your eyesight is concenerned. The biggest visible changes occur between zero and about 65%. The eye sees little change between 65% and 100% as the program demonstrates...
Code:
    '
    '   Define LED Ports
    '   ----------------
    LEDA var PortB.0
    LEDB var PortB.1
    LEDC var PortB.2
    '
    '   Define Software Variables
    '   -------------------------
    StatusA var Byte
    DirectionA var Bit
    StatusB var Byte
    DirectionB var Bit
    StatusC var Byte
    DirectionC var Bit
    CounterA var Byte
    '
    '   Initialise PIC
    '   --------------
    TRISB=%00000000
    '
    '   Start Program
    '   -------------
    StatusA=66
    DirectionA=1
    StatusB=66
    DirectionB=0
    StatusC=0
    DirectionC=0
    '
    '   LED Ramp-Up/Ramp-Down Loop
    '   --------------------------
Loop:
    Gosub DimLEDS
    If DirectionA=0 then
        StatusA=StatusA+1
        If StatusA=100 then DirectionA=1
        else
        StatusA=StatusA-1
        If StatusA=0 then DirectionA=0
        endif
    If DirectionB=0 then
        StatusB=StatusB+1
        If StatusB=100 then DirectionB=1
        else
        StatusB=StatusB-1
        If StatusB=0 then DirectionB=0
        endif
    If DirectionC=0 then
        StatusC=StatusC+1
        If StatusC=100 then DirectionC=1
        else
        StatusC=StatusC-1
        If StatusC=0 then DirectionC=0
        endif
    Goto Loop

    '
    '   Subroutine Displays LEDS as % of Brightness
    '   -------------------------------------------
DimLEDS:
    For CounterA=0 to 100
        If StatusA>0 then 
            High LEDA
            If CounterA=>StatusA then
                Low LEDA
                endif
            endif
        If StatusB>0 then 
            High LEDB
            If CounterA=>StatusB then
                Low LEDB
                endif
            endif
        If StatusC>0 then 
            High LEDC
            If CounterA=>StatusC then
                Low LEDC
                endif
            endif
        PauseUS 20
        Next CounterA
    Return

    End
Here the Hub of the program is the above subroutine DimLEDs. This subroutine takes 2mS to execute once (100 times 20uS). This 2mS period is our PWM period. The 2mS time period is subdivided into 100 slots of 20uS each. This determines the ON time of the LED's. The amount of 20uS slots (from zero to 100) that an LED is lit is dependant on the LED's StatusX variable. This variable when zero represents 0% PWM, and when the variable is 100 represents 100% PWM with all the steps intermediate. So when StatusC=50 for example, this means that LEDC will be on for fifty out of the one hundred 20uS slots, namely 50% of the 2mS time period or 1mS (calculating 50*20uS=1mS).

As you can see, this crude subroutine accounts for one period cycle of 2mS. Call this routine repeatedly (as we do in this example), and we have a vague 500Hz refresh rate (excluding any external calculation time - reality is a lot slower as I've not taken the program execution time into effect - but you'll see what I'm driving at without clouding the main issue). The secret is in keeping the external time outside the subroutine to a minimum as prolonged delays there can easily cause unacceptible flicker.

How do you think those cheapo Christmas lights get the dimming effect? They sure don't use microcontrollers with 3 or 4 hardware PWM channels.

If you build the circuit and run this code, you will get three LED's all sequencing up and down (equivallent of 120 degrees out of phase with each other) - and very smoothly too... and with this method you can control a lot more than three LED's at a time... just don't try to do anything too time-consuming outside that subroutine though!

Going back to Srigopal's requirement of 20%, 30% and 80%, you could execute it as...

Code:
SrigopalsLoop:
    StatusA=20	' 20%
    StatusB=30	' 30%
    StatusC=80	' 80%
    Gosub DimLEDS
    goto SrigopalsLoop
If you play with this then you will then discover that to your eye does not distingush brightness linearly. The program will faithfully ramp up and down those LED's from zero to 100% and back down again... but that's not how your eye sees it. But as they say... that's another story...

Melanie