This post is older than 2 years and might not be relevant anymore
More Info: Consider searching for newer posts

nRF52832 PWM loop forever between duty cycles defined in a sequence

Hi,

This is my first post here. I hope I will follow the structure of a good question.

I want to have a sequence of defined duty cycles (let's say 4 values). The aim is to loop forever between the 4 values in this sequence in order to "smoothly" dim a LED (use of a single output pin). I would like to run PWM by itself to do that without any ISR support by CPU.

I'm working with the NRF52832. I can't use the SDK because we are building our own code.

I have looked at the Nordic datasheet (rev 1.1) and at this post but I still haven't understood how to solve my problem.

Here is what I tried as code:

#include "pwm.h"

#include "nrf52.h"
#include "nrf52_bitfields.h"
#include "nrf_gpio.h"

//#include "app.h"

static uint32_t pwm_max_value = 100;


static uint16_t pwm_seq[4][4]={{10, 10, 10, 10}, {25, 25, 25, 25}, { 50, 50, 50, 50}, {75,75,75,75}}; // Pay attention that it is INVERSE LOGICAL in the sequence (ex: 1= 99%, 90 = 10%)
                                      
/** Is PWM Initialized */
static bool m_initialized = false;

void pwm_init()
{
    nrf_gpio_cfg_output(BOARD_PWM_OUTPUT_GPIO);
    nrf_gpio_pin_clear(BOARD_PWM_OUTPUT_GPIO);

    // Select output pin
    NRF_PWM0->PSEL.OUT[0] = (BOARD_PWM_OUTPUT_GPIO << PWM_PSEL_OUT_PIN_Pos) |
                            (PWM_PSEL_OUT_CONNECT_Connected <<
                                                     PWM_PSEL_OUT_CONNECT_Pos);
    // Enable PWM module
    NRF_PWM0->ENABLE      = (PWM_ENABLE_ENABLE_Enabled << PWM_ENABLE_ENABLE_Pos);

    // Set Mode
    NRF_PWM0->MODE        = (PWM_MODE_UPDOWN_Up << PWM_MODE_UPDOWN_Pos);

    // Set prescaler to set frequency clock of 1MHz (= f_default(16MHz)/PWM_PRESCALER_PRESCALER_DIV_16)
    NRF_PWM0->PRESCALER   = (PWM_PRESCALER_PRESCALER_DIV_16 <<
                                                     PWM_PRESCALER_PRESCALER_Pos);
    // Set counter top to have a PWM frequency of 10 KHz (= PWM_PRESCALER_PRESCALER_DIV_16/pwm_max_value)
    NRF_PWM0->COUNTERTOP  = (pwm_max_value << PWM_COUNTERTOP_COUNTERTOP_Pos);

    NRF_PWM0->LOOP        = (PWM_LOOP_CNT_Disabled<< PWM_LOOP_CNT_Pos);

    NRF_PWM0->DECODER   = (PWM_DECODER_LOAD_WaveForm << PWM_DECODER_LOAD_Pos) |
                          (PWM_DECODER_MODE_RefreshCount << PWM_DECODER_MODE_Pos);

    NRF_PWM0->SEQ[0].PTR  = ((uint32_t)(pwm_seq) << PWM_SEQ_PTR_PTR_Pos);
    NRF_PWM0->SEQ[0].CNT  = ((sizeof(pwm_seq) / sizeof(uint16_t)) << PWM_SEQ_CNT_CNT_Pos);
    NRF_PWM0->SEQ[0].REFRESH  = 1;
    NRF_PWM0->SEQ[0].ENDDELAY = 0;
    NRF_PWM0->TASKS_SEQSTART[0] = 1;

    m_initialized = true;
}

The file pwm.h simply includes the header of pwm_init().

Any comments or suggestions about how I have to do ?

Thanks in advance for your answer,

Best regards,

Florent

Parents Reply Children
No Data
Related