Test application for NUCLEO-F411RE Internal temperature sensor.
Dependencies: TextLCD_improved mbed
Diff: main.cpp
- Revision:
- 0:4127c73008a9
- Child:
- 4:be36f1d1babe
diff -r 000000000000 -r 4127c73008a9 main.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/main.cpp Sat Dec 12 19:36:52 2015 +0000 @@ -0,0 +1,143 @@ +#include "mbed.h" +#include "stm32f411xe.h" +#include "TextLCD.h" + +/* +Reading the temperature +To use the sensor: +3. Select ADC1_IN16 or ADC1_IN18 input channel. +4. Select a sampling time greater than the minimum sampling time specified in the datasheet. +5. Set the TSVREFE bit in the ADC_CCR register to wake up the temperature sensor from power down mode +6. Start the ADC conversion by setting the SWSTART bit (or by external trigger) +7. Read the resulting VSENSE data in the ADC data register +8. Calculate the temperature using the following formula: Temperature (in °C) = {(VSENSE – V25) / Avg_Slope} + 25 +Where: + – V25 = VSENSE value for 25° C + – Avg_Slope = average slope of the temperature vs. VSENSE curve (given in mV/°C or μV/°C) + + Refer to the datasheet’s electrical characteristics section for the actual values of V25and Avg_Slope. + +The TSVREFE bit must be set to enable the conversion of both internal channels: the ADC1_IN16 or ADC1_IN18 (temperature sensor) and the ADC1_IN17 (VREFINT). + +The sensor has a startup time after waking from power down mode before it can output VSENSE at the correct level. +The ADC also has a startup time after power-on, so to minimize the delay, the ADON and TSVREFE bits should be set at the same time. +The temperature sensor output voltage changes linearly with temperature. +The offset of this linear function depends on each chip due to process variation (up to 45 °C from one chip to another). +The internal temperature sensor is more suit ed for applications that detect temperature variations instead of absolute temperatures. +If accurate temperature reading is required, an external temperature sensor should be used. + +SINGLE Conversion: + +START + CONT = 0 + ADC_CR2.SWSTART = + +COMPLETED + 16bit data in ADC_DR + EOC Flag is set + If JEOCIE bit is set then interrupt generated + ADC Stops + +ADC_SR (Status Register) + - EOC (0x02): Cleared upon reading ADC_DR + +ADC_CR1 (Control Register 1) + - RES [1:0]: Resolution + 00 12bit + 01 10bit + 10 8bit + 11 6bit + +ADC_CR2 (Control Register 2) + - SWSTART (ADON must be set to 1): Start conversion on regular channels + - ADON: A/D Convertor on/off + - CONT: Continuous conversion + +ADC_DR (Data Register) + +ADC_CCR (Common Control Register) + - TSVREFE (): Temperature Sensor and Vrefint enable + VBATE must be disabled to measure temperature + - VBATE (): Vbat enable + +ADC1_SQR1 + - L - počet převod; u regular + 0 = 1 převod + +ADC_SQR3 + - nejnižších 5 bitů je první převod + +ADC_Typedef +ADC_Common_TypeDef + +RCC_TypeDef (APB2ENR) + +ADC_BASE +ADC1_BASE + +ADC +ADC1 + + */ + +void initADCTemp() { + //enable ADC1 clock + SET_BIT(RCC->APB2ENR, RCC_APB2ENR_ADC1EN); + + // Zapnout ADC + SET_BIT(ADC1->CR2, ADC_CR2_ADON); + CLEAR_BIT(ADC1->CR2, ADC_CR2_CONT); + + // Zapnout Temp sensor + CLEAR_BIT(ADC->CCR, ADC_CCR_VBATE); + SET_BIT(ADC->CCR, ADC_CCR_TSVREFE); + + CLEAR_BIT(ADC1->CR1, ADC_CR1_RES); +} + +uint16_t getADCTemp() { + // Set channel + ADC1->SQR1 &= ~ADC_SQR1_L; // Count = 1 + ADC1->SQR3 |= ADC_SQR3_SQ1 & 18; + + // Start conversion + SET_BIT(ADC1->CR2, ADC_CR2_SWSTART); + + // Wait for completion + while (!READ_BIT(ADC1->SR, ADC_SR_EOC)) + ; + + // Return result + return READ_REG(ADC1->DR); +} + + +int main() { + const float V25 = 943.3212f;// when V25=1.41V at ref 3.3V (0,76V) + const float Avg_Slope = 3.1030303f; //when avg_slope=4.3mV/C at ref 3.3V (2.5mV/C) + const uint16_t bufferSize = 4; + + float temp; + uint16_t i; + uint16_t uiCnt = 0; + + TextLCD lcd(PA_8, PA_7, PA_9, PA_1, PB_5, PA_10, TextLCD::LCD16x2); + + initADCTemp(); + + while (true) { + for (i = 0, temp = 0.0f; i < bufferSize; i++) { + temp += ((float)getADCTemp() - V25) / Avg_Slope + 48.2f; + wait_us(1000); + } + temp /= (float)bufferSize; + + lcd.cls(); + lcd.printf("Teplota: % 4u s", uiCnt); + uiCnt += 1; + lcd.locate(0, 1); + lcd.printf("% 3.1f%cC", temp, 0xdf); + wait_us(1000000); + } +} +