Hello,
I want to make a PWM signal that fires an interrupt at the end of the PWM period. I want to use two CC registers - one for the pulse width and one for the period width. On compare event I want to trigger one task that sets and another that clears a pin. I want to use direct register access (no libraries). I have a softdevice running. My part is NRF51822.
Here is my code:
void TIMER1_IRQHandler(){
NVIC_ClearPendingIRQ(TIMER1_IRQn);
NRF_TIMER1->EVENTS_COMPARE[0] = 0;
if(NRF_TIMER1->EVENTS_COMPARE[1]){
//One PWM period has elapsed
NRF_TIMER1->EVENTS_COMPARE[1] = 0;
NRF_TIMER1->TASKS_CLEAR = 1;
pwm_triggers++;
}
}
inline void pwm_init(void){
NRF_GPIOTE->CONFIG[0] = (0x03 | (25<<8) | (0x01 << 16) | (0x01 << 20)); //Make GPIO a task, use pin 25, task sets pin high, init as pin high, 0x111903
NRF_GPIOTE->CONFIG[1] = (0x03 | (25<<8) | (0x02 << 16) | (0x00<< 20)); //Make GPIO a task, use pin 25, task sets pin low, init as pin low, 0x21903
NRF_PPI->CHG[0] |= 0x03;
NRF_PPI->CH[0].EEP = (uint32_t)&NRF_TIMER1->EVENTS_COMPARE[0];
NRF_PPI->CH[0].TEP = (uint32_t)&NRF_GPIOTE->TASKS_OUT[0];
NRF_PPI->CH[1].EEP = (uint32_t)&NRF_TIMER1->EVENTS_COMPARE[1];
NRF_PPI->CH[1].TEP = (uint32_t)&NRF_GPIOTE->TASKS_OUT[1];
NRF_PPI->CHEN |= 0x03;
NRF_TIMER1->POWER = 0x01;
NRF_TIMER1->TASKS_CLEAR = 1;
NRF_TIMER1->MODE = 0x00; //Timer mode
NRF_TIMER1->BITMODE = 0x01; //8-bit
NRF_TIMER1->PRESCALER = 0x00; //Prescaler = /1
NRF_TIMER1->CC[0] = 1;
NRF_TIMER1->CC[1] = 20;
while(NRF_TIMER1->CC[0] != 1){ }
while(NRF_TIMER1->CC[1] != 20){ }
NRF_TIMER1->INTENSET = 0x30000; //Enable interrupt on compare register 0 & 1
NVIC_SetPriority(TIMER1_IRQn, APP_IRQ_PRIORITY_HIGHEST);
NVIC_ClearPendingIRQ(TIMER1_IRQn);
NVIC_EnableIRQ(TIMER1_IRQn);
NRF_TIMER1->TASKS_START = 1;
}
This code doesn't work, but the separate modules work - the timer is counting and interrupting, if I use toggle task [NRF_GPIOTE->CONFIG[1] = (0x03 | (25<<8) | (0x03 << 16) | (0x01 << 20))] for the GPIO I see PWM output but I cannot control the duty this way.
With the debugger I see that the interrupt never exits because the COMPARE_EVENT[1] is set whenever COMPARE_EVENT[0] is set, which is not expected.
I believe I'm doing something fundamentally wrong, maybe I'm missing something important ...
Any help is appreciated!
Regards,
L. B.