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

-
For better understanding of PWM module it would be best to start with the example provided in Examples folder of our mikroBasic PRO for AVR compiler.
When you select a MCU, mikroBasic PRO for AVR automaticaly loads the correct PWM-16bit library, which can be verified by looking at the Library Manager.
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
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 |
sub procedure PWM16bit_Init(dim wave_mode as byte, dim prescaler as byte, dim inverted as byte, dim duty as word, dim timer as byte) |
---|---|
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, _TIMER1) |
PWM16bit_Change_Duty
Prototype |
sub procedure PWM16bit_Change_Duty(dim duty as word, dim channel as byte) |
||||||||||||||||||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
Returns |
Nothing. |
||||||||||||||||||||||||||||
Description |
Changes 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_Change_Duty( 300, _TIMER1_CH_A ) |
PWM16bit_Start
Prototype |
sub procedure PWM16bit_Start(dim timer as 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 |
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 |
sub procedure PWM16_Stop(dim timer as 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 |
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.
program PWM_Test dim current_duty as byte current_duty1 as byte 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 = 127 ' initial value for current_duty current_duty1 = 127 ' initial value for current_duty DDB1_bit = 1 ' Set PORTB pin 1 as output pin for the PWM (according to datasheet) DDB2_bit = 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 ' Endless loop if (PINC.B0 <> 0) then ' Detect if PORTC pin 0 is pressed Delay_ms(40) ' Small delay to avoid deboucing effect Inc(current_duty) ' Increment duty ratio PWM_Set_Duty(current_duty) ' Set incremented duty end if if (PINC.B1 <> 0) then ' Detect if PORTC pin 1 is pressed Delay_ms(40) ' Small delay to avoid deboucing effect Dec(current_duty) ' Decrement duty ratio PWM_Set_Duty(current_duty) ' Set decremented duty ratio end if if (PINC.B2 <> 0) then ' Detect if PORTC pin 2 is pressed Delay_ms(40) ' Small delay to avoid deboucing effect Inc(current_duty1) ' Increment duty ratio PWM1_Set_Duty(current_duty1) ' Set incremented duty end if if (PINC.B3 <> 0) then ' Detect if PORTC pin 3 is pressed Delay_ms(40) ' Small delay to avoid deboucing effect Dec(current_duty1) ' Decrement duty ratio PWM1_Set_Duty(current_duty1) ' Set decremented duty ratio end if wend end.
HW Connection
PWM demonstration
What do you think about this topic ? Send us feedback!