Guten Morgen,
ich hab ein hartnäckiges Problem mit dem STM32-internen 
Temperatursensor.
Dieser liefert kontinuierlich Werte, die ca 10°C zu hoch sind.
Meine Initialisierung:
| 1 | static void MX_ADC_Init(void) {
 | 
| 2 |   __HAL_RCC_ADC1_CLK_ENABLE();
 | 
| 3 | 
 | 
| 4 |   ADC_ChannelConfTypeDef sConfig = { 0 };
 | 
| 5 |   hadc.Instance = ADC1;
 | 
| 6 |   hadc.Init.OversamplingMode = DISABLE;
 | 
| 7 |   hadc.Init.ClockPrescaler = ADC_CLOCK_SYNC_PCLK_DIV2;
 | 
| 8 |   hadc.Init.Resolution = ADC_RESOLUTION_12B;
 | 
| 9 |   hadc.Init.DataAlign = ADC_DATAALIGN_RIGHT;
 | 
| 10 |   hadc.Init.SamplingTime = ADC_SAMPLETIME_160CYCLES_5;
 | 
| 11 |   hadc.Init.ScanConvMode = ADC_SCAN_DIRECTION_FORWARD;
 | 
| 12 |   hadc.Init.ContinuousConvMode = DISABLE;
 | 
| 13 |   hadc.Init.DiscontinuousConvMode = ENABLE;
 | 
| 14 |   hadc.Init.ExternalTrigConvEdge = ADC_EXTERNALTRIGCONVEDGE_NONE;
 | 
| 15 |   hadc.Init.ExternalTrigConv = ADC_SOFTWARE_START;
 | 
| 16 |   hadc.Init.DMAContinuousRequests = DISABLE;
 | 
| 17 |   hadc.Init.EOCSelection = ADC_EOC_SINGLE_CONV;
 | 
| 18 |   hadc.Init.Overrun = ADC_OVR_DATA_OVERWRITTEN;
 | 
| 19 |   hadc.Init.LowPowerAutoWait = DISABLE;
 | 
| 20 |   hadc.Init.LowPowerFrequencyMode = DISABLE;
 | 
| 21 |   hadc.Init.LowPowerAutoPowerOff = DISABLE;
 | 
| 22 |   if (HAL_ADC_Init(&hadc) != HAL_OK) {
 | 
| 23 |     Error_Handler();
 | 
| 24 |   }
 | 
| 25 |   /**Configure for the selected ADC regular channel to be converted.
 | 
| 26 |    */
 | 
| 27 |   sConfig.Channel = ADC_CHANNEL_0;
 | 
| 28 |   sConfig.Rank = ADC_RANK_CHANNEL_NUMBER;
 | 
| 29 | 
 | 
| 30 |   if (HAL_ADC_ConfigChannel(&hadc, &sConfig) != HAL_OK) {
 | 
| 31 |     Error_Handler();
 | 
| 32 |   }
 | 
| 33 |   /**Configure for the selected ADC regular channel to be converted.
 | 
| 34 |    */
 | 
| 35 |   sConfig.Channel = ADC_CHANNEL_1;
 | 
| 36 |   if (HAL_ADC_ConfigChannel(&hadc, &sConfig) != HAL_OK) {
 | 
| 37 |     Error_Handler();
 | 
| 38 |   }
 | 
| 39 |   /**Configure for the selected ADC regular channel to be converted.
 | 
| 40 |   */
 | 
| 41 |   sConfig.Channel = ADC_CHANNEL_VREFINT; //Initialize VREFINT_CAL reference voltage
 | 
| 42 |   sConfig.Rank = ADC_RANK_CHANNEL_NUMBER;
 | 
| 43 |   if (HAL_ADC_ConfigChannel(&hadc, &sConfig) != HAL_OK)
 | 
| 44 |   {
 | 
| 45 |     Error_Handler();
 | 
| 46 |   }
 | 
| 47 | 
 | 
| 48 |   sConfig.Channel = ADC_CHANNEL_TEMPSENSOR; // Initialize the chip temperature sensor
 | 
| 49 |   sConfig.Rank = ADC_RANK_CHANNEL_NUMBER;
 | 
| 50 |   if (HAL_ADC_ConfigChannel(&hadc, &sConfig) != HAL_OK)
 | 
| 51 |   {
 | 
| 52 |     Error_Handler();
 | 
| 53 |   }
 | 
| 54 | 
 | 
| 55 |   HAL_ADCEx_EnableVREFINT();
 | 
| 56 |   HAL_ADCEx_EnableVREFINTTempSensor();
 | 
| 57 | }
 | 
