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

SAADC does not sample

I'm trying to sample analog input but there is no value after sampling.

I tested the input by configuring it as digital input and it worked correctly.

Below is code. Any help would be greatly appreciated.

// Configure ADC and enable it
void adc_init( void )
{
    NRF_SAADC->CH[0].PSELP = 1;
    NRF_SAADC->CH[0].PSELN = 0;
    NRF_SAADC->CH[0].CONFIG = 0x20010;
    NRF_SAADC->RESOLUTION = 0;
    NRF_SAADC->RESULT.PTR = (uint32_t)adcResult;
    NRF_SAADC->RESULT.MAXCNT = 1;
    nrf_saadc_enable();
    nrf_saadc_task_trigger(NRF_SAADC_TASK_START);
}

int main(void)
{
    // Initialize clock
    clocks_start();
    
    nrf_delay_ms(1);

    // Initialize peripherals
    gpio_init();
    adc_init();

    nrf_gpio_pin_write(LED_1,0);

    nrf_delay_ms(100);

    while (true)
    {
        nrf_saadc_task_trigger(NRF_SAADC_TASK_SAMPLE);
        while (nrf_saadc_event_check(NRF_SAADC_EVENT_DONE) == 0);
        nrf_adc_result = ((uint16_t)*adcResult >> 8) & 0x7F;
        nrf_saadc_event_clear(NRF_SAADC_EVENT_DONE);

        if (nrf_adc_result > 25)
        {
            nrf_gpio_pin_write(LED_2,0);
        }
        else
        {
            nrf_gpio_pin_write(LED_2,1);
        }

        if (nrf_adc_result > 50)
        {
            nrf_gpio_pin_write(LED_3,0);
        }
        else
        {
            nrf_gpio_pin_write(LED_3,1);
        }

        if (nrf_adc_result > 100)
        {
            nrf_gpio_pin_write(LED_4,0);
        }
        else
        {
            nrf_gpio_pin_write(LED_4,1);
        }

        nrf_gpio_pin_toggle(LED_1);
        nrf_delay_ms(250);


    }
}

  • Missing defintition of  "adcResult", which is likely used wrong here.

    Note that there is SAADC example code in the SDK.

  • I forgot to include other details...

    I'm using SES for IDE and the nRF52 Dev board. I've already tried many variations of pointer declaration just to see if it would effect the result.

    I've looked at the SDK example as well as other examples and I think my code should work.

    Here is the definition code:

    #include <stdbool.h>
    #include <stdint.h>
    #include <string.h>
    #include "sdk_common.h"
    #include "nrf52.h"
    #include "nrf_delay.h"
    #include "nrf_gpio.h"
    #include "nrf_saadc.h"
    
    #define LED_1           17                      // I/O for LED 1 = P0.17
    #define LED_2           18                      // I/O for LED 2 = P0.18
    #define LED_3           19                      // I/O for LED 3 = P0.19
    #define LED_4           20                      // I/O for LED 4 = P0.20
    
    static uint16_t nrf_adc_result = 0;
    int16_t * adcResult = 0;

  • OK, I have figured this out. My code had several problems. The first problem, which made it very difficult to debug,

    was that the SAMPLE task only executes once and then apparently the SAADC stops. So, when I want to sample

    again, I have to start the SAADC and then I can start the SAMPLE task. The second problem is that I needed to configure

    the SAADC result address as &adcResult. The third problem is that I was assuming the placement of the 8-bit value

    and the sign bit. Both were wrong. There is missing information from the nRF52832 data sheet. Even for 8-bit value,

    the sign bit is bit 15 of the result. Also, when configured for an 8-bit value, the SAADC result is not little endian.

    Here are the changes I made to the code:

    NRF_SAADC->RESULT.PTR = (uint32_t)&adcResult;
    
            nrf_saadc_task_trigger(NRF_SAADC_TASK_START);
            while (nrf_saadc_event_check(NRF_SAADC_EVENT_STARTED) == 0);
            nrf_saadc_task_trigger(NRF_SAADC_TASK_SAMPLE);
            while (nrf_saadc_event_check(NRF_SAADC_EVENT_END) == 0);
            nrf_saadc_event_clear(NRF_SAADC_EVENT_END);
            nrf_adc_result = (uint16_t)adcResult;
            if (nrf_adc_result >> 15 == 1)
            {
                nrf_adc_result = 0;
            }

  • That looks a lot like a NULL pointer to me.

    Hopefully OP set adcResult pointer to a more sensible RAM location in code not shown here.

Related