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

SAADC maintains high current consumption

After performing the first ADC operation (4 channel scan, sample rate controlled from TIMER1), the power consumption stays at almost 4 mA for the nRF52832.

Why?

Initialization code:

	case DRIVER_ADC_IOCTL_START:
	if( ioctl )
	{
		memset( dma_sample_buf, 0, sizeof( dma_sample_buf ));
		memset( read_ring_buf, 0, sizeof( read_ring_buf ));
		ovfl_mask = 0;
		current_dma_buffer = 0;
		read_since_event = 1;
		SAADC_RESULT->PTR = ( uint32_t *)&dma_sample_buf[current_dma_buffer][0];
		
		if( sample_callback != NULL )
		{
			// Call back function is called on each sample
			SAADC_RESULT->MAXCNT = NOF_SCAN_CHANNELS;
		}
		else
		{
			SAADC_RESULT->MAXCNT = NOF_DMA_SAMPLES * NOF_SCAN_CHANNELS;
		}
		
		SAADC_INTENSET = INT_STARTED | INT_END | INT_STOPPED | INT_CALIBRATEDONE;			
		SAADC_SAMPLERATE = 0;// ( 1 << 12 ) | 1333;  		// Sample rate 16 MHz / ( 5 x 266) = 12030 Hz.
		
		// Sample rate setup
		TIMER1_PRESCALER = 0;		// 16 MHx base frequency
		TIMER1_MODE = 0;			// Timer
		TIMER1_BITMODE = 0;			// 16 Bit timer
		TIMER1_CC[0] = 16000000 / SAMPLE_RATE; 
		TIMER1_SHORTS = 1;			// CC0 clears counter
		TIMER1_TASKS_CLEAR = 1;
		
		// Analog input mapping - setup to fit board
#if defined( CONFIG_TARGET_NRF_DK ) || defined( CONFIG_TARGET_NRF_DK_BREAK_OUT)
		SAADC_CH[0].PSELP = AIN1;
		SAADC_CH[1].PSELP = AIN2;
		SAADC_CH[2].PSELP = AIN4;
		SAADC_CH[3].PSELP = AIN5;
		//SAADC_CH[4].PSELP = AIN0;
#else
		SAADC_CH[0].PSELP = AIN0;
		SAADC_CH[1].PSELP = AIN1;
		SAADC_CH[2].PSELP = AIN2;
		SAADC_CH[3].PSELP = AIN3;	// VBAT_MON
#endif
		
		// Analog input configuration - according to errata 74 this must be the last thing before enable
		SAADC_CH[0].CONFIG = RESP_BYPASS | RESN_BYPASS | GAIN1_4 | REFSEL_INTERNAL | TACQ_10US | MODE_SE | BURST_DISABLED;
		SAADC_CH[1].CONFIG = RESP_BYPASS | RESN_BYPASS | GAIN1_4 | REFSEL_INTERNAL | TACQ_10US | MODE_SE | BURST_DISABLED;
		SAADC_CH[2].CONFIG = RESP_BYPASS | RESN_BYPASS | GAIN1_4 | REFSEL_INTERNAL | TACQ_10US | MODE_SE | BURST_DISABLED;
		SAADC_CH[3].CONFIG = RESP_BYPASS | RESN_BYPASS | GAIN1_4 | REFSEL_INTERNAL | TACQ_10US | MODE_SE | BURST_DISABLED;
		//SAADC_CH[4].CONFIG = RESP_BYPASS | RESN_BYPASS | GAIN1_4 | REFSEL_VDD1_4 | TACQ_10US | MODE_SE | BURST_DISABLED;
		
		PPI_CH[0].EEP = &TIMER1_EVENTS_COMPARE[0];
		PPI_CH[0].TEP = &SAADC_TASKS_SAMPLE;
		PPI_CHENSET = 1;
		
		NVIC_SetPriority( SAADC_IRQ_NO, SAADC_IRQ_LEVEL );
	    NVIC_ClearPendingIRQ( SAADC_IRQ_NO );
		NVIC_EnableIRQ( SAADC_IRQ_NO );
		
		SAADC_ENABLE = 1;
			
		isr_cmd = ISR_CMD_CALIBRATE_OFFSET;
		SAADC_TASKS_CALIBRATEOFFSE = 1;			
		adc_client = os_get_pid();
	}
	else
	{
		isr_cmd = ISR_CMD_STOP;
	}
	break;

Code to stop ADC in IRQ handler:

	if( SAADC_EVENTS_STOPPED > 0 )
{
	SAADC_EVENTS_STOPPED = 0;
	
	if( isr_cmd == ISR_CMD_CALIBRATE_OFFSET )
	{
		isr_cmd = ISR_CMD_NONE;
		TIMER1_TASKS_START = 1;
		SAADC_TASKS_START = 1;
	}
	else  // Stop ADC
	{
		NVIC_DisableIRQ( SAADC_IRQ_NO );
		SAADC_ENABLE = 0;
		
		uint8_t n;
		for( n = 0; n < 8; n++ )
		{
			SAADC_CH[n].CONFIG = 0;
			SAADC_CH[n].PSELP = 0;
			SAADC_CH[n].PSELN = 0;
		}

		TIMER1_TASKS_CLEAR = 1;
		TIMER1_TASKS_STOP = 1;
		PPI_CHENCLR = 1;
		
		os_isr_status_bits_set( DEVHDL_ADC, ISR_STATUS_SAMPLING_STOPPED );
	}
}

Appart from the high current consumption the operation is fine.

Parents Reply Children
No Data
Related