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

Using a counter via PPI to count pulses on a pin

I am highly experienced with microcontrollers, all the way back to the Intel 8008, but somewhat new to the nRF52832, with only a few designs under my belt for this microcontroller. I am attempting to use the PPI for my first time, in order to link a port bit change to a counter, ultimately to count pulses. I am testing by outputting a PWM train on an adjacent pin, and the PWM is working fine, all the way from being able to set the duty cycle in application units via BLE. However, as soon as the pulse train starts, that data I'm streaming to the serial port via NRF_LOG_INFO stops, and updates to the PWM no longer happen. Here are the two relevant functions from my code:

#define Timer NRF_TIMER3

void ConfigureCounter (void)
{
NRF_PPI -> CH [6].EEP = (int) (NRF_GPIOTE -> EVENTS_IN + 6); // Connect channel 6 to event on selected pin
NRF_PPI -> CH [6].TEP = (int) (&Timer -> TASKS_COUNT); // Connect task to timer input
Timer -> MODE = 1; // Counter mode
Timer -> BITMODE = 3; // 32 bits wide
NRF_GPIO -> OUTSET = 0x80000000;
NRF_GPIO -> PIN_CNF [31] = 0x00030000;
NRF_GPIOTE -> CONFIG [6] = 0x00011F01; // Event 6 on falling edge on P0.31
NRF_PPI -> CHENSET = 0x40; // Enable channel 6
}

void UpdateCounter (void)
{
Timer -> TASKS_CAPTURE [0] = 1;
LastLevel = Timer -> CC [0];
}

If I set bit 0 of CONFIG[6] to zero, this particular problem goes away, but of course the counter doesn't count. I am suspecting a conflict with resources used by the SoftDevice so have tried changing the timer number, the event number, and the PPI channel number, to no avail. I'm pretty sure I'm just overlooking something stupid, but I haven't been able to find it in several days of hunting. Also, is there an easier way to set up a counter to count pulses? In the end application I will be receiving a pulse train that could vary up to about 1 MHz, and I think this chip is quite capable of handling that - but I can't prove it. Help??

Parents
  • I have added this line to my configuration function:

    NRF_GPIOTE -> INTENCLR = 0xFFFFFFFF;

    and now everything works as it should. That tells me that somebody enabled one or more interrupts on that port. Everything appears to now be working nicely, including the BLE stack. But what have I turned off that is going to bite me later?

  • Hi Steve

    That is interesting. Typically it is only bit 31 that should be set. This is the PORT event, which is usually used for button detection by the button library. 

    You might find that buttons will no longer work if you clear this bit ;)

    Can you try to read the register before you clear it, using the debugger? 

    Then you should see which bits are set originally. 

    As a general comment I would strongly suggest using the defines in nrf52_bitfields.h rather than using magic numbers for the registers. Then your code is more easily readable:

    NRF_GPIO->PIN_CNF[31] = GPIO_PIN_CNF_SENSE_Low << GPIO_PIN_CNF_SENSE_Pos;
    NRF_GPIOTE->CONFIG[6] = GPIOTE_CONFIG_MODE_Event << GPIOTE_CONFIG_MODE_Pos |
    31 << GPIOTE_CONFIG_PSEL_Pos;

    Best regards
    Torbjørn

Reply
  • Hi Steve

    That is interesting. Typically it is only bit 31 that should be set. This is the PORT event, which is usually used for button detection by the button library. 

    You might find that buttons will no longer work if you clear this bit ;)

    Can you try to read the register before you clear it, using the debugger? 

    Then you should see which bits are set originally. 

    As a general comment I would strongly suggest using the defines in nrf52_bitfields.h rather than using magic numbers for the registers. Then your code is more easily readable:

    NRF_GPIO->PIN_CNF[31] = GPIO_PIN_CNF_SENSE_Low << GPIO_PIN_CNF_SENSE_Pos;
    NRF_GPIOTE->CONFIG[6] = GPIOTE_CONFIG_MODE_Event << GPIOTE_CONFIG_MODE_Pos |
    31 << GPIOTE_CONFIG_PSEL_Pos;

    Best regards
    Torbjørn

Children
No Data
Related