This is the documentation for the latest (main) development branch. If you are looking for the documentation of previous releases, use the drop-down menu on the left and select the desired version.

PWM Driver

Introduction

Pulse Width Modulation (PWM) is a control technique that is increasingly being applied in the field of IoT. PWM controls voltage or power by adjusting the duty cycle of pulse signals, making it an efficient means of analog signal control.
PWM is widely used in smart homes, industrial automation, medical devices, smart agriculture, and other fields.
  • Smart Homes: PWM technology is used in smart lighting systems to adjust the brightness and color temperature of lights, improving energy efficiency. In smart audio devices, PWM is used to control volume and sound quality, providing a better user experience.

  • Industrial Automation: In the industrial field, PWM is widely used in motor control systems to precisely adjust motor speed and torque, enhancing the efficiency and accuracy of production lines.

  • Medical Devices: PWM technology is applied in medical devices such as ventilators and infusion pumps to precisely control output parameters, ensuring stable and reliable operation of the equipment.

  • Smart Agriculture: In smart agriculture, PWM is used to control irrigation system water flow, fertilizer concentration in fertilization systems, and other parameters, aiding in the development of precision agriculture.

Function List

  • Supports 2-channel input signal capture (PWM0/PWM4).

  • Supports 5-channel PWM signal generation.

  • Supports 5-channel brake function.

Function Overview

PWM Flowchart

Output Modes

  • Independent Output: Each channel outputs a PWM waveform independently.

    PWM Independent Output
  • Dual-Channel Synchronous Output: ch0+ch1 or ch2+ch3 synchronous output.

    PWM Dual-Channel Synchronous Output
  • All-Channel Synchronous Output: All channels output synchronously.

    PWM All-Channel Synchronous Output
  • Dual-Channel Complementary Output: ch0+ch1 or ch2+ch3 output complementary waveforms.

    PWM Dual-Channel Complementary Output

Brake Modes

Depending on GPIO configuration, the following two brake modes can be achieved:

  • When the brake input GPIO detects a low level, the corresponding channel outputs a specified high/low level.

  • When the brake input GPIO detects a high level, the corresponding channel outputs a specified high/low level.

  • The input signal level for braking is determined by the GPIO initialization configuration. If it is pulled up, then triggering is detected at a low level, and vice versa.

    PWM Brake

Note

If you need to output a PWM waveform when triggered (raising the brake trigger pin), you need to specify the period and clkdiv. Set the frequency according to the formula in the documentation. Setting it to 0 means level mode.

Capture Mode

Monitor input signals from the ch0 or ch4 channel. The sampling range is 3 ~16K.

PWM Capture

Note

The period and clkdiv parameters in capture mode should be set larger to sample low frequencies; conversely, set them smaller to sample high frequencies.

Configuration

PWM Channel Configuration

Configure channels by calling the function wm_drv_pwm_channel_init.
Channel configuration requires passing a configuration structure wm_drv_pwm_channel_cfg_t to the channel configuration function.
Use the function wm_drv_pwm_channels_start to start the configured PWM channel and wm_drv_pwm_channels_stop to stop the configured PWM channel.

PWM Frequency Configuration

PWM frequency is the number of times within one second that the signal transitions from high to low and back to high, or the number of PWM cycles in one second. We provide two methods to change the PWM frequency:

  • Call wm_drv_pwm_set_channel_freq to set the frequency of a specific PWM channel.

  • Call wm_drv_pwm_set_channel_period_clkdiv to set the frequency of a PWM channel based on the given period and clock divider value.

  • Call wm_drv_pwm_get_channel_freq to get the current frequency of a specific PWM channel.

Note

The output frequency calculation formula is freq = main clock / ((period + 1) * clkdiv). According to the formula, some frequencies cannot be set.

PWM Duty Cycle Configuration

The PWM duty cycle is the ratio of the high-level time to the total period time within one pulse cycle. By adjusting the duty cycle, the pulse width can be adjusted. The duty cycle range is from 0 to 255 (default: 40).

  • Call wm_drv_pwm_set_channel_duty to set the duty cycle of a PWM channel.

  • Call wm_drv_pwm_get_channel_duty to get the duty cycle of a PWM channel.

Note

The parameter setting of 10 represents 10% and does not support decimal formats.

