nRF5 SDK v13.0.0
PWM

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.

It is also possible to start playbacks via PPI. To take advantage of this functionality, use NRF_DRV_PWM_FLAG_START_VIA_TASK when calling the desired playback function. The function will then only prepare the specified playback, and it will return the address of the task to be triggered. Use the returned value as the task endpoint for the configured PPI channel. Sample code:

uint32_t pwm_start_task_address =
nrf_drv_pwm_simple_playback(&m_pwm0, &seq0, 1,
/* ... */
nrf_ppi_channel_t ppi_pwm_trigger;
triggering_event_address, pwm_start_task_address));

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