The Pulse Width Modulation (PWM) module generates a square wave that has a constant period but varying duty cycle (compare time as shown here). The general form of this signal can be seen below:
The PWM is controlled by an internal timer and a Compare register is used to test the timer value and set the duty cycle or high time of the signal when a match occurs.
PWM signals are frequently used in motor control to control the speed and direction of DC, servo, and stepper motors. The purpose of this resource is not to teach PWM theory but to explain the usage of PWM module in MPLAB® Xpress IDE.
Locating the PWM Module
The PWM module is located under Device Resources in the MPLAB Code Configurator (MCC) in the MPLAB Xpress IDE.
One thing to keep in mind when using the PWM module is the necessity to always combine it with Timer2/4/6. Timers are a necessary part of the signal generation to keep the period and compare values consistent.
Once the PWMx is chosen, the following window should open:
Basic Module Functionality
Enable PWM
Checking this box states to the program that the PWM module will begin as part of the original initialization within your code, as opposed to manually calling it to begin in the user-written software section. Unchecking this box may be useful for power saving reasons at the microcontroller start-up.
Duty Cycle
This box is one way to automatically set what the original duty cycle percentage will be when the PWM module first initializes. For example, a 50% duty cycle means that the compare value will be half of the period. If Vcc was equal to 5 V, then the observed voltage would be 2.5 V. The actual period and compare time values will be determined by the Timer2/4/6 module and system clock.
Pulse Width Modulation Duty Cycle (PWMDC) Value
The PWMDC value is useful to know when writing the software to accompany your initial settings of MCC. This number corresponds to the duty cycle % number.
PWM Polarity
This value sets the active polarity or the value corresponding to ON, of the PWM signal. Active_hi means that at 100% duty cycle, the digital value will be one for 100% of the period. Active_lo means that at 100% duty cycle, the digital value will be zero for 100% of the period.
PWM Period
The finalized period time length based upon the chosen clock settings in the System module and Timer2/4/6.
PWM Frequency
This frequency is derived based upon the system clock frequency. See the datasheet for more information.
PWM Resolution
This number gives the number of different duty cycle values that a particular signal can use. For example, a 10-bit signal can have 1024 different duty cycle values which would correspond to 1024 different pulse lengths.
Configuring the Pins in MCC
There is usually only one pin that is necessary to set when using the PWM module. This is the output pin which will be used to send the signal out of the microcontroller to another peripheral, such as a motor.
The port options can be seen below:
In this example, pin RA4 was used to output the signal to an oscilloscope for testing.
Using Basic Software Functionality in Main.c File
Besides the initialize function, which only needs to be called if the Enable PWM is not initially checked, there is only one other custom function generated by the MCC.
Software Function | What It Does |
---|---|
void PWM6_LoadDutyValue(uint16_t dutyValue); | This function is looking for one of the numbers referenced in the section above labeled PWMDC Value. You will also notice that the range of numbers in the PWMDC Value correlates to the PWM Resolution. For example, at 1% duty cycle, basically, always OFF, the value will be around zero. At 100%, the PWMDC Value will correspond to the final bit resolution, say 1023 for 10-bit. This function is extremely useful when sending servo values where specific pulses relate to specific positions of the servo. |
Example Code
void main(void) { //no PWM6_Initialize() called because Enable PWM was checked SYSTEM_Initialize(); while (1) { //will load a 1% duty cycle value for the corresponding clock settings PWM6_LoadDutyValue(9); } }