PWM 16 bit Library

CMO module is available with a number of AVR MCUs. mikroC 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

void PWM16bit_Init(unsigned short wave_mode, unsigned short prescaler, unsigned short inverted, unsigned short duty, unsigned int timer);

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, 1);

PWM16bit_Set_Duty

Prototype

void PWM16bit_Set_Duty(unsigned duty, unsigned short channel);

Returns

Nothing.

Description

Sets 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_Set_Duty(300, _TIMER1_CH_A );

PWM16bit_Enable

Prototype

void PWM16bit_Enable(unsigned short inverted, unsigned short channel);

Returns

Nothing.

Description

Enables PWM module on desired timer/channel.

Parameters :

  • inverted: PWM mode. Values :
    Value Description
    _PWM16_INVERTED PWM inverted mode
    _PWM16_NON_INVERTED PWM non-inverted mode

  • channel: set desired channel. Valid values :
    Value Description
    _PWM16_TIMER1_CH_A Timer1, Channel A
    _PWM16_TIMER2_CH_A Timer2, Channel B
    _PWM16_TIMER1_CH_B Timer1, Channel A
    _PWM16_TIMER2_CH_B Timer2, Channel B
Requires

PWM module must to be initialised (PWM16bit_Init) before using this routine.

Example
PWM16bit_Enable(_PWM16_NON_INVERTED, _PWM16_TIMER1_CH_A );

PWM16bit_Disable

Prototype

void PWM16bit_Disable(unsigned short channel);

Returns

Nothing.

Description

Disables PWM module on desired timer/channel.

Parameters :

  • channel: set desired channel. Valid values :
    Value Description
    _PWM16_TIMER1_CH_A Timer1, Channel A
    _PWM16_TIMER2_CH_A Timer2, Channel B
    _PWM16_TIMER1_CH_B Timer1, Channel A
    _PWM16_TIMER2_CH_B Timer2, Channel B
Requires

PWM module must to be initialised (PWM16bit_Init) before using this routine.

Example
PWM16bit_Disable(_PWM16_TIMER1_CH_A );

PWM16bit_Set_Output

Prototype

void PWM16bit_Set_Output(unsigned short timer, chOutputSelectA, chOutputSelectB);

Returns

Nothing.

Description

This routine sets PWM module output on desired timer/channel.

Parameters :

  • timer: set desired timer. Valid values :
    Value Description
    _PWM16_TIMER1 Timer1
    _PWM16_TIMER2 Timer2

  • chOutputSelectA: TOCCn output for channel A. Valid values :
    Value Description
    _PWM16_CH_A_OUT_TOCC1 Sets TOCC1 output for channel A
    _PWM16_CH_A_OUT_TOCC3 Sets TOCC3 output for channel A
    _PWM16_CH_A_OUT_TOCC5 Sets TOCC5 output for channel A
    _PWM16_CH_A_OUT_TOCC7 Sets TOCC7 output for channel A
    _PWM16_CH_A_OUT_NONE Channel A will have no output.

  • chOutputSelectB: TOCCn output for channel B. Valid values :
    Value Description
    _PWM16_CH_B_OUT_TOCC0 Sets TOCC0 output for channel B
    _PWM16_CH_B_OUT_TOCC2 Sets TOCC2 output for channel B
    _PWM16_CH_B_OUT_TOCC4 Sets TOCC4 output for channel B
    _PWM16_CH_B_OUT_TOCC6 Sets TOCC6 output for channel B
    _PWM16_CH_B_OUT_NONE Channel B will have no output.
Requires

PWM module must to be initialised (PWM16bit_Init) before using this routine.

Example
PWM16bit_Set_Output(_PWM16_TIMER1, _PWM16_CH_A_OUT_TOCC1, _PWM16_CH_B_OUT_TOCC0);

PWM16bit_Start

Prototype

void PWM16bit_Start(unsigned int timer);

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

void PWM16_Stop(unsigned int timer);

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.B1 or PORTB.B2 ,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
char current_duty;
char current_duty1;

void main(){

  DDC0_bit = 0;                   // Set PORTC pin 0 as input
  DDC1_bit = 0;                   // Set PORTC pin 1 as input

  DDC2_bit = 0;                   // Set PORTC pin 2 as input
  DDC3_bit = 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);

  do {
    if (PINC.B0) {                             			// Detect if PORTC pin 0 is pressed
      Delay_ms(40);                             			// Small delay to avoid deboucing effect
      current_duty++;                           			// Increment duty ratio
      PWM16bit_Change_Duty(current_duty, _TIMER1_CH_A);       		// Set incremented duty
    }
    else
      if (PINC.B1) {                            			// Detect if PORTC pin 1 is pressed
        Delay_ms(40);                           			// Small delay to avoid deboucing effect
        current_duty--;                         			// Decrement duty ratio
        PWM16bit_Change_Duty(current_duty, _TIMER1_CH_A);     		// Set decremented duty ratio
      }
      else
        if (PINC.B2) {                          			// Detect if PORTC pin 2 is pressed
          Delay_ms(40);                         			// Small delay to avoid deboucing effect
          current_duty1++;                      			// Increment duty ratio
          PWM16bit_Change_Duty(current_duty1, _TIMER1_CH_B);  		// Set incremented duty
        }
        else
          if (PINC.B3) {                        			// Detect if PORTC pin 3 is pressed
            Delay_ms(40);                       			// Small delay to avoid deboucing effect
            current_duty1--;                    			// Decrement duty ratio
            PWM16bit_Change_Duty(current_duty1, _TIMER1_CH_B);		// Set decremented duty ratio
          }

  } while(1);                       // Endless loop
     
  }

HW Connection

PWM demonstration

PWM demonstration

Copyright (c) 2002-2017 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