cancel
Showing results for 
Search instead for 
Did you mean: 

NUCLEO-U575 Vbat ADC measurement

Skfir
Senior

Hello everyone!

I have set the Vbat measurement enabled flag, unsoldered the SB50 bridge and try to measure the voltage on the Vbat pin. The thing is the range seems to be strange. When I tie Vbat to GND, the ADC shows about 5000. Shouldn't the number be something much lower?

2 REPLIES 2
Mohamed Aymen HZAMI
ST Employee

Hello @Skfir​ and welcome to the community,

can you please give us your ADC configuration (if possible the project)?

Mohamed Aymen

Sure! Here it is:

Also an extended calibration for some reason also doesn't work!! If I uncomment all the lines in the "calibration" function, the ADCAL bit never resets.

void ADC_init(void){
	PWR->SVMCR |= (PWR_SVMCR_ASV);	//Removing Analog supply (VDDA) isolation, necessary in order to power ADC1 LDO up
	__NOP();
	__NOP();
	GPIOa_powerUp();
	//**Internal reference buffer init
	RCC->APB3ENR |= (RCC_APB3ENR_VREFEN);	//Power the reference buffer
	__NOP();
	__NOP();
	RCC->SRDAMR |= (RCC_SRDAMR_VREFAMEN);	//Enable reference buffer during sleep mode
	//!!!__!!! Unsolder SB3 bridge on the board
	VREFBUF->CSR = 0;	//Reference out pin is now connected to the reference buffer and the buffer is disabled
	VREFBUF->CSR |= (2 << VREFBUF_CSR_VRS_Pos);	//2V reference selected
	VREFBUF->CSR |= VREFBUF_CSR_ENVR;	//Reference buffer enabled
	while(!(VREFBUF->CSR & VREFBUF_CSR_VRR)){}	//Waiting for the reference voltage to stabilize
	//**Powering up ADC1
	RCC->AHB2ENR1 |= (RCC_AHB2ENR1_ADC12EN);	//Connecting ADC1
	//!!!__!!! MAKE ADC1SMEN: ADC1 clocks enable during Sleep and Stop modes
	ADC12_COMMON->CCR = ((2 << ADC_CCR_PRESC_Pos) + ADC_CCR_VBATEN + ADC_CCR_VSENSEEN);	//ADC1 clock/4 (ADC1 clock must be less than 55MHZ), temperature sensor enabled
	ADC1->CR &= ~(ADC_CR_DEEPPWD);	//Exit ADC1 power down mode
	ADC1->CR |= ADC_CR_ADVREGEN;	//Enable ADC1 LDO
	while(!(ADC1->ISR & ADC_ISR_LDORDY)){}	//Wait for the LDO to get ready
	ADC_calibrate();	//Extended calibration
	//!!!__!!! perhaps voltage booster may increase noise !!!__!!!
	//SYSCFG->CFGR1 |= SYSCFG_CFGR1_BOOSTEN; //Enable voltage boost on I/O analog switches in order to speed up conversions
	ADC1->PCSEL |= (ADC_PCSEL_PCSEL_15 + ADC_PCSEL_PCSEL_18 + ADC_PCSEL_PCSEL_19);	//Preselect Ch15 (PA6, opamp2), 18 (Vbat) and Ch19 (temperature)
	ADC1->SMPR1 |= (7 << ADC_SMPR2_SMP15_Pos);	//^Sampling Ch15, Ch19 (temperature) for the longest time possible (814 clk cycles), Ch18 (voltage) for 391 cycle (over 5us min)
	ADC1->SMPR2 |= ((6 << ADC_SMPR2_SMP18_Pos) + (7 << ADC_SMPR2_SMP19_Pos));
	ADC1->SQR1 |= (((NO_OF_ADC1_CHANNELS - 1) << ADC_SQR1_L_Pos /*total number of conversions - 1*/) + (15 << ADC_SQR1_SQ1_Pos) + (18 << ADC_SQR1_SQ2_Pos) + (19 << ADC_SQR1_SQ3_Pos));	//We convert two channels at a time (Ch15 opamp2) and (Ch19 - temperature)
	ADC1->CFGR2 |= ADC_CFGR2_LFTRIG;	//Preserve converted data from corruption, if we trigger conversions too seldom
	ADC1->CFGR1 |= (ADC_CFGR1_AUTDLY + ADC_CFGR1_CONT + (3 << ADC_CFGR1_DMNGT_Pos));	//New conversion is possible only after all the old conversion have been read, continuous conversion, DMA circular mode selected
	//**Oversampling = 1024, Injection restarts regular channel sampling from the first sample, oversampled data is 8 bits right shifted to get a 16 bit-wide result
	ADC1->CFGR2 |= (ADC_CFGR2_ROVSE + ADC_CFGR2_ROVSM + (1023 << ADC_CFGR2_OVSR_Pos) + ADC_CFGR2_OVSS_3);
	NVIC_SetPriority(ADC1_IRQn, 6);	//^Configure ADC1 interrupt
	//NVIC_EnableIRQ(ADC1_IRQn);
	ADC1->ISR &= ~(ADC_ISR_ADRDY + ADC_ISR_OVR);	//Clear the ADC1 ready flag and OVR in order to permit DMA transfers and see later that the ADC1 gets ready really
	ADC1->CR |= ADC_CR_ADEN;	//Enabling ADC1
	while(!(ADC1->ISR & ADC_ISR_ADRDY)){}	//Waiting for the ADC1 to get ready
	DMA_adc1FuncInit();		//Starting DMA on ADC1
	ADC1->CR |= ADC_CR_ADSTART;
}
 
void ADC_calibrate(void){
	ADC1->CR |= ADC_CR_ADCALLIN;	//Set the linear calibration bit - both offset and linear calibration will be performed
	ADC1->CALFACT &= ~(ADC_CALFACT_CAPTURE_COEF + ADC_CALFACT_LATCH_COEF);	//Making sure no previous calibration values are locked
	/*ADC1->CR |= ADC_CR_ADEN;	//Enabling ADC1
	while(!(ADC1->ISR & ADC_ISR_ADRDY)){}	//Waiting for the ADC1 to get ready
	ADC1->CR |= (0b1001 << ADC_CR_CALINDEX0_Pos); //^Some magic numbers, necessary for initiating the extended calibration
	ADC1->CALFACT2 = 0x00020000;
	ADC1->CALFACT |= ADC_CALFACT_LATCH_COEF;	//^More magic, just following the necessary steps
	ADC1->CALFACT &= ~(ADC_CALFACT_LATCH_COEF);*/
	ADC1->CR |= ADC_CR_ADCAL;	//Starting extended calibration
	while(ADC1->CR & ADC_CR_ADCAL){}	//Waiting for the calibration to finish
	ADC1->CR &= ~(ADC_CR_ADCALLIN);		//No need for linear calibration anymore