2017-11-09 10:40 PM
Hello.
I need read temperature from internal sensor. But when i use code from examples, all time i have result more then 30 degrees of Celsius(~1760 - factory calibration value, ~1740 - ADC value in cold start with ~25 degrees in room).
How i can read the real temperature of MCU?
It's my init code. ADC start conversion by software and read result in interrupt.
#define TEMP30_CAL_ADDR ((uint16_t*) ((uint32_t)0x1FFFF7B8)) // = 1767
#define TEMP110_CAL_ADDR ((uint16_t*) ((uint32_t)0x1FFFF7C2)) // = 1310
void init_periph_adc()
{
// Enable clock on ADC
RCC->APB2ENR |= RCC_APB2ENR_ADC1EN;
RCC->CR2 |= RCC_CR2_HSI14ON;
while ((RCC->CR2 & RCC_CR2_HSI14RDY) == 0)
;
// Start calibration of ADC
ADC1->CR |= ADC_CR_ADDIS;
while ((ADC1->CR & ADC_CR_ADEN) != 0)
;//TODO: make time management
ADC1->CR |= ADC_CR_ADCAL;
// Wait and of calibration
while ((ADC1->CR & ADC_CR_ADCAL) != 0)
; //TODO: make time management
// Select discontinious mode
ADC1->CFGR1 |= ADC_CFGR1_DISCEN;
// Select sampling mode
ADC1->SMPR |= ADC_SMPR_SMP_0 | ADC_SMPR_SMP_1 | ADC_SMPR_SMP_2;
//Enable temp sensor
ADC->CCR |= ADC_CCR_TSEN;
// Enable ADC interrupts
ADC1->IER |= ADC_IER_EOCIE;
// Set interrupt priority
NVIC_SetPriority(ADC1_IRQn, 2);
// Enable IRQ on NVIC
NVIC_EnableIRQ(ADC1_IRQn);
//Enable ADC
ADC1->CR |= ADC_CR_ADEN;
}�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?
#adc-stm32f0 #internal-temperature-sensor
2017-11-10 12:51 AM
Show also the code performing the actual measurement.
JW
2017-11-10 02:00 AM
uint32_t adc_get_result()
{
return adc_temp;
}
void ADC1_IRQHandler(void)
{
if (ADC1->ISR & ADC_ISR_EOC)
{ // Conversion completed, data in the result register
// Flag is cleared automatically after reading DR register
adc_temp = (ADC1->DR);
}
}
// main:
internal_temp = (int32_t)(adc_get_result());
internal_temp -= (int32_t) *TEMP30_CAL_ADDR;
internal_temp *= (int32_t)(110-30);
internal_temp /= (int32_t)(*TEMP110_CAL_ADDR - *TEMP30_CAL_ADDR);
internal_temp += 30;�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?
2017-11-10 05:03 AM
Hi,
I can't see where you select the temperature channel for the ADC, I suppose it is not shown but actually there in your code. I havedone almost the same regarding the temperature reading with the difference that since my Vsup was 3.5V I had to also measure VrefInt in order to get the correct values. If recall correctly, my readings were also off by some °C (don't remember by how much), but in my application it was not critical as it was just an indication.
// Get temperature
int32_t temperature = (int32_t)ADC1->DR;
// Compute temperature with a resolution of 0.01°C
temperature = ((temperature * (int32_t)*VREFINT_CAL_ADDR) / VRef) - (int32_t)*TEMP30_CAL_ADDR;
temperature *= (int32_t)(11000 - 3000);
temperature = temperature / (int32_t)(*TEMP110_CAL_ADDR - *TEMP30_CAL_ADDR);
temperature += 3000;�?�?�?�?�?�?�?�?
Yet I still try to get 0.01°C resolution :)
2017-11-10 05:17 AM
Yes, temperature channel is selected in different place, and calculated temperature value +-correct change if i heat MCU.
My Vref is 3.3V, so i removed Vref coefficient.