2021-04-03 22:48:53 +02:00
|
|
|
#include <ring-light/temp-adc.h>
|
|
|
|
#include <stm32f0xx.h>
|
|
|
|
|
|
|
|
#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;
|
2021-05-09 11:14:14 +02:00
|
|
|
|
2021-05-13 16:12:27 +02:00
|
|
|
return temp;
|
2021-04-03 22:48:53 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
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();
|
|
|
|
}
|
2021-05-09 11:14:14 +02:00
|
|
|
}
|