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
  • First I just want to point out that since you are using nRF52, there is an entire PWM peripheral for you to use, so you don't have to use the software PWM library.

    The PWM library generates a PWM waveform using a combination of a Timer instance and the PPI.

    One thing I notice is that you are creating the APP PWM instance using Timer0. Are you using a SoftDevice with this? The SoftDevice reserves the use of Timer0, so creating the App PWM instance with Timer0 is sure to cause issue.

    Another thing is I see is that in your ppi_timer_stop_counter_init() and ppi_gpiote_counter_init(), you are assigning tasks and events to specific PPI channels. As mentioned before, the App PWM library use PPI. If you initialize PPI with your function after you initialize the App PWM library, you might have overwritten the PPI configurations the App PWM library uses to work. Just as you have guessed.

Reply
  • First I just want to point out that since you are using nRF52, there is an entire PWM peripheral for you to use, so you don't have to use the software PWM library.

    The PWM library generates a PWM waveform using a combination of a Timer instance and the PPI.

    One thing I notice is that you are creating the APP PWM instance using Timer0. Are you using a SoftDevice with this? The SoftDevice reserves the use of Timer0, so creating the App PWM instance with Timer0 is sure to cause issue.

    Another thing is I see is that in your ppi_timer_stop_counter_init() and ppi_gpiote_counter_init(), you are assigning tasks and events to specific PPI channels. As mentioned before, the App PWM library use PPI. If you initialize PPI with your function after you initialize the App PWM library, you might have overwritten the PPI configurations the App PWM library uses to work. Just as you have guessed.

Children
No Data
Related