PWM generation using timers in Embedded C - Time & Space Complexity
When generating PWM signals with a software loop, it's important to understand how the code execution time changes as period or duty cycle values change.
We want to know how the program's running time grows when controlling PWM with a software loop.
Analyze the time complexity of the following code snippet.
// Simple software PWM generation
void generate_pwm(int duty_cycle, int period) {
for (int i = 0; i < period; i++) {
if (i < duty_cycle) {
set_pin_high();
} else {
set_pin_low();
}
delay_one_unit();
}
}
This code creates a PWM signal by turning a pin on or off for each unit of the period based on the duty cycle.
Identify the loops, recursion, array traversals that repeat.
- Primary operation: The for-loop that runs once for each unit of the PWM period.
- How many times: It runs exactly
periodtimes, controlling the signal timing.
As the period increases, the loop runs more times, so the total work grows directly with the period size.
| Input Size (period) | Approx. Operations (loop iterations) |
|---|---|
| 10 | 10 |
| 100 | 100 |
| 1000 | 1000 |
Pattern observation: The execution time grows in a straight line with the period size.
Time Complexity: O(period)
This means the time to generate the PWM signal grows directly with the length of the period.
[X] Wrong: "The time to generate PWM depends on the duty cycle only."
[OK] Correct: The loop runs for the entire period, not just the duty cycle, so the period size controls the total time.
Understanding how timing loops affect execution time helps you explain embedded system behavior clearly and confidently.
"What if we replaced the for-loop with an interrupt-driven timer callback? How would the time complexity change?"
Practice
Solution
Step 1: Understand the acronym PWM
PWM is a common term in embedded systems related to signal control.Step 2: Match PWM with its full form
PWM stands for Pulse Width Modulation, which controls signal timing using timers.Final Answer:
Pulse Width Modulation -> Option AQuick Check:
PWM = Pulse Width Modulation [OK]
- Confusing PWM with power management terms
- Thinking PWM is a mode for writing data
- Mixing PWM with watchdog timer functions
Solution
Step 1: Identify standard embedded C HAL function
HAL libraries use the prefix HAL_TIM_PWM_Start for starting PWM timers.Step 2: Check syntax correctness
HAL_TIM_PWM_Start(&htim); uses correct syntax with a timer handle pointer, matching HAL style.Final Answer:
HAL_TIM_PWM_Start(&htim); -> Option BQuick Check:
HAL_TIM_PWM_Start(&htim) is correct syntax [OK]
- Using incorrect function names without HAL prefix
- Missing the timer handle argument
- Using lowercase or camelCase incorrectly
uint32_t period = 1000; uint32_t pulse = 250; // Timer configured with period and pulse // PWM output uses pulse width = pulse
Solution
Step 1: Understand duty cycle formula
Duty cycle = (pulse / period) * 100%Step 2: Calculate duty cycle with given values
Duty cycle = (250 / 1000) * 100% = 25%Final Answer:
25% -> Option DQuick Check:
Duty cycle = 25% [OK]
- Confusing pulse with period
- Calculating 1000/250 instead of 250/1000
- Forgetting to multiply by 100 for percentage
TIM_HandleTypeDef htim; htim.Init.Period = 1000; htim.Init.Pulse = 500; HAL_TIM_PWM_Start(&htim);
Solution
Step 1: Check PWM initialization sequence
Before starting PWM, the channel must be configured with pulse value using HAL_TIM_PWM_ConfigChannel.Step 2: Identify missing configuration call
The code sets pulse in Init (which is incorrect) and skips HAL_TIM_PWM_ConfigChannel call.Final Answer:
Missing call to HAL_TIM_PWM_ConfigChannel before starting PWM -> Option AQuick Check:
ConfigChannel call needed before HAL_TIM_PWM_Start [OK]
- Setting pulse in Init structure instead of channel config
- Starting PWM without configuring channel
- Assuming timer handle must be pointer variable
Solution
Step 1: Calculate timer frequency after prescaler
Timer clock = 72 MHz / (71 + 1) = 1 MHz (1 microsecond per tick)Step 2: Calculate period for 1 kHz PWM frequency
Period = (Timer frequency / PWM frequency) - 1 = (1,000,000 / 1,000) - 1 = 999Step 3: Calculate pulse for 60% duty cycle
Pulse = Period * 0.6 = 999 * 0.6 = 599.4 ≈ 600Final Answer:
Period = 999, Pulse = 600 -> Option CQuick Check:
Period 999 and pulse 600 give 60% duty cycle at 1 kHz [OK]
- Not adding 1 to prescaler or period calculations
- Using full clock without prescaler division
- Rounding pulse incorrectly
Ready to prove it?
Pass the test and this pattern moves unknown
