Guides‎ > ‎

PWM using C18

posted Jan 15, 2011, 7:08 PM by Danny Ng   [ updated Feb 8, 2011, 6:43 PM ]
The gadget spec URL could not be found

The use of pulse width modulation (PWM) is common for the use of controlling power to a particular electrical device. Motor speed control, LED contrast control, power supplies are some of the example usage of PWM. 18 series PIC always come with a CCP module which is capable of generating PWM. The picture below shows an example of using the capture/compare/pwm (CCP) module to control the LED brightness. PWM duty cycle is set accordingly using the value obtain from the potential meter through the ADC with 5v being the brightness and 0v dimmest for the LED.

The test circuit below is constructed to test the PWM module of PIC18f2455. LED of the 2x16 LCD is controlled by a NPN transistor BC547. PWM output is feed through CCP1 for the brightness control. The example below uses the code from ADC and LCD guides.

The first requirement is to set the output port for the CCP1 pin. Setting the tris register to 0 for the bit put the port to output mode.
   TRISCbits.TRISC2 = 0;
Next step would be to set the CCP module to function as a PWM. Timer 2 is tied to the PWM function for the generation of CCP. PR2 is used to determine the Period of the PWM pulse. CCPR1L and bit 4 and 5 of CCP1CON control the duty cycle of the generated PWM. The equation for couting of PWM and duty cycle is given as

PWM Period = [(PR2) + 1] • 4 • TOSC • (TMR2 Prescale Value)

PWM Duty Cycle = (CCPRXL:CCPXCON<5:4>) • TOSC • (TMR2 Prescale Value)

For the example we set the module configuration as below.

T2CON = 0x04;
PR2 = 0xFF;
CCP1CON = 0x3F;
CCPR1L = 0x00;
With this we can obtain a pwm period and maximum duty cycle of 
PWM Period = (255 + 1) * 4 * (1 / (8 * (10^6))) = 0.000128
Max PWM Duty Cycle period = (1024 * (1/(8*10^6))) =0.000128
allowing us to use full 10 bit to control the duty cycle of the PWM. The 10 bit adc value is set in to the corresponding bit for the control of the PWM. Below is the code for the update of pwm duty cycle. Fill attached contain the project for the example.

    ADCValue = ReadADC();
    CCP1CONbits.DC1B0 = ADCValue;
    CCP1CONbits.DC1B1 = ADCValue >> 1;
    CCPR1L = ADCValue >> 2;

Danny Ng,
Jan 15, 2011, 8:52 PM