2023-02-26 07:04 PM
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?
2023-03-24 03:06 AM
Hello @Skfir and welcome to the community,
can you please give us your ADC configuration (if possible the project)?
Mohamed Aymen
2023-03-24 07:45 PM
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