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

NRF52 SAADC never writes result to buffer

Hi.

My first attempt to get SAADC to work was:

NRF_SAADC->INTENSET = (SAADC_INTEN_RESULTDONE_Enabled << SAADC_INTEN_RESULTDONE_Pos) | //A result is ready to get transferred to RAM.
(SAADC_INTEN_DONE_Enabled <<SAADC_INTEN_DONE_Pos) | //A conversion task has been completed
(SAADC_INTEN_END_Enabled << SAADC_INTEN_END_Pos) | // The ADC has filled up the Result buffer
(SAADC_INTEN_STARTED_Enabled << SAADC_INTEN_STARTED_Pos) |
(SAADC_INTEN_STOPPED_Enabled << SAADC_INTEN_STOPPED_Pos);

//NRF_SAADC->CH[0].PSELP = SAADC_CH_PSELP_PSELP_AnalogInput0 << SAADC_CH_PSELP_PSELP_Pos;
NRF_SAADC->CH[0].PSELP = SAADC_CH_PSELP_PSELP_VDD << SAADC_CH_PSELP_PSELP_Pos;
// AIN0 as Negative for differential channel
NRF_SAADC->CH[0].PSELN = SAADC_CH_PSELN_PSELN_NC << SAADC_CH_PSELN_PSELN_Pos;
//ADC range = 0.6V/(1/6) = 3.6V
NRF_SAADC->CH[0].CONFIG = (SAADC_CH_CONFIG_GAIN_Gain1_6 << SAADC_CH_CONFIG_GAIN_Pos) |
(SAADC_CH_CONFIG_REFSEL_Internal << SAADC_CH_CONFIG_REFSEL_Pos) |
(SAADC_CH_CONFIG_MODE_SE << SAADC_CH_CONFIG_MODE_Pos) |
(SAADC_CH_CONFIG_RESN_Bypass << SAADC_CH_CONFIG_RESN_Pos) |
(SAADC_CH_CONFIG_RESP_Bypass << SAADC_CH_CONFIG_RESP_Pos) |
(SAADC_CH_CONFIG_TACQ_3us << SAADC_CH_CONFIG_TACQ_Pos);
while (NRF_SAADC->STATUS & 0x01); // Wait while ADC busy
NRF_SAADC->SAMPLERATE = SAADC_SAMPLERATE_MODE_Task << SAADC_SAMPLERATE_MODE_Pos;
NRF_SAADC->RESOLUTION = SAADC_RESOLUTION_VAL_14bit << SAADC_RESOLUTION_VAL_Pos;
NRF_SAADC->RESULT.PTR = adc_result; // Pointer to result variable
NRF_SAADC->RESULT.MAXCNT = 1;

NRF_SAADC->ENABLE = 0x01;
NVIC_EnableIRQ(SAADC_IRQn);

// Calibrate the SAADC (only needs to be done once in a while)
NRF_SAADC->TASKS_CALIBRATEOFFSET = 1;
while (NRF_SAADC->EVENTS_CALIBRATEDONE == 0);
NRF_SAADC->EVENTS_CALIBRATEDONE = 0;
while (NRF_SAADC->STATUS == (SAADC_STATUS_STATUS_Busy <<SAADC_STATUS_STATUS_Pos));

NRF_SAADC->TASKS_START = 1;

In SAADC_IRQHandler after catching EVENTS_STARTED i run samling by NRF_SAADC->TASKS_SAMPLE = 1; and wait for EVENTS_END interupt

i've tryed to use adc_result as uint32_t, as int, as volatile but alway in SAADC_IRQHandler in EVENTS_END get nothing even if i set VDD as an input

Then i've tryed to use the part from example:

nrf_saadc_channel_config_t channel_config =
NRF_DRV_SAADC_DEFAULT_CHANNEL_CONFIG_SE(NRF_SAADC_INPUT_VDD );//NRF_SAADC_INPUT_AIN0);
err_code = nrf_drv_saadc_init(NULL, saadc_callback);
err_code = nrf_drv_saadc_channel_init(0, &channel_config);
err_code = nrf_drv_saadc_buffer_convert(m_buffer_pool[0], 2);
err_code = nrf_drv_saadc_buffer_convert(m_buffer_pool[1], 2);

nrf_drv_saadc_sample();

with the very same result in saadc_callback(nrf_drv_saadc_evt_t const * p_event) - i've always getting zero, or more correctly SAADC not writing to buffer, i've wrote to buffer

