Bird
Raised Fist0
Embedded Cprogramming~10 mins

PWM generation using timers in Embedded C - Step-by-Step Execution

Choose your learning style10 modes available
Concept Flow - PWM generation using timers
Configure Timer Prescaler and Period
↓
Set Timer Mode to PWM
↓
Set PWM Duty Cycle
↓
Start Timer
↓
Timer Counts Up
↓
Compare Counter with Duty Cycle
↓
Counter < Duty
↓
Output HIGH
↓
Repeat Counting
↓
PWM Signal
The timer is set up with a prescaler and period, configured for PWM mode, then the duty cycle is set. The timer counts up, and the output pin is set HIGH or LOW depending on the counter compared to the duty cycle, creating a PWM signal.
Execution Sample
Embedded C
TIM_HandleTypeDef htim2;

void PWM_Init() {
  htim2.Init.Prescaler = 79;
  htim2.Init.Period = 999;
  HAL_TIM_PWM_Start(&htim2, TIM_CHANNEL_1);
}

void Set_Duty(uint16_t duty) {
  __HAL_TIM_SET_COMPARE(&htim2, TIM_CHANNEL_1, duty);
}
This code initializes a timer for PWM with a prescaler and period, starts PWM on channel 1, and sets the duty cycle by changing the compare value.
Execution Table
StepTimer Counter (CNT)Duty Cycle (CCR)Condition (CNT < CCR)Output PinAction
10500TrueHIGHTimer starts counting from 0, output HIGH
2100500TrueHIGHCounter less than duty, output stays HIGH
3499500TrueHIGHCounter still less than duty, output HIGH
4500500FalseLOWCounter equals duty, output switches LOW
5700500FalseLOWCounter greater than duty, output LOW
6999500FalseLOWCounter reaches period, output LOW
70500TrueHIGHCounter resets to 0, output HIGH again
ExitCounter resets after reaching PeriodPWM cycle repeats continuously
💡 Timer counter resets after reaching the period, PWM signal repeats
Variable Tracker
VariableStartAfter Step 1After Step 4After Step 7Final
CNT (Timer Counter)005000Repeats 0 to 999
CCR (Duty Cycle)500500500500Constant at 500
Output PinLOWHIGHLOWHIGHToggles based on CNT vs CCR
Key Moments - 3 Insights
Why does the output pin go LOW when the counter equals the duty cycle?
Because in the execution_table at step 4, when CNT equals CCR, the condition CNT < CCR becomes false, so the output switches from HIGH to LOW to create the PWM off time.
What happens when the timer counter reaches the period value?
At step 6 and 7 in the execution_table, the counter resets to 0 after reaching the period, restarting the PWM cycle and setting the output HIGH again.
Why is the duty cycle value constant during the PWM cycle?
The duty cycle (CCR) is set once before the timer starts and remains constant during counting, as shown in variable_tracker, controlling how long the output stays HIGH each cycle.
Visual Quiz - 3 Questions
Test your understanding
Look at the execution_table, what is the output pin state at step 3 when CNT is 499 and CCR is 500?
AHIGH
BLOW
CUndefined
DToggling
💡 Hint
Check the 'Output Pin' column at step 3 in the execution_table
At which step does the timer counter reset to 0?
AStep 4
BStep 7
CStep 6
DStep 5
💡 Hint
Look at the 'Timer Counter (CNT)' column and the 'Action' description in the execution_table
If the duty cycle (CCR) is increased to 800, how would the output pin behave between CNT 500 and 700?
AOutput switches LOW at CNT 800
BOutput switches LOW at CNT 500
COutput stays HIGH
DOutput stays LOW
💡 Hint
Refer to the condition CNT < CCR in the execution_table and how output depends on it
Concept Snapshot
PWM generation uses a timer counting from 0 to a set period.
Output pin is HIGH while counter < duty cycle (compare value).
When counter >= duty cycle, output goes LOW.
Timer resets at period, repeating PWM cycle.
Duty cycle controls pulse width (HIGH time).
Prescaler and period set PWM frequency.
Full Transcript
PWM generation using timers works by configuring a timer with a prescaler and period to set the PWM frequency. The timer counts up from zero to the period value repeatedly. A compare register holds the duty cycle value. While the timer counter is less than the duty cycle, the output pin is set HIGH, creating the ON part of the pulse. When the counter reaches or exceeds the duty cycle, the output pin goes LOW, creating the OFF part. This cycle repeats continuously, producing a PWM signal with a pulse width proportional to the duty cycle. The example code initializes the timer, starts PWM, and sets the duty cycle by updating the compare register. The execution table shows the timer counter increasing, output pin switching states based on the counter compared to the duty cycle, and the counter resetting after reaching the period. Key moments clarify why the output changes state and how the timer resets. The visual quiz tests understanding of output states and timer behavior. This method is common in embedded systems to control motors, LEDs, and other devices by varying power with PWM.

Practice

(1/5)
1. What does PWM stand for in embedded C programming when using timers?
easy
A. Pulse Width Modulation
B. Power Wave Management
C. Programmed Write Mode
D. Peripheral Watchdog Monitor

