How to Control PWM Duty Cycle in Embedded C Easily
To control the PWM duty cycle in
embedded C, you adjust the value of the timer's compare register that sets the ON time of the PWM signal within its period. Changing this compare value changes the duty cycle, which controls how long the signal stays HIGH in each cycle.Syntax
In embedded C, controlling PWM duty cycle usually involves setting a timer's compare register value. The general syntax looks like this:
TIMER_COMPARE_REGISTER = duty_value;— sets the ON time of PWM.duty_valueranges from 0 (0% duty cycle) to the timer's max count (100% duty cycle).- The timer and PWM must be configured before setting this value.
c
TIMER_COMPARE_REGISTER = duty_value; // Set PWM duty cycleExample
This example shows how to set up a PWM signal on a microcontroller timer and change its duty cycle in embedded C. It assumes a 16-bit timer with a max count of 1000 for simplicity.
c
#include <stdint.h> #include <stdio.h> // Simulated hardware registers volatile uint16_t TIMER_PERIOD = 1000; // PWM period volatile uint16_t TIMER_COMPARE_REGISTER = 0; // PWM duty cycle control // Function to set PWM duty cycle (0 to 1000) void set_pwm_duty_cycle(uint16_t duty) { if (duty > TIMER_PERIOD) { duty = TIMER_PERIOD; // Limit duty cycle to max period } TIMER_COMPARE_REGISTER = duty; } int main() { // Initialize PWM with 0% duty cycle set_pwm_duty_cycle(0); printf("Initial duty cycle: %u/1000\n", TIMER_COMPARE_REGISTER); // Change duty cycle to 25% set_pwm_duty_cycle(250); printf("Duty cycle set to 25%%: %u/1000\n", TIMER_COMPARE_REGISTER); // Change duty cycle to 75% set_pwm_duty_cycle(750); printf("Duty cycle set to 75%%: %u/1000\n", TIMER_COMPARE_REGISTER); // Change duty cycle to 100% set_pwm_duty_cycle(1000); printf("Duty cycle set to 100%%: %u/1000\n", TIMER_COMPARE_REGISTER); return 0; }
Output
Initial duty cycle: 0/1000
Duty cycle set to 25%: 250/1000
Duty cycle set to 75%: 750/1000
Duty cycle set to 100%: 1000/1000
Common Pitfalls
Common mistakes when controlling PWM duty cycle include:
- Setting the duty cycle value beyond the timer's maximum count, causing unexpected behavior.
- Not configuring the timer and PWM mode properly before changing the duty cycle.
- Forgetting to update the compare register atomically if interrupts are involved, which can cause glitches.
- Using integer division incorrectly when calculating duty cycle percentages.
c
#include <stdint.h> // Wrong: duty cycle exceeds period void wrong_set_pwm(uint16_t duty) { // No check for max period TIMER_COMPARE_REGISTER = duty; // Can cause overflow or invalid PWM } // Correct: limit duty cycle to max period void correct_set_pwm(uint16_t duty) { if (duty > TIMER_PERIOD) { duty = TIMER_PERIOD; } TIMER_COMPARE_REGISTER = duty; }
Quick Reference
Remember these tips when controlling PWM duty cycle in embedded C:
- Duty cycle value must be between 0 and timer period.
- Update the timer compare register to change duty cycle.
- Configure timer and PWM mode before setting duty cycle.
- Use integer math carefully to avoid rounding errors.
Key Takeaways
Control PWM duty cycle by setting the timer's compare register value within its period range.
Always ensure the duty cycle value does not exceed the timer's maximum count to avoid errors.
Configure the timer and PWM mode properly before changing the duty cycle.
Use integer math carefully to calculate duty cycle percentages accurately.
Update the compare register atomically if interrupts or concurrency are involved.