#include #include #define FLOAT_TO_S23_8(x) (int32_t)((x) * 1024.0f) static volatile uint16_t adc_results[16]; static volatile int32_t vdd_lf_s23_8 = FLOAT_TO_S23_8(0); static volatile int32_t temp_lf_s23_8 = FLOAT_TO_S23_8(0); void temperature_adc_init(void) { RCC->AHBENR |= RCC_AHBENR_DMAEN; RCC->APB2ENR |= RCC_APB2ENR_ADCEN; /* ADC is mapped to DMA Channel 1 */ SYSCFG->CFGR1 &= ~SYSCFG_CFGR1_DMA_RMP; DMA1_Channel1->CNDTR = 16; DMA1_Channel1->CPAR = (uint32_t)&ADC1->DR; DMA1_Channel1->CMAR = (uint32_t)&adc_results[0]; DMA1_Channel1->CCR = DMA_CCR_PL_1 | DMA_CCR_MSIZE_0 | DMA_CCR_PSIZE_0 | DMA_CCR_MINC | DMA_CCR_CIRC | DMA_CCR_TCIE | DMA_CCR_EN; NVIC_EnableIRQ(DMA1_Channel1_IRQn); /* Calibrate the ADC */ ADC1->CR = ADC_CR_ADCAL; while (ADC1->CR & ADC_CR_ADCAL); /* Dummy read the offset calibration value */ ADC1->DR; ADC1->CR = 0; ADC1->CFGR1 = ADC_CFGR1_DMAEN | ADC_CFGR1_DMACFG | ADC_CFGR1_CONT; ADC1->CFGR2 = ADC_CFGR2_CKMODE_1; ADC1->SMPR = 7u; ADC->CCR |= ADC_CCR_TSEN | ADC_CCR_VREFEN; ADC1->CHSELR = (1<<17) | (1<<16); ADC1->CR = ADC_CR_ADEN | ADC_CR_ADSTART; } static uint32_t get_temp_sensor_cal(void) { const volatile uint16_t *cal; cal = (const volatile uint16_t *)0x1FFFF7B8UL; return (uint32_t)*cal; } int32_t temperature_adc_get_temp(void) { int32_t temp; const int32_t slope = FLOAT_TO_S23_8(5.336f); temp = ((temp_lf_s23_8 / 16) * vdd_lf_s23_8 / FLOAT_TO_S23_8(3.3)) * 16; temp = (get_temp_sensor_cal() << 10) - temp; temp = (temp * 10 / slope) + 300; } static uint32_t get_vrefint_cal(void) { const volatile uint16_t *cal; cal = (const volatile uint16_t *)0x1FFFF7BAUL; return (uint32_t)*cal; } static void process_adc_samples(void) { int i; uint32_t temp_val = 0; uint32_t vref_val = 0; int32_t vdd_s23_8; int32_t temp_s23_8; const uint32_t ref_cal = get_vrefint_cal(); for (i = 0; i < 8; i++) { temp_val += adc_results[2 * i]; vref_val += adc_results[(2 * i) + 1]; } vref_val >>= 3; temp_val >>= 3; vdd_s23_8 = (FLOAT_TO_S23_8(3.3f) * ref_cal) / vref_val; temp_s23_8 = temp_val << 10; /* Moving average filter */ vdd_lf_s23_8 = (vdd_lf_s23_8 * FLOAT_TO_S23_8(0.78125f) + vdd_s23_8 * FLOAT_TO_S23_8(0.21875f)) >> 10; temp_lf_s23_8 = (int32_t)((((int64_t)temp_lf_s23_8 * (int64_t)FLOAT_TO_S23_8(0.78125f)) + temp_s23_8 * FLOAT_TO_S23_8(0.21875f)) / 1024); } void DMA_CH1_IRQHandler(void) { uint32_t isr; isr = DMA1->ISR; DMA1->IFCR = isr; if (isr & DMA_ISR_TCIF1) { process_adc_samples(); } }