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

Setting a GPIO pin as an analog input

Hi. I have the following code, I am attempting to read AIN0 on pin 4 (P0.02).

I am watching the result whilst debugging the application on DK52, and it is a random value fluctuating at about 0x336c even when I GND pin 4, i.e. reading should be 0x0000.

How do I set pin 4 as an analog input?? It must be setup incorrectly at the moment so is always floating.

The adc_measure is being called every second within an LED event handler.

Thanks

const nrf_drv_timer_t TIMER_LED = NRF_DRV_TIMER_INSTANCE(0);
uint32_t seconds = 0;
int16_t result = 0;


void adc_measure(void)
{

    // Start HFCLK from crystal oscillator, this will give the SAADC higher accuracy
    NRF_CLOCK->TASKS_HFCLKSTART = 1;
    while (NRF_CLOCK->EVENTS_HFCLKSTARTED == 0);
    NRF_CLOCK->EVENTS_HFCLKSTARTED = 0;

    // Configure SAADC singled-ended channel, Internal reference (0.6V) and 1/6 gain.
    NRF_SAADC->CH[0].CONFIG = (SAADC_CH_PSELN_PSELN_AnalogInput0 << SAADC_CH_CONFIG_BURST_Pos) |
                              (SAADC_CH_CONFIG_GAIN_Gain1_6    << SAADC_CH_CONFIG_GAIN_Pos) |
                              (SAADC_CH_CONFIG_MODE_SE         << SAADC_CH_CONFIG_MODE_Pos) |
                              (SAADC_CH_CONFIG_REFSEL_Internal << SAADC_CH_CONFIG_REFSEL_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);


    // Configure the SAADC channel with VDD as positive input, no negative input(single ended).
    NRF_SAADC->CH[0].PSELP = SAADC_CH_PSELP_PSELP_VDD << SAADC_CH_PSELP_PSELP_Pos;
    NRF_SAADC->CH[0].PSELN = SAADC_CH_PSELN_PSELN_NC << SAADC_CH_PSELN_PSELN_Pos;

    // Configure the SAADC resolution.
    NRF_SAADC->RESOLUTION = SAADC_RESOLUTION_VAL_14bit << SAADC_RESOLUTION_VAL_Pos;

    // Configure result to be put in RAM at the location of "result" variable.
    NRF_SAADC->RESULT.MAXCNT = 1;
    NRF_SAADC->RESULT.PTR = (uint32_t)&result;

    // No automatic sampling, will trigger with TASKS_SAMPLE.
    NRF_SAADC->SAMPLERATE = SAADC_SAMPLERATE_MODE_Task << SAADC_SAMPLERATE_MODE_Pos;

    // Enable SAADC (would capture analog pins if they were used in CH[0].PSELP)
    NRF_SAADC->ENABLE = SAADC_ENABLE_ENABLE_Enabled << SAADC_ENABLE_ENABLE_Pos;

    // 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));

    // Start the SAADC and wait for the started event.
    NRF_SAADC->TASKS_START = 1;
    while (NRF_SAADC->EVENTS_STARTED == 0);
    NRF_SAADC->EVENTS_STARTED = 0;

    // Do a SAADC sample, will put the result in the configured RAM buffer.
    NRF_SAADC->TASKS_SAMPLE = 1;
    while (NRF_SAADC->EVENTS_END == 0);
    NRF_SAADC->EVENTS_END = 0;

    // Stop the SAADC, since it's not used anymore.
    NRF_SAADC->TASKS_STOP = 1;
    while (NRF_SAADC->EVENTS_STOPPED == 0);
    NRF_SAADC->EVENTS_STOPPED = 0;
}

/**
 * @brief Handler for timer events.
 */
void timer_led_event_handler(nrf_timer_event_t event_type, void* p_context)
{

    nrf_gpio_pin_toggle(17);
    seconds++;
    if(seconds == 60) seconds = 0;

    if(seconds == 0) nrf_gpio_pin_clear(18);
    else nrf_gpio_pin_set(18);

  //  nrf_gpio_cfg_sense_input(
//nrf_gpio_pin_set(4);
      adc_measure();


   // bsp_board_led_invert(1);
 //   static uint32_t i;
 //   uint32_t led_to_invert = ((i++) % LEDS_NUMBER);

 //   switch (event_type)
 //   {
 //       case NRF_TIMER_EVENT_COMPARE0:
 //           bsp_board_led_invert(led_to_invert);
 //           break;

  //      default:
            //Do nothing.
  //          break;
 //   }
}

Related