PWM Library

The CCP module is available with a number of PIC32 MCUs. mikroPascal 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

function PWM_Init(freq_hz : dword; enable_channel_x, timer_prescale, use_timer_x : word) : word;

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 :
var pwm_period1 : word;
...
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

function PWM_Init_Advanced(freq_hz, Fpb_kHz : dword; enable_channel_x, timer_prescale, use_timer_x : word) : word;

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
var pwm_period1 : word;
...
pwm_period1 := PWM_Init_Advanced(5000, 50000, 1, 0, 2);
Notes

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

PWM_Set_Duty

Prototype

procedure PWM_Set_Duty(duty, channel : word);

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%:
var pwm_period1 : word;
...
PWM_Set_Duty(pwm_period1 div 2, 1);
Notes

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

PWM_Start

Prototype

procedure PWM_Start(enable_channel_x : byte);

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

procedure PWM_Stop(disable_channel_x : byte);

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
program Pwm_Demo;
var current_duty, old_duty, current_duty1, old_duty1 : word;
    pwm_period1, pwm_period2 : word;

procedure InitMain();
begin
  CHECON := 0x32;
  AD1PCFG := 0xFFFF;                          // configure 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
end;

begin
  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 (TRUE) do                                // endless loop
    begin
      if RB0_bit = 1 then                        // button on RB0 pressed
        begin
          Delay_ms(1);
          current_duty := current_duty + 5;      // increment current_duty
          if (current_duty > pwm_period1) then   // 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
        end;

      if RB1_bit = 1 then                        // button on RB1 pressed
        begin
          Delay_ms(1);
          current_duty := current_duty - 5;      // decrement current_duty
          if (current_duty > pwm_period1) then   // 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
        end;

      if RB2_bit = 1 then                        // button on RB2 pressed
        begin
          Delay_ms(1);
          current_duty1 := current_duty1 + 5;    // increment current_duty1
          if (current_duty1 > pwm_period2) then  // 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
        end;

      if RB3_bit = 1 then                        // button on RB3 pressed
        begin
          Delay_ms(1);
          current_duty1 := current_duty1 - 5;    // decrement current_duty
          if (current_duty1 > pwm_period2) then  // 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);
        end;

      Delay_ms(2);                               // slow down change pace a little
    end;
end.

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