dragonpilot - 基於 openpilot 的開源駕駛輔助系統
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

80 lines
2.5 KiB

#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;
}