# include "lladc_declarations.h"
static uint32_t adc_avdd_mV = 0U ;
void adc_init ( ADC_TypeDef * adc ) {
adc - > CR & = ~ ( ADC_CR_ADEN ) ; // Disable ADC
adc - > CR & = ~ ( ADC_CR_DEEPPWD ) ; // Reset deep-power-down mode
adc - > CR | = ADC_CR_ADVREGEN ; // Enable ADC regulator
while ( ! ( adc - > ISR & ADC_ISR_LDORDY ) & & ( adc ! = ADC3 ) ) ;
if ( adc ! = ADC3 ) {
adc - > CR & = ~ ( ADC_CR_ADCALDIF ) ; // Choose single-ended calibration
adc - > CR | = ADC_CR_ADCALLIN ; // Lineriality calibration
}
adc - > CR | = ADC_CR_ADCAL ; // Start calibration
while ( ( adc - > CR & ADC_CR_ADCAL ) ! = 0U ) ;
adc - > ISR | = ADC_ISR_ADRDY ;
adc - > CR | = ADC_CR_ADEN ;
while ( ! ( adc - > ISR & ADC_ISR_ADRDY ) ) ;
}
uint16_t adc_get_raw ( const adc_signal_t * signal ) {
signal - > adc - > SQR1 & = ~ ( ADC_SQR1_L ) ;
signal - > adc - > SQR1 = ( ( uint32_t ) signal - > channel < < 6U ) ;
// sample time
if ( signal - > channel < 10U ) {
signal - > adc - > SMPR1 = ( ( uint32_t ) signal - > sample_time < < ( signal - > channel * 3U ) ) ;
} else {
signal - > adc - > SMPR2 = ( ( uint32_t ) signal - > sample_time < < ( ( signal - > channel - 10U ) * 3U ) ) ;
}
// select channel
signal - > adc - > PCSEL_RES0 = ( 0x1UL < < signal - > channel ) ;
// oversampling
signal - > adc - > CFGR2 = ( ( ( 1U < < ( uint32_t ) signal - > oversampling ) - 1U ) < < ADC_CFGR2_OVSR_Pos ) | ( ( uint32_t ) signal - > oversampling < < ADC_CFGR2_OVSS_Pos ) ;
signal - > adc - > CFGR2 | = ( signal - > oversampling ! = OVERSAMPLING_1 ) ? ADC_CFGR2_ROVSE : 0U ;
// start conversion
signal - > adc - > CR | = ADC_CR_ADSTART ;
while ( ! ( signal - > adc - > ISR & ADC_ISR_EOC ) ) ;
uint16_t res = signal - > adc - > DR ;
while ( ! ( signal - > adc - > ISR & ADC_ISR_EOS ) ) ;
signal - > adc - > ISR | = ADC_ISR_EOS ;
return res ;
}
static void adc_calibrate_vdda ( void ) {
// ADC2 used for calibration
adc_init ( ADC2 ) ;
// enable VREFINT channel
ADC3_COMMON - > CCR | = ADC_CCR_VREFEN ;
SYSCFG - > ADC2ALT | = SYSCFG_ADC2ALT_ADC2_ROUT1 ;
// measure VREFINT and derive AVDD
uint16_t raw_vrefint = adc_get_raw ( & ( adc_signal_t ) { . adc = ADC2 , . channel = 17U , . sample_time = SAMPLETIME_810_CYCLES , . oversampling = OVERSAMPLING_256 } ) ;
adc_avdd_mV = ( uint32_t ) * VREFINT_CAL_ADDR * 16U * 3300U / raw_vrefint ;
print ( " AVDD: 0x " ) ; puth ( adc_avdd_mV ) ; print ( " mV \n " ) ;
}
uint16_t adc_get_mV ( const adc_signal_t * signal ) {
uint16_t ret = 0 ;
if ( adc_avdd_mV = = 0U ) {
adc_calibrate_vdda ( ) ;
}
if ( ( signal - > adc = = ADC1 ) | | ( signal - > adc = = ADC2 ) ) {
ret = ( adc_get_raw ( signal ) * adc_avdd_mV ) / 65535U ;
} else if ( signal - > adc = = ADC3 ) {
ret = ( adc_get_raw ( signal ) * adc_avdd_mV ) / 4095U ;
} else { }
return ret ;
}