nRF5 SDK v12.1.0
PWM
This information applies to the nRF52 Series only.

The Pulse Width Modulation (PWM) module driver includes two layers: the hardware access layer (HAL) and the driver layer (DRV).

The hardware access layer provides basic APIs for accessing the registers of the PWM peripheral. See the API documentation for the PWM HAL for details.

The driver layer provides APIs on a higher level than the HAL. See the API documentation for the PWM driver for details.

Key features include:

The PWM Driver Example provides sample code that you can use to quickly get started.

Driver configuration

The configurable parameters include:

The default configuration for the PWM driver is located in sdk_config.h. This configuration is used when nrf_drv_pwm_init is called with a NULL pointer to the configuration structure.

Before it can be used for a particular instance of the peripheral, the driver must be explicitly enabled for this instance in sdk_config.h.

Using the PWM driver

First, call nrf_drv_pwm_init to initialize and configure the driver for a given instance of the peripheral. See the nrf_drv_pwm_config_t structure documentation for possible configuration options.

For example:

uint32_t err_code;
nrf_drv_pwm_config_t const config0 =
{
{
BSP_LED_0 | NRF_DRV_PWM_PIN_INVERTED, // channel 0
},
.irq_priority = APP_IRQ_PRIORITY_LOW,
.base_clock = NRF_PWM_CLK_1MHz,
.count_mode = NRF_PWM_MODE_UP,
.top_value = 1000,
.load_mode = NRF_PWM_LOAD_COMMON,
.step_mode = NRF_PWM_STEP_AUTO
};
err_code = nrf_drv_pwm_init(&m_pwm0, &config0, NULL);
if (err_code != NRF_SUCCESS)
{
// Initialization failed. Take recovery action.
}

Next, define a sequence of duty cycle values using the nrf_pwm_sequence_t structure. For example:

static nrf_pwm_values_common_t seq_values[] =
{
0, 200, 400, 600, 800, 1000
};
nrf_pwm_sequence_t const seq =
{
.values.p_common = seq_values,
.length = NRF_PWM_VALUES_LENGTH(seq_values),
.repeats = 0,
.end_delay = 0
};

Start the playback of the sequence by calling nrf_drv_pwm_simple_playback.

You can play the sequence several times (for example, 3 times):

nrf_drv_pwm_simple_playback(&m_pwm0, &seq, 3, 0);

Additionally, the playback can be repeated in a loop:

If a more complicated pattern of duty cycles is required that involves two sequence definitions, use nrf_drv_pwm_complex_playback.

If a sequence must be updated during the playback, define a proper event handler and pass it as parameter in the call to nrf_drv_pwm_init. By default, the handler is called at the end of the playback (or right before the next iteration in a loop), but it can be configured to be called when a sequence is completely loaded.

For example:

static void event_handler(nrf_drv_pwm_evt_type_t event_type)
{
if (event_type == NRF_DRV_PWM_EVT_END_SEQ0)
{
// Update sequence 0.
/* ... */
}
else if (event_type == NRF_DRV_PWM_EVT_END_SEQ1)
{
// Update sequence 1.
/* ... */
}
}
/* ... */
err_code = nrf_drv_pwm_init(&m_pwm0, &config0, event_handler);
/* ... */
nrf_drv_pwm_complex_playback(&m_pwm0, &seq0, &seq1, 1,

Entries in the array of duty cycle values can be modified directly, since the peripheral loads the values as the sequence is played back. If the whole sequence definition must be changed, use nrf_drv_pwm_sequence_update. If only some part of the definition must be modified, you can use one of the other updating functions.

At any time, the playback can be stopped by calling nrf_drv_pwm_stop. The pulse generation will stop at the end of the current PWM period.

When the PWM driver is no longer needed or its configuration must be changed, call nrf_drv_pwm_uninit.


Documentation feedback | Developer Zone | Subscribe | Updated