Setting up PWM in nRF52
By: Sanskar Biswal
Tags: Nrf52, Electronics, Programming, Tutorial, Embedded Systems

Prerequisites

This is tutorial is not intended to be a guide for learning C language or about the Nordic SDK platform. It’s primary target is to provide developers a concise guide about integrating peripheral modules and features into active applications.

If you are a beginner, I would recommend you look into an nRF52 Project Setup guide like this one.

Another easy way to get started with coding, without bothering with all basic stuff like files and driver inclusion, check out this Code Generation Tool

nrf52 Code Generator: https://vicara.co/nrf52-code-generator

PWM Signal

Pulse Width Modulation is a technique that is implemented by varying the duration for which a signal is On or Off.

Fig.2 Pulse Width Modulation

The duration of the pulse width may correspond to the amplitude, frequency or phase of an analog signal. This method reduces the average power consumed in the transmission when compared to an analog signal with the same data.

PWM is also used for controlling Motors and LED’s, and this allows a much better control of these devices.

Implementing PWM in nRF52832

In the following section, I will provide a guide as it has been tested in the nRF52832 Dev Kit. However, the same structure will remain common across all nRF52 devices.

Including correct Headers

Fig.3 Project Explorer in SES

Include the driver file which controls PWM in the nRF52 devices. This should be a file titled, nrf_drv_pwm.c It should be available at SDK/integration/nrfx/legacy folder.

Update sdk_config.h File

PWM_ENABLED has to be enabled.

PWMn_ENABLED has to be enabled, where n is the PWM instance number.

Fig.4 Enable PWM

Fig.5 Enable PWM Instance

In main.c File

Header File

#include "nrf_drv_pwm.h"

Define PWM Instance

static nrf_drv_pwm_t m_pwm = NRF_DRV_PWM_INSTANCE(1);

The nRF52832 has 3 Instances. This will vary with the chosen nRF52 module, so it is essential to verify this with its product specification and datasheet.

PWM Instance Callback

Each instance of PWM that is being used will need to be handled by its individual callback. This function will handle the signals generated by that instance.

static void pwm_handler(nrf_drv_pwm_evt_type_t event_type)

{

switch(event_type-){

case // EVENT ID:

break;

default;

break;

}

}

Define Initialization Function

This function will set the parameters with which PWM instance is going to operation. Multiple instances can be initialized in the same function definition.

static void pwm_init()

{

nrf_drv_pwm_config_t const config =

{

.output_pins =

{

17, // channel 0

NRF_DRV_PWM_PIN_NOT_USED, // channel 1

NRF_DRV_PWM_PIN_NOT_USED, // channel 2

NRF_DRV_PWM_PIN_NOT_USED // channel 3

},

.irq_priority = APP_IRQ_PRIORITY_LOWEST,

.base_clock = NRF_PWM_CLK_125kHz,

.count_mode = NRF_PWM_MODE_UP,

.top_value = 12500,

.load_mode = NRF_PWM_LOAD_INDIVIDUAL,

.step_mode = NRF_PWM_STEP_AUTO

};

APP_ERROR_CHECK(nrf_drv_pwm_init(&m_pwm, &config, pwm_handler));

}

For PWM, the only channel specific configuration is the pin used for that channel. But each instance needs to be configured separately though. All 4 pins can be set to NRF_DRV_PWM_PIN_NOT_USED i.e. PWM instance is configured but no pins are asigned.

Add Initialize Function to main function call

pwm_init(); // After default definition, before Advertise Start

Conclusion

With the above steps anyone can easily get started with incorporating PWM control into their application code.

NOTE

There is another easier method to initialize and auto-generate code for nRF52. This tool, will handle all library additions and code generations for a variety of peripherals like SPI, I2C, UART etc.