PWM Library

The CCP module is available with a number of PIC32 MCUs. mikroC PRO for PIC32 provides a library which simplifies using of the PWM HW Module.

  Important : PWM module uses either Timer2 or Timer3 module.

Library Routines

PWM_Init

Prototype

unsigned int PWM_Init(unsigned long freq_hz, unsigned int enable_channel_x, unsigned int timer_prescale, unsigned int use_timer_x);

Description

Initializes the PWM module with duty ratio 0.

Parameters
  • freq_hz: PWM frequency in Hz (refer to device datasheet for correct values in respect with Fosc)
  • enable_channel_x: number of PWM channel to be initialized. Refer to MCU's datasheet for available PWM channels
  • timer_prescale: timer prescaler parameter. Valid values: 1, 8, 64, and 256
  • use_timer_x: timer to be used with the PWM module. Valid values: 2 (Timer2) and 3 (Timer3)
Returns
  • 0xFFFF - if timer settings are not valid
  • otherwise returns calculated timer period
Requires

MCU must have the HW PWM Module.

Example
// Initializes the PWM module at 5KHz, channel 1, no clock prescale, timer2 :
unsigned int pwm_period1;
...
pwm_period1 = PWM_Init(5000, 1, 0, 2);
Notes

Number of available PWM channels depends on MCU. Refer to MCU datasheet for details.

PWM_Init_Advanced

Prototype

unsigned int PWM_Init_Advanced(unsigned long freq_hz, unsigned long Fpb_kHz, unsigned int enable_channel_x, unsigned int timer_prescale, unsigned int use_timer_x);

Description

Initializes the PWM module with duty ratio 0.

Parameters
  • freq_hz: PWM frequency in Hz
  • Fpb_kHz: Peripheral Bus Clock frequency in kHz.
  • enable_channel_x: number of PWM channel to be initialized. Refer to MCU's datasheet for available PWM channels
  • timer_prescale: timer prescaler parameter. Valid values: 1, 8, 64, and 256
  • use_timer_x: timer to be used with the PWM module. Valid values: 2 (Timer2) and 3 (Timer3)
Returns
  • 0xFFFF - if timer settings are not valid
  • otherwise returns calculated timer period
Requires

MCU must have the HW PWM Module.

Example
// Initializes the PWM module at 5KHz, channel 1, no clock prescale, timer2 :
unsigned int pwm_period1;
...
pwm_period1 = PWM_Init(5000, 1, 0, 2);
Notes

Number of available PWM channels depends on MCU. Refer to MCU datasheet for details.

PWM_Set_Duty

Prototype

void PWM_Set_Duty(unsigned duty, unsigned channel);

Description

The function changes PWM duty ratio.

Parameters
  • duty: PWM duty ratio. Valid values: 0 to timer period returned by the PWM_Init function.
  • channel: number of PWM channel to change duty to.
Returns

Nothing.

Requires

MCU must have the HW PWM Module.

PWM channel must be properly initialized. See PWM_Init routine.

Example
// Set channel 1 duty ratio to 50%:
unsigned int pwm_period1;
...
PWM_Set_Duty(pwm_period1/2, 1);
Notes

Number of available PWM channels depends on MCU. Refer to MCU datasheet for details.

PWM_Start

Prototype

void PWM_Start(unsigned int enable_channel_x);

Description

Starts PWM at requested channel.

Parameters
  • enable_channel_x: number of PWM channel
Returns

Nothing.

Requires

MCU must have the HW PWM Module.

PWM channel must be properly configured. See the PWM_Init and PWM_Set_Duty routines.

Example
// start PWM at channel 1
PWM_Start(1);
Notes

Number of available PWM channels depends on MCU. Refer to MCU datasheet for details.

PWM_Stop

Prototype

void PWM_Stop(unsigned int disable_channel_x);

Description

Stops PWM at requested channel.

Parameters
  • disable_channel_x: number of PWM channel
Returns

Nothing.

Requires

MCU must have the HW PWM Module.

Example
// stop PWM at channel 1
PWM_Stop(1);
Notes

Number of available PWM channels depends on MCU. Refer to MCU datasheet for details.

Library Example

The example changes PWM duty ratio on channels 1 and 2 continuously. If LEDs are connected to channels 1 and 2, a gradual change of emitted light will be noticeable.

Copy Code To ClipboardCopy Code To Clipboard
unsigned int current_duty, old_duty, current_duty1, old_duty1;
unsigned int pwm_period1, pwm_period2;

void InitMain() {
  CHECON = 0x32;
  AD1PCFG = 0xFFFF;                          // Configure AN pins as digital I/O
  TRISB = 0xFFFF;                            // configure PORTB pins as input
  PORTD = 0;                                 // set PORTD to 0
  TRISD = 0;                                 // designate PORTD pins as output
}

void main() {
  InitMain();
  current_duty  = 100;                        // initial value for current_duty
  current_duty1 = 100;                        // initial value for current_duty1

  pwm_period1 = PWM_Init(5000 , 1, 1, 2);
  pwm_period2 = PWM_Init(10000, 2, 1, 3);

  PWM_Start(1);
  PWM_Start(2);

  PWM_Set_Duty(current_duty,  1);            // Set current duty for PWM1
  PWM_Set_Duty(current_duty1, 2);            // Set current duty for PWM2

  while (1) {                                // endless loop
    if (RB0_bit) {                           // button on RB0 pressed
      Delay_ms(1);
      current_duty = current_duty + 5;       // increment current_duty
      if (current_duty > pwm_period1) {      // if we increase current_duty greater then possible pwm_period1 value
        current_duty = 0;                    // reset current_duty value to zero
      }
      PWM_Set_Duty(current_duty,  1);        // set newly acquired duty ratio
     }

    if (RB1_bit) {                           // button on RB1 pressed
      Delay_ms(1);
      current_duty = current_duty - 5;       // decrement current_duty
      if (current_duty > pwm_period1) {      // if we decrease current_duty greater then possible pwm_period1 value (overflow)
        current_duty = pwm_period1;          // set current_duty to max possible value
      }
      PWM_Set_Duty(current_duty,  1);        // set newly acquired duty ratio
     }

    if (RB2_bit) {                           // button on RB2 pressed
      Delay_ms(1);
      current_duty1 = current_duty1 + 5;     // increment current_duty
      if (current_duty1 > pwm_period2) {     // if we increase current_duty1 greater then possible pwm_period2 value
        current_duty1 = 0;                   // reset current_duty1 value to zero
      }
      PWM_Set_Duty(current_duty1,  2);       // set newly acquired duty ratio
     }

    if (RB3_bit) {                           // button on RB3 pressed
      Delay_ms(1);
      current_duty1 = current_duty1 - 5;     // decrement current_duty
      if (current_duty1 > pwm_period2) {     // if we decrease current_duty1 greater then possible pwm_period1 value (overflow)
        current_duty1 = pwm_period2;         // set current_duty to max possible value
      }
      PWM_Set_Duty(current_duty1,  2);
     }

    Delay_ms(1);                             // slow down change pace a little
  }
}

HW Connection

PWM demonstration

PWM demonstration

Copyright (c) 2002-2012 mikroElektronika. All rights reserved.
What do you think about this topic ? Send us feedback!
Want more examples and libraries? 
Find them on LibStock - A place for the code