Test application for NUCLEO-F411RE Internal temperature sensor.

Dependencies:   TextLCD_improved mbed

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);
+    }
+}
+