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

SAADC problem

Hi, I'm working on a simple SAADC acquire in scan mode.

I create the two following function:

void adc_init(){
	// Configure SAADC singled-ended channel 0, Internal reference (0.6V) and 1/6 gain.

	NRF_SAADC->CH[0].CONFIG = (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 SAADC singled-ended channel 1, GPIO PIN Internal reference (0.6V) and 1/3 gain.
	NRF_SAADC->CH[1].CONFIG = (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[1].PSELP = SAADC_CH_PSELP_PSELP_AnalogInput6 << SAADC_CH_PSELP_PSELP_Pos;
	    NRF_SAADC->CH[1].PSELN = SAADC_CH_PSELN_PSELN_NC << SAADC_CH_PSELN_PSELN_Pos;

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

	  // Configure result to be put in RAM at the location of "result" variable.
	  NRF_SAADC->RESULT.MAXCNT = 2;
	  NRF_SAADC->RESULT.PTR = (uint32_t)&adc_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));

}

uint32_t adc_read(){

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

	NRF_SAADC->TASKS_SAMPLE = 1;
	while (NRF_SAADC->EVENTS_END == 0);
	NRF_SAADC->EVENTS_END = 0;

	nrf_delay_us(5); //with delay less than 5 us the firmware stop to work

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

	return (adc_result);
}

I was able to init and read the adc without problem.

If I remove the 5 us delay in the read_adc() funciton the firmware stop to work.

In debug mode it works also without the delay, if I add any log line in the read adc funtion it works also without the delay.

Is it correct this behaviour? How I can understand more about this behaviour?

Thanks.

Parents Reply Children
Related