This post is older than 2 years and might not be relevant anymore
More Info: Consider searching for newer posts
This discussion has been locked.
You can no longer post new replies to this discussion. If you have a question you can start a new discussion

PWM clock on nRF52 does not lock on oscilloscope

I have a very simple program that generates a 50% duty cycle clock using the NRF_PWM0 on the new nRF52 device. Unfortunately, my Tektronix 1GHz oscilloscope doesn't lock to the signal. If I used a Timer and GPIOTE with PPI then the clock was perfect.

I am wondering if the PWM_CLK input to the PWM hardware resource is not correct. The reference manual just uses the PWM_CLK in description but doesn't describe what it is or how do I configure or start/lock it. Any ideas?

Note that I am not using any SoftDevice and this is on a custom board with just the nRF52 part and nothing else.

int main (void)
{
    // Start 16 MHz crystal oscillator .
    NRF_CLOCK->EVENTS_HFCLKSTARTED = 0;
    NRF_CLOCK->TASKS_HFCLKSTART    = 1;

    // Wait for the external oscillator to start up.
    while (NRF_CLOCK->EVENTS_HFCLKSTARTED == 0) {
    }

    NRF_PWM0->ENABLE = (PWM_ENABLE_ENABLE_Enabled << PWM_ENABLE_ENABLE_Pos);
    NRF_PWM0->PRESCALER = NRF_PWM_CLK_1MHz;
    NRF_PWM0->MODE = NRF_PWM_MODE_UP;
    NRF_PWM0->COUNTERTOP = 20;
    NRF_PWM0->PSEL.OUT[0] = 6;
    NRF_PWM0->PSEL.OUT[1] = NRF_PWM_PIN_NOT_CONNECTED;
    NRF_PWM0->PSEL.OUT[2] = NRF_PWM_PIN_NOT_CONNECTED;
    NRF_PWM0->PSEL.OUT[3] = NRF_PWM_PIN_NOT_CONNECTED;
    NRF_PWM0->DECODER = ((uint32_t)NRF_PWM_LOAD_INDIVIDUAL << PWM_DECODER_LOAD_Pos) |
                        ((uint32_t)NRF_PWM_STEP_AUTO << PWM_DECODER_MODE_Pos);
    NRF_PWM0->SHORTS = 0;
    NRF_PWM0->INTEN = 0;
    static nrf_pwm_values_individual_t duty = 
    {
        .channel_0 = 10,
        .channel_1 = 10,
        .channel_2 = 10,
        .channel_3 = 10,
    };

    NRF_PWM0->SEQ[0].PTR = (uint32_t)&duty;
    NRF_PWM0->SEQ[0].CNT = NRF_PWM_VALUES_LENGTH(duty);
    NRF_PWM0->SEQ[0].REFRESH = 0;
    NRF_PWM0->SEQ[0].ENDDELAY = 0;
    NRF_PWM0->TASKS_SEQSTART[0] = 1;

    while (1) {
    }
}

Thanks a lot!

Parents Reply Children
  • I did want to ask a thing though - I can use functions from nrf_pwm.h for everything other than starting the PWM task itself. For that I have to use the direct write to the register. Is the following correct and intended? Why is there no function to write to TASKS_SEQSTART[0]

    nrf_gpio_cfg_output(SAMPLE);
    nrf_pwm_enable(NRF_PWM0);
    nrf_pwm_pins_set(NRF_PWM0, out_pins);
    nrf_pwm_configure(NRF_PWM0, NRF_PWM_CLK_16MHz, NRF_PWM_MODE_UP, 50);
    nrf_pwm_decoder_set(NRF_PWM0, NRF_PWM_LOAD_INDIVIDUAL, NRF_PWM_STEP_AUTO);
    nrf_pwm_shorts_set(NRF_PWM0, 0);
    nrf_pwm_int_set(NRF_PWM0, 0);
    nrf_pwm_loop_set(NRF_PWM0, 0);
    nrf_pwm_sequence_set(NRF_PWM0, 0, &seq);
    NRF_PWM0->TASKS_SEQSTART[0] = 1; // <=== why no function?
    
  • You can use nrw_pwm_tasks_trigger.

Related