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

NRF51 PPI: ADC event NRF_DRV_ADC_EVT_DONE not working?

Hi,

I am trying to perform ADC conversions controlled by Timer with minimal manual interaction. My goal is that every 2 seconds, the ADC takes 10 samples in quick succession. For that I configured 2 timers (timer1 2000ms , timer2 10ms).

Then I configured the PPI channels that timer1 triggers timer2, and timer2 triggers the ADC conversion (ADC is set up to collect 10 samples with nrf_drv_adc_buffer_convert). That works fine so far, but when the conversion is done, I need the PPI to stop timer2, which does not work.

Here is the code of my PPI initialization:

static void ppi_init(void)
{
    uint32_t err_code = NRF_SUCCESS;

    err_code = nrf_drv_ppi_init();
    APP_ERROR_CHECK(err_code);

    // Configure 1st available PPI channel to start TIMER2 on TIMER1 COMPARE[0] match
    err_code = nrf_drv_ppi_channel_alloc(&ppi_channel1);
    APP_ERROR_CHECK(err_code);
    err_code = nrf_drv_ppi_channel_assign(ppi_channel1,
                                          nrf_drv_timer_event_address_get(&timer1, NRF_TIMER_EVENT_COMPARE0),
                                          nrf_drv_timer_task_address_get(&timer2,NRF_TIMER_TASK_START));
    APP_ERROR_CHECK(err_code);

    // Configure 2nd available PPI channel to start ADC sampling on TIMER2 COMPARE[0] match
    err_code = nrf_drv_ppi_channel_alloc(&ppi_channel2);
    APP_ERROR_CHECK(err_code);
    err_code = nrf_drv_ppi_channel_assign(ppi_channel2,
                                          nrf_drv_timer_event_address_get(&timer2, NRF_TIMER_EVENT_COMPARE0),
                                          nrf_drv_adc_start_task_get());
    APP_ERROR_CHECK(err_code);
    
    // Configure 3nd available PPI channel to stop TIMER2 on ADC sampling finished
    err_code = nrf_drv_ppi_channel_alloc(&ppi_channel3);
    APP_ERROR_CHECK(err_code);
    err_code = nrf_drv_ppi_channel_assign(ppi_channel3,
                                          nrf_adc_event_address_get(NRF_DRV_ADC_EVT_DONE),
                                          nrf_drv_timer_task_address_get(&timer2, NRF_TIMER_TASK_STOP));
    APP_ERROR_CHECK(err_code);


    // Enable all configured PPI channels
    err_code = nrf_drv_ppi_channel_enable(ppi_channel1);
    APP_ERROR_CHECK(err_code);
    err_code = nrf_drv_ppi_channel_enable(ppi_channel2);
    APP_ERROR_CHECK(err_code);
    err_code = nrf_drv_ppi_channel_enable(ppi_channel3);
    APP_ERROR_CHECK(err_code);
}

I am suspecting that the event "NRF_DRV_ADC_EVT_DONE" is not right. As a workaround I call   nrf_drv_timer_pause(&timer2);   in my ADC event handler, which does what I need, but It would be nice if the PPI could handle that for me. So how should I configure ppi_channel3 to work with the ADC-Done Event?

I am using SDK12.3 with an NRF51822.

Thanks

Parents
  • Hi,

    Your assumption is correct, NRF_DRV_ADC_EVT_DONE is an application event, only available in the driver/application. It cannot be used with PPI, which is a hardware peripheral.

    The ADC in nRF51 does not support EasyDMA like SAADC in the nRF52 series, the buffer feature is a driver-feature. The hardware ADC peripheral will not generate any event when the buffer is filled, it will only generate the END event after each sample conversion.

    You have two possible options:

    1. Stop the timer in the ADC driver callback handler, when you receive the DONE event.
    2. Use a third timer in count-mode, counting the number of END events from the ADC peripheral. Set the compare register to the desired number of samples, and configure PPI to stop the second timer when compare the event from the third timer is generated.

    Best regards,
    Jørgen

  • Hi. This confirms my suspicion. I will then stick to my current solution of stopping the timer in the ADC callback handler.

    Thanks for the answer!

    Cheers.

Reply Children
No Data
Related