PWM 16 bit Library

CMO module is available with a number of AVR MCUs. mikroPascal PRO for AVR provides library which simplifies using PWM HW Module.

  Important :

Library Routines

Predefined constants used in PWM-16bit library

The following variables are used in PWM-16bit library functions: Description :
_PWM16_PHASE_CORRECT_MODE_8BIT Selects Phase Correct, 8-bit mode.
_PWM16_PHASE_CORRECT_MODE_9BIT Selects Phase Correct, 9-bit mode.
_PWM16_PHASE_CORRECT_MODE_10BIT Selects Phase Correct, 10-bit mode.
_PWM16_FAST_MODE_8BIT Selects Fast, 8-bit mode.
_PWM16_FAST_MODE_9BIT Selects Fast, 9-bit mode.
_PWM16_FAST_MODE_10BIT Selects Fast, 10-bit mode.
_PWM16_PRESCALER_16bit_1 Sets prescaler value to 1 (No prescaling).
_PWM16_PRESCALER_16bit_8 Sets prescaler value to 8.
_PWM16_PRESCALER_16bit_64 Sets prescaler value to 64.
_PWM16_PRESCALER_16bit_256 Sets prescaler value to 256.
_PWM16_PRESCALER_16bit_1024 Sets prescaler value to 1024.
_PWM16_INVERTED Selects the inverted PWM-16bit mode.
_PWM16__NON_INVERTED Selects the normal (non inverted) PWM-16bit mode.
_TIMER1 Selects the Timer/Counter1 (used with PWM16bit_Start and PWM16bit_Stop.
_TIMER3 Selects the Timer/Counter3 (used with PWM16bit_Start and PWM16bit_Stop.
_TIMER1_CH_A Selects the channel A on Timer/Counter1 (used with PWM16bit_Change_Duty).
_TIMER1_CH_B Selects the channel B on Timer/Counter1 (used with PWM16bit_Change_Duty).
_TIMER1_CH_C Selects the channel C on Timer/Counter1 (used with PWM16bit_Change_Duty).
_TIMER3_CH_A Selects the channel A on Timer/Counter3 (used with PWM16bit_Change_Duty).
_TIMER3_CH_B Selects the channel B on Timer/Counter3 (used with PWM16bit_Change_Duty).
_TIMER3_CH_C Selects the channel C on Timer/Counter3 (used with PWM16bit_Change_Duty).

  Note :

PWM16bit_Init

Prototype

procedure PWM16bit_Init(wave_mode : byte; prescaler : byte; inverted : byte; duty : word; timer : byte);

Returns

Nothing.

Description

Initializes the PWM module. Parameter wave_mode is a desired PWM-16bit mode.
There are several modes included :

  • PWM, Phase Correct, 8-bit
  • PWM, Phase Correct, 9-bit
  • PWM, Phase Correct, 10-bit
  • Fast PWM, 8-bit
  • Fast PWM, 9-bit
  • Fast PWM, 10-bit

Parameter prescaler chooses prescale value N = 1,8,64,256 or 1024 (some modules support 32 and 128, but for this you will need to check the datasheet for the desired MCU). Paremeter inverted is for choosing between inverted and non inverted PWM signal. Parameter duty sets duty ratio from 0 to TOP value (this value varies on the PWM wave mode selected). PWM signal graphs and formulas are shown below.

PWM-16bit Graphs01


The N variable represents the prescaler factor (1, 8, 64, 256, or 1024).

PWM-16bit Graphs02

The N variable represents the prescaler factor (1, 8, 64, 256, or 1024).

PWM16bit_Init must be called before using other functions from PWM Library.

Requires

You need a CMO on the given MCU (that supports PWM-16bit).

Before calling this routine you must set the output pin for the PWM (according to the datasheet):
DDB1_bit = 1; // set PORTB pin 1 as output for the PWM-16bit

This code example is for ATmega168, for different MCU please consult datasheet for the correct pinout of the PWM module or modules.

Example

Initialize PWM-16bit module:

PWM16bit_Init(_PWM16_PHASE_CORRECT_MODE_8BIT, _PWM16_PRESCALER_16bit_8, _PWM16_NON_INVERTED, 255, _TIMER1);

PWM16bit_Change_Duty

Prototype

procedure PWM16bit_Change_Duty(duty : word; channel : byte);

Returns

Nothing.

Description

Changes PWM duty ratio. Parameter duty takes values shown on the table below. Where 0 is 0%, and TOP value is 100% duty ratio. Other specific values for duty ratio can be calculated as (Percent*TOP)/100.

Timer/Counter Mode of Operation : TOP : Update of OCRnX at : TOVn Flag Set on :
PWM, Phase Correct, 8 bit 0x00FF TOP BOTTOM
PWM, Phase Correct, 9 bit 0x01FF TOP BOTTOM
PWM, Phase Correct, 10 bit 0x03FF TOP BOTTOM
Fast PWM, 8 bit 0x00FF TOP TOP
Fast PWM, 9 bit 0x01FF TOP TOP
Fast PWM, 10 bit 0x03FF TOP TOP
Requires

PWM module must to be initialised (PWM16bit_Init) before using PWM_Set_Duty function.

Example

Example lets set duty ratio to :

PWM16bit_Change_Duty(300, _TIMER1_CH_A );

PWM16bit_Start

Prototype

procedure PWM16bit_Start(timer : byte);

Returns

Nothing.

Description

Starts PWM-16bit module with alredy preset values (wave mode, prescaler, inverted and duty) given in the PWM16bit_Init.

Requires

MCU must have CMO module to use this library. PWM16bit_Init must be called before
using this routine, otherwise it will have no effect as the PWM module is not initialised.

Example
PWM16bit_Start(_TIMER1 );		// Starts the PWM-16bit module on Timer/Counter1	

or

PWM16bit_Start(_TIMER3 );		// Starts the PWM-16bit module on Timer/Counter3	

PWM16bit_Stop

Prototype

procedure PWM16_Stop(timer : byte);

Returns

Nothing.

Description

Stops the PWM-16bit module, connected to Timer/Counter set in this stop function.

Requires

MCU must have CMO module to use this library. Like in PWM16bit_Start before, PWM16bit_Init must be called before
using this routine , otherwise it will have no effect as the PWM module is not running.

Example
PWM16bit_Stop(_TIMER1 );		// Stops the PWM-16bit module on Timer/Counter1	

or

PWM16bit_Stop(_TIMER3 );		// Stops the PWM-16bit module on Timer/Counter3	

Library Example

The example changes PWM duty ratio continually by pressing buttons on PORTC (0-3). If LED is connected to PORTB.1 or PORTB.2 ,you can observe the gradual change of emitted light. This example is written for ATmega168. This AVR MCU has only Timer/Counter1 split over two channels A and B. In this example we are changing the duty ratio on both of these channels.

Copy Code To ClipboardCopy Code To Clipboard
program PWM16bit_Test;

var current_duty : byte;
    current_duty1 : byte;

begin
  DDRC.B0 := 0;                    // Set PORTC pin 0 as input
  DDRC.B1 := 0;                    // Set PORTC pin 1 as input

  DDRC.B2 := 0;                    // Set PORTC pin 2 as input
  DDRC.B3 := 0;                    // Set PORTC pin 3 as input

  current_duty := 255;             // initial value for current_duty
  current_duty1 := 255;            // initial value for current_duty

  DDRB.B1 := 1;                    // Set PORTB pin 1 as output pin for the PWM (according to datasheet)
  DDRB.B2 := 1;                    // Set PORTB pin 2 as output pin for the PWM (according to datasheet)

  PWM16bit_Init(_PWM16_FAST_MODE_9BIT, _PWM16_PRESCALER_16bit_1, _PWM16_INVERTED, 255, 1);

  while TRUE do
    begin
    if (PINC.B0 <> 0) then    // Detect if PORTC pin 0 is pressed
        begin                                   
          Delay_ms(40);                             // Small delay to avoid deboucing effect
          Inc(current_duty);                        // Increment duty ratio
          PWM16bit_Set_Duty(current_duty);          // Set incremented duty
        end
      else
        if (PINC.B1 <> 0) then                   // Detect if PORTC pin 1 is pressed
          begin
            Delay_ms(40);                           // Small delay to avoid deboucing effect
            Dec(current_duty);                      // Decrement duty ratio
            PWM16bit_Set_Duty(current_duty);        // Set decremented duty ratio
          end
        else
          if (PINC.B2 <> 0) then                 // Detect if PORTC pin 2 is pressed
            begin
              Delay_ms(40);                         // Small delay to avoid deboucing effect
              Inc(current_duty1);                   // Increment duty ratio
              PWM16bit_Set_Duty(current_duty1);     // Set incremented duty
            end
          else
            if (PINC.B3 <> 0) then               // Detect if PORTC pin 3 is pressed
              begin
                Delay_ms(40);                       // Small delay to avoid deboucing effect
                Dec(current_duty1);                 // Decrement duty ratio
                PWM16bit_Set_Duty(current_duty1);   // Set decremented duty ratio
              end;

    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