Note

Duty cycle = (duty + 1) / (period + 1).

PWM Period Configuration

The PWM period is the time of one pulse signal, and each period has a cycle count range from 0 to 255 (default: 199).
When the cycle count is 0, this function is disabled. A value greater than 0 stops output after the specified cycle count.
  • Call wm_drv_pwm_set_channel_period_num to set the number of cycles before generating an interrupt for a specific PWM channel.

  • Call wm_drv_pwm_get_channel_period_num to get the cycle count interrupt setting for a specific PWM channel.

PWM Clock Division Configuration

Clock division indicates the number of clock signal cycles per second.

  • Call wm_drv_pwm_get_channel_period_clkdiv to get the clock division value of the PWM channel.

Note

clkdiv values of 0 and 1 indicate no division.

Note

The period is affected by the frequency.

Main Functions

Output Function

Starting Condition:

  • Define and initialize the wm_drv_pwm_channel_cfg_t structure. Set the basic parameters of the PWM channel, choose the output mode, and initialize the PWM channel.

Related Timing APIs:

  • Call wm_drv_pwm_init to initialize the PWM device and obtain the device pointer.

  • Use wm_drv_pwm_channel_init to initialize the PWM channel according to the configuration structure.

  • Call wm_drv_pwm_channels_start to start the PWM channel and begin generating the PWM signal.

  • Call wm_drv_pwm_set_channel_duty as needed to dynamically set the duty cycle of the channel.

  • Set the period, frequency, etc., as needed.

Result:

  • Outputs a waveform with the set duty cycle.

Brake Function

Starting Condition:

  • Define and initialize the wm_drv_pwm_channel_cfg_t structure. Set the basic parameters of the PWM channel, choose the brake mode, and initialize the PWM channel.

Related Timing APIs:

  • Call wm_drv_pwm_init to initialize the PWM device and obtain the device pointer.

  • Use wm_drv_pwm_set_channel_brake_level to set the brake mode output high/low level of the PWM channel.

  • Use wm_drv_pwm_channel_init to initialize the PWM channel according to the configuration structure.

  • Call wm_drv_pwm_channels_start to start the PWM channel.

Result:

  • When the brake input GPIO detects a low level, the corresponding channel outputs the specified high/low level.

  • When the brake input GPIO detects a high level, the corresponding channel outputs the specified high/low level.

Capture Function

Starting Condition:

  • Define and initialize the wm_drv_pwm_channel_cfg_t structure. Set the basic parameters of the PWM channel, choose the capture mode, and initialize the PWM channel.

Related Timing APIs:

  • Call wm_drv_pwm_init to initialize the PWM device and obtain the device pointer.

  • Use wm_drv_pwm_channel_init to initialize the PWM channel according to the configuration structure.

  • Call wm_drv_pwm_channels_start to start the PWM channel.

Result:

  • Captures the pulse.

Application Example

int main(void)
{
    wm_drv_pwm_channel_cfg_t cfg = { 0 };

    wm_device_t *pwm_device = wm_drv_pwm_init("pwm");
    if (pwm_device == NULL) {
        WM_PWM_DEMO_LOG_E("PWM driver init Failed!\n");

        return WM_ERR_FAILED;
    }

    cfg.channel      = WM_PWM_CHANNEL_0;
    cfg.mode         = WM_PWM_OUT_ALLSYNC;
    cfg.clkdiv       = WM_PWM_CLKDIV_DEFAULT;
    cfg.period_cycle = WM_PWM_PERIOD_DEFAULT;
    cfg.duty_cycle   = WM_PWM_DUTY_CYCLE_DEFAULT;
    cfg.autoload     = true;

    if (wm_drv_pwm_channel_init(pwm_device, &cfg) != WM_ERR_SUCCESS) {
        WM_PWM_DEMO_LOG_E("PWM driver channel init failed!\n");
    }

    if (wm_drv_pwm_channels_start(pwm_device)) {
        WM_PWM_DEMO_LOG_E("PWM driver channel start failed!\n");
    }
    /* After PWM initialization is complete, call various functional functions, such as wm_drv_pwm_set_channel_duty, to set the duty cycle */

    return WM_ERR_SUCCESS;
}

API Reference

To find PWM-related APIs, please refer to:

PWM API Reference