Zur Umrechnung der ADC-Werte hab ich die Code-Snippts aus dem Reference 
Manual und auch aus Example-Projekten aus dem STM32Cube Repository für 
die L0.
| 1 | #define TEMP30_CAL_ADDR   ((uint16_t*) ((uint32_t) 0x1FF8007A)) /* Internal temperature sensor, parameter TS_CAL1: TS ADC raw data acquired at a temperature of 30 DegC (+-5 DegC), VDDA = 3.3 V (+-10 mV). */
 | 
| 2 | #define TEMP130_CAL_ADDR  ((uint16_t*) ((uint32_t) 0x1FF8007E)) /* Internal temperature sensor, parameter TS_CAL2: TS ADC raw data acquired at a temperature of  130 DegC (+-5 DegC), VDDA = 3.3 V (+-10 mV). */
 | 
| 3 | 
 | 
| 4 | #define VDDA_APPLI                     ((uint32_t) 3300)    /* Value of analog voltage supply Vdda (unit: mV) */
 | 
| 5 | #define VDDA_TEMP_CAL                  ((uint32_t) 3000)        /* Vdda value with which temperature sensor has been calibrated in production (+-10 mV). */
 | 
| 6 | 
 | 
| 7 | /* Private macro -------------------------------------------------------------*/
 | 
| 8 | /**
 | 
| 9 |   * @brief  Computation of temperature (unit: degree Celsius) from the internal
 | 
| 10 |   *         temperature sensor measurement by ADC.
 | 
| 11 |   *         Computation is using temperature sensor calibration values done
 | 
| 12 |   *         in production.
 | 
| 13 |   *         Computation formula:
 | 
| 14 |   *         Temperature = (TS_ADC_DATA - TS_CAL1) * (130degC - 30degC)
 | 
| 15 |   *                       / (TS_CAL2 - TS_CAL1) + 30degC
 | 
| 16 |   *         with TS_ADC_DATA = temperature sensor raw data measured by ADC
 | 
| 17 |   *              Avg_Slope = (TS_CAL2 - TS_CAL1) / (130 - 30)
 | 
| 18 |   *              TS_CAL1 = TS_ADC_DATA @30degC (calibrated in factory)
 | 
| 19 |   *              TS_CAL2 = TS_ADC_DATA @130degC (calibrated in factory)
 | 
| 20 |   *         Calculation validity conditioned to settings:
 | 
| 21 |   *          - ADC resolution 12 bits (need to scale conversion value
 | 
| 22 |   *            if using a different resolution).
 | 
| 23 |   *          - Power supply of analog voltage set to literal VDDA_APPLI
 | 
| 24 |   *            (need to scale value if using a different value of analog
 | 
| 25 |   *            voltage supply).
 | 
| 26 |   * @param TS_ADC_DATA: Temperature sensor digital value measured by ADC
 | 
| 27 |   * @retval None
 | 
| 28 |   */
 | 
| 29 | #define COMPUTATION_TEMPERATURE_TEMP30_TEMP130(TS_ADC_DATA)                    \
 | 
| 30 |   (((( ((int32_t)((TS_ADC_DATA * VDDA_APPLI) / VDDA_TEMP_CAL)                  \
 | 
| 31 |         - (int32_t) *TEMP30_CAL_ADDR)                                          \
 | 
| 32 |      ) * (int32_t)(130 - 30)                                                   \
 | 
| 33 |     ) / (int32_t)(*TEMP130_CAL_ADDR - *TEMP30_CAL_ADDR)                        \
 | 
| 34 |    ) + 30                                                                      \
 | 
| 35 |   )
 | 
Eigentlich kann man doch da nicht viel falsch machen - statt 25°C 
erhalte ich Werte, die rund 10°C höher sind.
Ich kann mir beim besten Willen nicht vorstellen, dass ich die 
Temperatur meines µCs um 10°C falsch einschätze.
Mein ADC wird mit 3,3V bepowert - das ist aber in der Umrechnung von als 
VDD_APPLI einberechnet.
ADC Kalibrierung kann es nicht sein, weil ich auch eine 
Batterie-Spannungsmessung eingebaut hab, die auf 5mV genau misst.
Hat jemand ähnliche Probleme mal festgestellt?
Viele Grüße,
Mampf
*edit*: Die beiden Kalibrierwerte:
658 für 30°C bei 3,0Vadc entspricht 598 @ 3,3Vadc
931 für 130°C bei 3,0Vadc entspricht 846 @ 3,3Vadc
ADC hat gelesen: 612 bei 3,3Vadc
Das wären definitiv mehr als 30°C
m = (130-30)/(846-598) = 0,40322
t = 30 - 0,40322 * 598 = -211,12556
Temp = 612 * 0,40322 - 211,12556 = 35,645°C
Hmm, kann da keinen Fehler entdecken.
*edit2*: Die slope (über die Kalibrierwerte) ist außerhalb des 
max-Wertes: 1,81mv/°C
Angegeben ist: 1,48 (min), 1,61 (typ), 1.75 (max).
Das ist ja seltsam ...