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

PPI does not work with PWM

URGENT

First of all, I have to mention that I dont understand PPI.

I have application which uses PWM to control a pump which is connected to the nRF52. To the nRF52 is a sensor connected, which gives me a frequency.

To measure this frequency I use this example:

devzone.nordicsemi.com/.../

Now when I add this code to my application, then the pwm wont work anymore. Why?

What does PPI have to do with PWM?

Here is my setup of the pwm:

APP_PWM_INSTANCE(PWM1,0);

static void PWMinit(void)
{
 app_pwm_config_t pwm1_cfg = APP_PWM_DEFAULT_CONFIG_1CH(9000,27);
 pwm1_cfg.pin_polarity[0] = APP_PWM_POLARITY_ACTIVE_HIGH;
 app_pwm_init(&PWM1, &pwm1_cfg, pwm_ready_callback);
 app_pwm_enable(&PWM1);
}

And here the frequency measuring part:

static void timer_init()
{
 NRF_TIMER1->TASKS_STOP = 1;
 NRF_TIMER1->MODE = TIMER_MODE_MODE_Timer;
 NRF_TIMER1->PRESCALER = 8;  // Fhck / 2^8 
 NRF_TIMER1->CC[0] = 62500;  // 62500 - 1s

 NRF_TIMER1->BITMODE = (TIMER_BITMODE_BITMODE_16Bit << TIMER_BITMODE_BITMODE_Pos);   

 NRF_TIMER1->TASKS_CLEAR = 1;
 NRF_TIMER1->INTENSET = (TIMER_INTENSET_COMPARE0_Enabled << TIMER_INTENSET_COMPARE0_Pos);

 NRF_TIMER1->EVENTS_COMPARE[0] = 0;
}

static void counter_init()
{
 NRF_TIMER2->TASKS_STOP = 1; 
 NRF_TIMER2->MODE = TIMER_MODE_MODE_Counter;
 NRF_TIMER2->BITMODE = (TIMER_BITMODE_BITMODE_24Bit << TIMER_BITMODE_BITMODE_Pos);
 NRF_TIMER2->TASKS_CLEAR = 1;
 NRF_TIMER2->EVENTS_COMPARE[0] = 0;
}

static void gpiote_init(uint32_t pin)
{
 NRF_GPIOTE->CONFIG[0]   =   0x01 << 0;                              // MODE: Event
 NRF_GPIOTE->CONFIG[0]   |=  pin << 8;                               // Pin number
 NRF_GPIOTE->CONFIG[0]   |=  GPIOTE_CONFIG_POLARITY_LoToHi  << 16;   // Event rising edge    
}

static void ppi_timer_stop_counter_init()
{
 NRF_PPI->CHEN |= 1 << 0;
 *(&(NRF_PPI->CH0_EEP)) = (uint32_t)&NRF_TIMER1->EVENTS_COMPARE[0];
 *(&(NRF_PPI->CH0_TEP)) = (uint32_t)&NRF_TIMER2->TASKS_STOP;
 NRF_PPI->CHENSET |= 1 << 0;
}

static void ppi_gpiote_counter_init()
{
 NRF_PPI->CHEN |= 1 << 1;
 *(&(NRF_PPI->CH1_EEP)) = (uint32_t)&NRF_GPIOTE->EVENTS_IN[0];
 *(&(NRF_PPI->CH1_TEP)) = (uint32_t)&NRF_TIMER2->TASKS_COUNT;
 NRF_PPI->CHENSET |= 1 << 1;
}

void TIMER1_IRQHandler(void) 
{
  if (NRF_TIMER1->EVENTS_COMPARE[0] != 0)
  {
    NRF_TIMER1->EVENTS_COMPARE[0] = 0;
    NRF_TIMER2->TASKS_CAPTURE[0] = 1;

   frequency = NRF_TIMER2->CC[0];

    NRF_TIMER1->TASKS_CLEAR = 1;
    NRF_TIMER2->TASKS_CLEAR = 1;    

    NRF_TIMER2->TASKS_START = 1;            
  }
}

Is it possible that they use the same PPI channel? How can I choose the channel of PWM PPI?

Any hints?

On what I have to pay attention when I use PWM and PPI?

UPDATE

I think the problem is not in the PPI. I changed all of them. And the same for the timers.

What else can I do?

The problem is between PWMinit() and gpiote_init functions.

But this is strange. Because in the gpiote_init function I only choose a mode,pin and polaritity.

Parents
  • Here is the PWM Module page for SDK 11.

    From there, I draw two key info to answer your question:

    • The PWM driver supports multiple PWM instances.
    • Each PWM instance supports up to 4 PWM output.

    So yes, you can get 6 different duty cycle.

    In a small project I did ages ago to evaluate nRF52's PWM peripheral, I use this line to update PWM duty cycle:

    nrf_drv_pwm_sequence_values_update(&m_pwm, 1, m_nrf_pwm_values_50_duty);
    

    I remember trying two other ways to toggle PWM on and off:

    • Step through different duty cycle values in a looped sequence.
    • Trigger PWM peripheral task using nrf_pwm_task_trigger()

    But I don't have any record of how those attempts turned out...

    Do refer to the PWM Module website for more info on HAL and Driver APIs.

Reply
  • Here is the PWM Module page for SDK 11.

    From there, I draw two key info to answer your question:

    • The PWM driver supports multiple PWM instances.
    • Each PWM instance supports up to 4 PWM output.

    So yes, you can get 6 different duty cycle.

    In a small project I did ages ago to evaluate nRF52's PWM peripheral, I use this line to update PWM duty cycle:

    nrf_drv_pwm_sequence_values_update(&m_pwm, 1, m_nrf_pwm_values_50_duty);
    

    I remember trying two other ways to toggle PWM on and off:

    • Step through different duty cycle values in a looped sequence.
    • Trigger PWM peripheral task using nrf_pwm_task_trigger()

    But I don't have any record of how those attempts turned out...

    Do refer to the PWM Module website for more info on HAL and Driver APIs.

Children
No Data
Related