Skip to content

PWM glitches with analogWrite() on CH32V003Β #223

@BerranRemzi

Description

@BerranRemzi

Problem

analogWrite(PD4, duty) occasionally produces glitches on the PWM output. Duty cycle changes take effect mid-cycle, rather than at cycle boundaries.

Image

Reproduction

for(int duty = 0; duty < 255; duty++) {
    analogWrite(PD4, duty);  // Glitches appear here
    delay(1);
}

Root Cause

Timer preload registers are not enabled - capture compare updates the values immediately rather than being synchronized to timer overflow (or PWM end).

Solution

Enable preload for used PWM channels.
I enabled it in my main() function:

  // Enable TIM2 Channel 1 Preload Enable (CH1PE) bit
  // This enables shadow register for TIM2 CH1 compare value
  TIM2->CHCTLR1 |= TIM_OC1PE;

For a universal solution, the code below needs to be added in void HardwareTimer::setMode(uint32_t channel, TimerModes_t mode, PinName pin):

// Enable preload (shadow registers) for PWM channel to prevent duty cycle glitches
// Ensures duty cycle updates only take effect at the start of the next PWM cycle
TIM_OC1PreloadConfig(_timerObj.handle.Instance, TIM_OCPreload_Enable); 
TIM_OC2PreloadConfig(_timerObj.handle.Instance, TIM_OCPreload_Enable);
TIM_OC3PreloadConfig(_timerObj.handle.Instance, TIM_OCPreload_Enable);
TIM_OC4PreloadConfig(_timerObj.handle.Instance, TIM_OCPreload_Enable); 

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions