Test application for NUCLEO-F411RE Internal temperature sensor.
Dependencies: TextLCD_improved mbed
main.cpp@0:4127c73008a9, 2015-12-12 (annotated)
- 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?
User | Revision | Line number | New 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 |