Test application for NUCLEO-F411RE Internal temperature sensor.

Dependencies:   TextLCD_improved mbed

Committer:
dzoni
Date:
Sat Dec 12 19:36:52 2015 +0000
Revision:
0:4127c73008a9
Child:
4:be36f1d1babe
Release 1.0

Who changed what in which revision?

UserRevisionLine numberNew contents of line
dzoni 0:4127c73008a9 1 #include "mbed.h"
dzoni 0:4127c73008a9 2 #include "stm32f411xe.h"
dzoni 0:4127c73008a9 3 #include "TextLCD.h"
dzoni 0:4127c73008a9 4
dzoni 0:4127c73008a9 5 /*
dzoni 0:4127c73008a9 6 Reading the temperature
dzoni 0:4127c73008a9 7 To use the sensor:
dzoni 0:4127c73008a9 8 3. Select ADC1_IN16 or ADC1_IN18 input channel.
dzoni 0:4127c73008a9 9 4. Select a sampling time greater than the minimum sampling time specified in the datasheet.
dzoni 0:4127c73008a9 10 5. Set the TSVREFE bit in the ADC_CCR register to wake up the temperature sensor from power down mode
dzoni 0:4127c73008a9 11 6. Start the ADC conversion by setting the SWSTART bit (or by external trigger)
dzoni 0:4127c73008a9 12 7. Read the resulting VSENSE data in the ADC data register
dzoni 0:4127c73008a9 13 8. Calculate the temperature using the following formula: Temperature (in °C) = {(VSENSE – V25) / Avg_Slope} + 25
dzoni 0:4127c73008a9 14 Where:
dzoni 0:4127c73008a9 15 – V25 = VSENSE value for 25° C
dzoni 0:4127c73008a9 16 – Avg_Slope = average slope of the temperature vs. VSENSE curve (given in mV/°C or μV/°C)
dzoni 0:4127c73008a9 17
dzoni 0:4127c73008a9 18 Refer to the datasheet’s electrical characteristics section for the actual values of V25and Avg_Slope.
dzoni 0:4127c73008a9 19
dzoni 0:4127c73008a9 20 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).
dzoni 0:4127c73008a9 21
dzoni 0:4127c73008a9 22 The sensor has a startup time after waking from power down mode before it can output VSENSE at the correct level.
dzoni 0:4127c73008a9 23 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.
dzoni 0:4127c73008a9 24 The temperature sensor output voltage changes linearly with temperature.
dzoni 0:4127c73008a9 25 The offset of this linear function depends on each chip due to process variation (up to 45 °C from one chip to another).
dzoni 0:4127c73008a9 26 The internal temperature sensor is more suit ed for applications that detect temperature variations instead of absolute temperatures.
dzoni 0:4127c73008a9 27 If accurate temperature reading is required, an external temperature sensor should be used.
dzoni 0:4127c73008a9 28
dzoni 0:4127c73008a9 29 SINGLE Conversion:
dzoni 0:4127c73008a9 30
dzoni 0:4127c73008a9 31 START
dzoni 0:4127c73008a9 32 CONT = 0
dzoni 0:4127c73008a9 33 ADC_CR2.SWSTART =
dzoni 0:4127c73008a9 34
dzoni 0:4127c73008a9 35 COMPLETED
dzoni 0:4127c73008a9 36 16bit data in ADC_DR
dzoni 0:4127c73008a9 37 EOC Flag is set
dzoni 0:4127c73008a9 38 If JEOCIE bit is set then interrupt generated
dzoni 0:4127c73008a9 39 ADC Stops
dzoni 0:4127c73008a9 40
dzoni 0:4127c73008a9 41 ADC_SR (Status Register)
dzoni 0:4127c73008a9 42 - EOC (0x02): Cleared upon reading ADC_DR
dzoni 0:4127c73008a9 43
dzoni 0:4127c73008a9 44 ADC_CR1 (Control Register 1)
dzoni 0:4127c73008a9 45 - RES [1:0]: Resolution
dzoni 0:4127c73008a9 46 00 12bit
dzoni 0:4127c73008a9 47 01 10bit
dzoni 0:4127c73008a9 48 10 8bit
dzoni 0:4127c73008a9 49 11 6bit
dzoni 0:4127c73008a9 50
dzoni 0:4127c73008a9 51 ADC_CR2 (Control Register 2)
dzoni 0:4127c73008a9 52 - SWSTART (ADON must be set to 1): Start conversion on regular channels
dzoni 0:4127c73008a9 53 - ADON: A/D Convertor on/off
dzoni 0:4127c73008a9 54 - CONT: Continuous conversion
dzoni 0:4127c73008a9 55
dzoni 0:4127c73008a9 56 ADC_DR (Data Register)
dzoni 0:4127c73008a9 57
dzoni 0:4127c73008a9 58 ADC_CCR (Common Control Register)
dzoni 0:4127c73008a9 59 - TSVREFE (): Temperature Sensor and Vrefint enable
dzoni 0:4127c73008a9 60 VBATE must be disabled to measure temperature
dzoni 0:4127c73008a9 61 - VBATE (): Vbat enable
dzoni 0:4127c73008a9 62
dzoni 0:4127c73008a9 63 ADC1_SQR1
dzoni 0:4127c73008a9 64 - L - počet převod; u regular
dzoni 0:4127c73008a9 65 0 = 1 převod
dzoni 0:4127c73008a9 66
dzoni 0:4127c73008a9 67 ADC_SQR3
dzoni 0:4127c73008a9 68 - nejnižších 5 bitů je první převod
dzoni 0:4127c73008a9 69
dzoni 0:4127c73008a9 70 ADC_Typedef
dzoni 0:4127c73008a9 71 ADC_Common_TypeDef
dzoni 0:4127c73008a9 72
dzoni 0:4127c73008a9 73 RCC_TypeDef (APB2ENR)
dzoni 0:4127c73008a9 74
dzoni 0:4127c73008a9 75 ADC_BASE
dzoni 0:4127c73008a9 76 ADC1_BASE
dzoni 0:4127c73008a9 77
dzoni 0:4127c73008a9 78 ADC
dzoni 0:4127c73008a9 79 ADC1
dzoni 0:4127c73008a9 80
dzoni 0:4127c73008a9 81 */
dzoni 0:4127c73008a9 82
dzoni 0:4127c73008a9 83 void initADCTemp() {
dzoni 0:4127c73008a9 84 //enable ADC1 clock
dzoni 0:4127c73008a9 85 SET_BIT(RCC->APB2ENR, RCC_APB2ENR_ADC1EN);
dzoni 0:4127c73008a9 86
dzoni 0:4127c73008a9 87 // Zapnout ADC
dzoni 0:4127c73008a9 88 SET_BIT(ADC1->CR2, ADC_CR2_ADON);
dzoni 0:4127c73008a9 89 CLEAR_BIT(ADC1->CR2, ADC_CR2_CONT);
dzoni 0:4127c73008a9 90
dzoni 0:4127c73008a9 91 // Zapnout Temp sensor
dzoni 0:4127c73008a9 92 CLEAR_BIT(ADC->CCR, ADC_CCR_VBATE);
dzoni 0:4127c73008a9 93 SET_BIT(ADC->CCR, ADC_CCR_TSVREFE);
dzoni 0:4127c73008a9 94
dzoni 0:4127c73008a9 95 CLEAR_BIT(ADC1->CR1, ADC_CR1_RES);
dzoni 0:4127c73008a9 96 }
dzoni 0:4127c73008a9 97
dzoni 0:4127c73008a9 98 uint16_t getADCTemp() {
dzoni 0:4127c73008a9 99 // Set channel
dzoni 0:4127c73008a9 100 ADC1->SQR1 &= ~ADC_SQR1_L; // Count = 1
dzoni 0:4127c73008a9 101 ADC1->SQR3 |= ADC_SQR3_SQ1 & 18;
dzoni 0:4127c73008a9 102
dzoni 0:4127c73008a9 103 // Start conversion
dzoni 0:4127c73008a9 104 SET_BIT(ADC1->CR2, ADC_CR2_SWSTART);
dzoni 0:4127c73008a9 105
dzoni 0:4127c73008a9 106 // Wait for completion
dzoni 0:4127c73008a9 107 while (!READ_BIT(ADC1->SR, ADC_SR_EOC))
dzoni 0:4127c73008a9 108 ;
dzoni 0:4127c73008a9 109
dzoni 0:4127c73008a9 110 // Return result
dzoni 0:4127c73008a9 111 return READ_REG(ADC1->DR);
dzoni 0:4127c73008a9 112 }
dzoni 0:4127c73008a9 113
dzoni 0:4127c73008a9 114
dzoni 0:4127c73008a9 115 int main() {
dzoni 0:4127c73008a9 116 const float V25 = 943.3212f;// when V25=1.41V at ref 3.3V (0,76V)
dzoni 0:4127c73008a9 117 const float Avg_Slope = 3.1030303f; //when avg_slope=4.3mV/C at ref 3.3V (2.5mV/C)
dzoni 0:4127c73008a9 118 const uint16_t bufferSize = 4;
dzoni 0:4127c73008a9 119
dzoni 0:4127c73008a9 120 float temp;
dzoni 0:4127c73008a9 121 uint16_t i;
dzoni 0:4127c73008a9 122 uint16_t uiCnt = 0;
dzoni 0:4127c73008a9 123
dzoni 0:4127c73008a9 124 TextLCD lcd(PA_8, PA_7, PA_9, PA_1, PB_5, PA_10, TextLCD::LCD16x2);
dzoni 0:4127c73008a9 125
dzoni 0:4127c73008a9 126 initADCTemp();
dzoni 0:4127c73008a9 127
dzoni 0:4127c73008a9 128 while (true) {
dzoni 0:4127c73008a9 129 for (i = 0, temp = 0.0f; i < bufferSize; i++) {
dzoni 0:4127c73008a9 130 temp += ((float)getADCTemp() - V25) / Avg_Slope + 48.2f;
dzoni 0:4127c73008a9 131 wait_us(1000);
dzoni 0:4127c73008a9 132 }
dzoni 0:4127c73008a9 133 temp /= (float)bufferSize;
dzoni 0:4127c73008a9 134
dzoni 0:4127c73008a9 135 lcd.cls();
dzoni 0:4127c73008a9 136 lcd.printf("Teplota: % 4u s", uiCnt);
dzoni 0:4127c73008a9 137 uiCnt += 1;
dzoni 0:4127c73008a9 138 lcd.locate(0, 1);
dzoni 0:4127c73008a9 139 lcd.printf("% 3.1f%cC", temp, 0xdf);
dzoni 0:4127c73008a9 140 wait_us(1000000);
dzoni 0:4127c73008a9 141 }
dzoni 0:4127c73008a9 142 }
dzoni 0:4127c73008a9 143