fake values like 55 and 99 and got those in handler intead of the real results of ADC conversion.

Looks like EasyDMA is just ignoring my buffer in both cases. should i somewhere in config expliciltly enable easydma module?

I'm using Keil with their implementation of SDK from Packs Installer, maybe it's corrupted or i need do something in options?

  • Hi,

    i've tryed to use adc_result as uint32_t, as int, as volatile

    Is it a plain variable, not an array? then you should write NRF_SAADC->RESULT.PTR = (uint32_t ) &adc_result;

    A sample is a signed 16-bit value, so adc_result should be "short" or "int16_t".

  • Thanx for the advice, Dmitry. This isn't working too. i've already tryed:

    uint32_t adc_result;

    NRF_SAADC->RESULT.PTR = (uint32_t ) &adc_result;

    then volatile uint32_t adc_result;

    then  int adc_result;

    and  volatile int adc_result;

    then uint16_t adc_result;

    and  volatile uint16_t adc_result;

    and  tryed to use SDK with

    static nrf_saadc_value_t     m_buffer_pool[2][2];

    if my code based on just reading datasheet and poor programming knowledge may be incorrect, then with SDK it should work flawlessly, because my intrusion is as minimal as possible, i've just copied lines from example and SDK should do all the magic with buffering/double buffering but it gives me the very same result - nothing written to buffer when (p_event->type == NRF_DRV_SAADC_EVT_DONE).

    The biggest question is - why i can't just get the result from some sort of ADCRESULT register as i did with STM32, LPC,  MKL03Z,  MSP432, EFM32 if i don't need/want/can using DMA.

  • Umm, cannot say anything helpful.. What chip do you have? Your code works on my 52840 DK (without interrupts for simplicity, but it shouldn't matter), adc_result is filled with VDD:

    static uint16_t adc_result= 0xaaaa;
    
    //NRF_SAADC->CH[0].PSELP = SAADC_CH_PSELP_PSELP_AnalogInput0 << SAADC_CH_PSELP_PSELP_Pos;
    NRF_SAADC->CH[0].PSELP = SAADC_CH_PSELP_PSELP_VDD << SAADC_CH_PSELP_PSELP_Pos;
    // AIN0 as Negative for differential channel
    NRF_SAADC->CH[0].PSELN = SAADC_CH_PSELN_PSELN_NC << SAADC_CH_PSELN_PSELN_Pos;
    //ADC range = 0.6V/(1/6) = 3.6V
    NRF_SAADC->CH[0].CONFIG = (SAADC_CH_CONFIG_GAIN_Gain1_6 << SAADC_CH_CONFIG_GAIN_Pos) |
    (SAADC_CH_CONFIG_REFSEL_Internal << SAADC_CH_CONFIG_REFSEL_Pos) |
    (SAADC_CH_CONFIG_MODE_SE << SAADC_CH_CONFIG_MODE_Pos) |
    (SAADC_CH_CONFIG_RESN_Bypass << SAADC_CH_CONFIG_RESN_Pos) |
    (SAADC_CH_CONFIG_RESP_Bypass << SAADC_CH_CONFIG_RESP_Pos) |
    (SAADC_CH_CONFIG_TACQ_3us << SAADC_CH_CONFIG_TACQ_Pos);
    while (NRF_SAADC->STATUS & 0x01); // Wait while ADC busy
    NRF_SAADC->SAMPLERATE = SAADC_SAMPLERATE_MODE_Task << SAADC_SAMPLERATE_MODE_Pos;
    NRF_SAADC->RESOLUTION = SAADC_RESOLUTION_VAL_14bit << SAADC_RESOLUTION_VAL_Pos;
    NRF_SAADC->RESULT.PTR = (uint32_t) &adc_result; // Pointer to result variable
    NRF_SAADC->RESULT.MAXCNT = 1;
    
    NRF_SAADC->ENABLE = 0x01;
    
    NRF_SAADC->EVENTS_STARTED = 0;
    NRF_SAADC->TASKS_START = 1;
    while (! NRF_SAADC->EVENTS_STARTED) {}
    
    NRF_SAADC->EVENTS_END = 0;
    NRF_SAADC->TASKS_SAMPLE = 1;
    while (! NRF_SAADC->EVENTS_END) {}
    

  • Hi

    What SDK version, and if relevant SoftDevice version are you using in this application? Have you already gotten it to work on a DK or similar, and are now struggling to get the project running on your custom board?

    Best regards,

    Simon

Related