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

Turn Off PWM

Hi all

SDK 11.0.0
S132 version 2.0.1
nrf52832

I want to turn on the PWM and turn off the PWM after 1 minute. The device will do BLE advertising When the device wakeup from turn off state.
So, I have written a function, pwm_on(), to turn on the PWM which is working properly. However, I got a problem to turn off the PWM for both of the folowing cases.


void pwm_on(data_t *s)
{
 NRF_PWM1->PSEL.OUT[0]=P0_25;
 NRF_PWM1->PSEL.OUT[1]=P0_26;
 NRF_PWM1->PSEL.OUT[2]=P0_27;
 NRF_PWM1->PSEL.OUT[3]=(PWM_PSEL_OUT_CONNECT_Disconnected << PWM_PSEL_OUT_CONNECT_Pos);
 NRF_PWM1->ENABLE=(PWM_ENABLE_ENABLE_Enabled<<PWM_ENABLE_ENABLE_Pos);
 NRF_PWM1->PRESCALER=PWM_PRESCALER_PRESCALER_DIV_16;
 NRF_PWM1->MODE=PWM_MODE_UPDOWN_Up;
 NRF_PWM1->COUNTERTOP=255;
 NRF_PWM1->DECODER=((PWM_DECODER_LOAD_Individual<<PWM_DECODER_LOAD_Pos)|(PWM_DECODER_MODE_RefreshCount<<PWM_DECODER_MODE_Pos));
 pwm_duty[0]=s->duty0;
 pwm_duty[1]=s->duty1;
 pwm_duty[2]=s->duty2;
 pwm_duty[3]=0xffff;
 NRF_PWM1->SEQ[0].PTR=(uint32_t)pwm_duty;
 NRF_PWM1->SEQ[0].CNT=sizeof(pwm_duty) / sizeof(uint16_t);
 NRF_PWM1->SEQ[0].REFRESH=0;
 NRF_PWM1->SEQ[0].ENDDELAY=0;
 NRF_PWM1->SEQ[1].PTR=0;
 NRF_PWM1->SEQ[1].CNT=0;
 NRF_PWM1->SEQ[1].REFRESH=0;
 NRF_PWM1->SEQ[1].ENDDELAY=0;
 NRF_PWM1->LOOP=0;
 NRF_PWM1->SHORTS=PWM_SHORTS_LOOPSDONE_SEQSTART0_Msk;
 NRF_PWM1->TASKS_SEQSTART[0]=1;
}

void pwm_off(void)
{
 if (NRF_PWM1->TASKS_SEQSTART[0])
  NRF_PWM1->TASKS_STOP = 1;
 NRF_PWM1->PSEL.OUT[0]=(PWM_PSEL_OUT_CONNECT_Disconnected<<PWM_PSEL_OUT_CONNECT_Pos);
 NRF_PWM1->PSEL.OUT[1]=(PWM_PSEL_OUT_CONNECT_Disconnected<<PWM_PSEL_OUT_CONNECT_Pos);
 NRF_PWM1->PSEL.OUT[2]=(PWM_PSEL_OUT_CONNECT_Disconnected<<PWM_PSEL_OUT_CONNECT_Pos);
 NRF_PWM1->PSEL.OUT[3]=(PWM_PSEL_OUT_CONNECT_Disconnected<<PWM_PSEL_OUT_CONNECT_Pos);
 NRF_PWM1->ENABLE = (PWM_ENABLE_ENABLE_Disabled << PWM_ENABLE_ENABLE_Pos);
}

void pwm_off2(void)
{
 if (NRF_PWM1->TASKS_SEQSTART[0])
  NRF_PWM1->TASKS_STOP = 1;
 NRF_PWM1->PSEL.OUT[0]=(PWM_PSEL_OUT_CONNECT_Disconnected<<PWM_PSEL_OUT_CONNECT_Pos);
 NRF_PWM1->PSEL.OUT[1]=(PWM_PSEL_OUT_CONNECT_Disconnected<<PWM_PSEL_OUT_CONNECT_Pos);
 NRF_PWM1->PSEL.OUT[2]=(PWM_PSEL_OUT_CONNECT_Disconnected<<PWM_PSEL_OUT_CONNECT_Pos);
 NRF_PWM1->PSEL.OUT[3]=(PWM_PSEL_OUT_CONNECT_Disconnected<<PWM_PSEL_OUT_CONNECT_Pos);
}

case 1) when I run the function, pwm_off(), to turn off the PWM
Observation: the device can works properly but thwe turn off current keep as 0.3mA

case 2) when I run the function, pwm_off2(), to turn off the PWM
Observation: the current is 30uA but it will cause a watchdog reset after 30s BLE advertising timeout


Question 1) Are there any problems for the function pwm_off() and pwm_off2() to turn off the PWM?
Question 2) For the function pwm_off(), why there is 0.3mA current and how to get rid of it?
Question 3) For the function pwm_off2(), do you have any idea why there is a watchdog reset after 30s BLE advertising timeout?

  • if (NRF_PWM1->TASKS_SEQSTART[0])
      NRF_PWM1->TASKS_STOP = 1;

    This check will never be true, task registers are write-only. 

    Do this instead:

    NRF_PWM1->TASKS_STOP = 1;
    while(!NRF_PWM1->EVENTS_STOPPED){};
    
    NRF_PWM1->PSEL.OUT[0]=(PWM_PSEL_OUT_CONNECT_Disconnected<<PWM_PSEL_OUT_CONNECT_Pos);
    NRF_PWM1->PSEL.OUT[1]=(PWM_PSEL_OUT_CONNECT_Disconnected<<PWM_PSEL_OUT_CONNECT_Pos);
    NRF_PWM1->PSEL.OUT[2]=(PWM_PSEL_OUT_CONNECT_Disconnected<<PWM_PSEL_OUT_CONNECT_Pos);
    NRF_PWM1->PSEL.OUT[3]=(PWM_PSEL_OUT_CONNECT_Disconnected<<PWM_PSEL_OUT_CONNECT_Pos);
    
    NRF_PWM1->ENABLE = (PWM_ENABLE_ENABLE_Disabled << PWM_ENABLE_ENABLE_Pos);

Related