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.

-
PWM library handles and initializes the PWM module on the given AVR MCU, but it is up to user to set the correct pins as PWM output, this topic will be covered later in this section.
Library Routines
- PWM16bit_Init
- PWM16bit_Set_Duty
- PWM16bit_Enable
- PWM16bit_Disable
- PWM16bit_Set_Output
- PWM16bit_Start
- PWM16bit_Stop
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). |

-
Not all of the MCUs have 16bit PWM, and not all of the MCUs have both Timer/Counter1 and Timer/Counter3. Sometimes, like its the case with ATmega168, MCU has only Timer/Counter1 and channels A and B. Therefore constants that have in their name
Timer3 or channel C are invalid (for ATmega168) and will not be visible from Code Assistant. It is highly advisable to use this feature, since it handles all the constants (available) and eliminates any chance of typing error.
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
Parameter
![]() The N variable represents the ![]() The N variable represents the 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
|
||||||||||||||||||||||||||||
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 :
|
||||||||||||||||
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 :
|
||||||||||
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 :
|
||||||||||||||||||||||||||||||
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 |
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 |
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.
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
What do you think about this topic ? Send us feedback!