Hi,
I am trying to obtain a 10khz PWM (50%) on an output using Timer2 (see code below). It is working fine up to around 500Hz (2msec), above that (1kHz) I am getting only sporadic PWM bursts, PWM will run up to advertising then will stop, then timer has to overun to startPWM again.
As mentioned, I have S110 advertising running in background, I am certain that I am missing the Timer2 interrupt to update Compare 0 because advertising interrupt is in higer priority.
My question is, how can I easily output a 10kHz PWM without needing to enter an interrupt by software to update an output compare register?
Here's the code:
GPIOTE init:
// Configure GPIOTE channel 0 to toggle the PWM pin state
nrf_gpiote_task_config(0, LED_6, NRF_GPIOTE_POLARITY_TOGGLE, RF_GPIOTE_INITIAL_VALUE_LOW);
PPI init:
// Configure PPI channel 0 to toggle PWM_OUTPUT_PIN on every TIMER2 COMPARE[0] match.
NRF_PPI->CH[0].EEP = (uint32_t)&NRF_TIMER2->EVENTS_COMPARE[0];
NRF_PPI->CH[0].TEP = (uint32_t)&NRF_GPIOTE->TASKS_OUT[0];
// Enable PPI channel 0.
NRF_PPI->CHEN = (PPI_CHEN_CH0_Enabled << PPI_CHEN_CH0_Pos);
Timer init + start:
// Init TIMER2 for 10kHz PWM
NRF_TIMER2->MODE = TIMER_MODE_MODE_Timer; // Set the timer in Counter Mode
NRF_TIMER2->TASKS_CLEAR = 1; // Clear the tasks first to be usable for later
NRF_TIMER2->PRESCALER = 4; // 2^PRESCALER (values authorized 1 to 9) 4 : 16MHz / 16 = 10MHz
NRF_TIMER2->BITMODE = TIMER_BITMODE_BITMODE_16Bit; //Set counter to 16 bit resolution
NRF_TIMER2->CC[0] = 50;
// Enable OC1 interrupt on TIMER2
NRF_TIMER2->INTENSET = TIMER_INTENSET_COMPARE0_Enabled << TIMER_INTENSET_COMPARE0_Pos;
NVIC_EnableIRQ(TIMER2_IRQn);
// Start TIMER2
NRF_TIMER2->TASKS_START = true;
The interrupt:
void TIMER2_IRQHandler(void)
{
if (NRF_TIMER2->EVENTS_COMPARE[0] != 0)
{
NRF_TIMER2->EVENTS_COMPARE[0] = 0; // Reset event
// Set next compare in 50nsec
NRF_TIMER2->CC[0] += 50;
}
}
Thanks for any help on this.
Phil