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

PWM / Timer question

HI, I want to use PWM to control various hardware (LED's, etc ..) so I started off from the suggested PWM code example, found in this forum + modified it as I want to use a "no -irq" scheme (runs w/o interrupt).

Basically, I use the same mechanism as in the example, with CC[0] responsible for the complete period, and another CC responsible for the "on" phase of the PWM.

I ended up with something like:

  • in my init_pwm function:
ppi_enable_channel(config->ppi_channel[2],&PWM_TIMER->EVENTS_COMPARE[0], &NRF_GPIOTE->TASKS_OUT[pwm_gpiote_channel[1]]); //
    ppi_enable_channel(config->ppi_channel[3],&PWM_TIMER->EVENTS_COMPARE[2], &NRF_GPIOTE->TASKS_OUT[pwm_gpiote_channel[1]]); // LED0

nrf_gpiote_task_config(pwm_gpiote_channel[1], pwm_io_ch[1], NRF_GPIOTE_POLARITY_TOGGLE, NRF_GPIOTE_INITIAL_VALUE_LOW);

PWM_TIMER->CC[0] = pwm_max_value; // this one for the whole period, will never change

(of course, Timer2 is used and initialised correctly.) Then, in ly "pwm_set_value" function, after A LOT of struggling :

    // Force the counter to stop and busy wait one period w/c
    PWM_TIMER->EVENTS_COMPARE[0] = 0;
    PWM_TIMER->SHORTS = TIMER_SHORTS_COMPARE0_CLEAR_Msk | TIMER_SHORTS_COMPARE0_STOP_Msk;
    PWM_TIMER->TASKS_START = 1;
    nrf_delay_us(pwm_period_us EVENTS_COMPARE[0] = 0;
    PWM_TIMER->CC[pwm_channel + 1] = value; // this one for the duty cycle (0 .. pwm_max_value)
    PWM_TIMER->SHORTS = TIMER_SHORTS_COMPARE0_CLEAR_Msk; // reset count when end of period detected
PWM_TIMER->TASKS_START = 1; // (re)-start now !

this is working fine .... however, for making it work, i had to do the following un-explained things:

  • stopping the time on the COMPARE0 event (which is monitoring the full rage) instead of on COMPARE3 (which monitors the positive phase) as it was my first thought
  • inverting the duty cycle period

Before thse 2 steps, it was working very unreliably, with the all things sometimes "inverting itself". Also I noticed that, adding PWM_TIMER->TASKS_STOP = 1; to stop explicitely the timer, was making tngs much worse ...

Is there an explanation to these strange behavior ? and Application ote somewhere .. .as the doc in the Tech Ref Manual is clearly not containing much :-( ?

Jacques PS: that said, I found the whole PPI / GPIOTE conenctivity VERY clever ! good job guys !

Related