Solution

  1. Step 1: Understand the acronym PWM

    PWM is a common term in embedded systems related to signal control.
  2. Step 2: Match PWM with its full form

    PWM stands for Pulse Width Modulation, which controls signal timing using timers.
  3. Final Answer:

    Pulse Width Modulation -> Option A
  4. Quick Check:

    PWM = Pulse Width Modulation [OK]
Hint: Remember PWM controls signal timing by pulse width [OK]
Common Mistakes:
  • Confusing PWM with power management terms
  • Thinking PWM is a mode for writing data
  • Mixing PWM with watchdog timer functions
2. Which of the following is the correct way to start a timer for PWM in embedded C?
easy
A. TIM_StartPWM();
B. HAL_TIM_PWM_Start(&htim);
C. StartTimerPWM();
D. timer_pwm_start();

Solution

  1. Step 1: Identify standard embedded C HAL function

    HAL libraries use the prefix HAL_TIM_PWM_Start for starting PWM timers.
  2. Step 2: Check syntax correctness

    HAL_TIM_PWM_Start(&htim); uses correct syntax with a timer handle pointer, matching HAL style.
  3. Final Answer:

    HAL_TIM_PWM_Start(&htim); -> Option B
  4. Quick Check:

    HAL_TIM_PWM_Start(&htim) is correct syntax [OK]
Hint: HAL functions start with HAL_ prefix and use handles [OK]
Common Mistakes:
  • Using incorrect function names without HAL prefix
  • Missing the timer handle argument
  • Using lowercase or camelCase incorrectly
3. Given the following code snippet, what is the duty cycle percentage of the PWM signal?
uint32_t period = 1000;
uint32_t pulse = 250;
// Timer configured with period and pulse
// PWM output uses pulse width = pulse
medium
A. 100%
B. 75%
C. 50%
D. 25%

Solution

  1. Step 1: Understand duty cycle formula

    Duty cycle = (pulse / period) * 100%
  2. Step 2: Calculate duty cycle with given values

    Duty cycle = (250 / 1000) * 100% = 25%
  3. Final Answer:

    25% -> Option D
  4. Quick Check:

    Duty cycle = 25% [OK]
Hint: Duty cycle = pulse divided by period times 100% [OK]
Common Mistakes:
  • Confusing pulse with period
  • Calculating 1000/250 instead of 250/1000
  • Forgetting to multiply by 100 for percentage
4. Identify the error in this PWM timer initialization code snippet:
TIM_HandleTypeDef htim;
htim.Init.Period = 1000;
htim.Init.Pulse = 500;
HAL_TIM_PWM_Start(&htim);
medium
A. Missing call to HAL_TIM_PWM_ConfigChannel before starting PWM
B. The 'Pulse' field requires pointer syntax like htim->Init.Pulse
C. Period value should be set after starting PWM
D. Timer handle 'htim' must be a pointer, not a variable

Solution

  1. Step 1: Check PWM initialization sequence

    Before starting PWM, the channel must be configured with pulse value using HAL_TIM_PWM_ConfigChannel.
  2. Step 2: Identify missing configuration call

    The code sets pulse in Init (which is incorrect) and skips HAL_TIM_PWM_ConfigChannel call.
  3. Final Answer:

    Missing call to HAL_TIM_PWM_ConfigChannel before starting PWM -> Option A
  4. Quick Check:

    ConfigChannel call needed before HAL_TIM_PWM_Start [OK]
Hint: Always configure PWM channel before starting timer [OK]
Common Mistakes:
  • Setting pulse in Init structure instead of channel config
  • Starting PWM without configuring channel
  • Assuming timer handle must be pointer variable
5. You want to generate a PWM signal with a 60% duty cycle and a frequency of 1 kHz using a timer with a 72 MHz clock. Which timer period and pulse values should you set? Assume timer prescaler is set to 71 (divides clock by 72).
hard
A. Period = 1000, Pulse = 600
B. Period = 72000, Pulse = 43200
C. Period = 999, Pulse = 600
D. Period = 71, Pulse = 43

Solution

  1. Step 1: Calculate timer frequency after prescaler

    Timer clock = 72 MHz / (71 + 1) = 1 MHz (1 microsecond per tick)
  2. Step 2: Calculate period for 1 kHz PWM frequency

    Period = (Timer frequency / PWM frequency) - 1 = (1,000,000 / 1,000) - 1 = 999
  3. Step 3: Calculate pulse for 60% duty cycle

    Pulse = Period * 0.6 = 999 * 0.6 = 599.4 ≈ 600
  4. Final Answer:

    Period = 999, Pulse = 600 -> Option C
  5. Quick Check:

    Period 999 and pulse 600 give 60% duty cycle at 1 kHz [OK]
Hint: Divide clock by prescaler, then calculate period and pulse [OK]
Common Mistakes:
  • Not adding 1 to prescaler or period calculations
  • Using full clock without prescaler division
  • Rounding pulse incorrectly
Recommended

Ready to prove it?

Pass the test and this pattern moves unknown strong while earning +1 Grip toward your certificate.

10 questions~5 mineasy hard