Ich versuche, den internen Temperatursensor zu lesen. Der Wert der ADC-Konvertierung beträgt jedes Mal 296, was zu einer negativen Temperatur führt. Sollte ich dem Code unten etwas hinzufügen, einige Peripheriegeräte aktivieren oder meine Berechnungen sind falsch?
#define TEMP_SENSOR_AVG_SLOPE_MV_PER_CELSIUS 2.5f
#define TEMP_SENSOR_VOLTAGE_MV_AT_25 760.0f
#define ADC_REFERENCE_VOLTAGE_MV 1210.0f
#define ADC_MAX_OUTPUT_VALUE 4095.0f
int32_t sensorValue, temperature;
__HAL_ADC_ENABLE(&hadc1);
// Disable Vbat signal from input channel and wake up temp sensor from power down mode
ADC->CCR &= ~(ADC_CCR_TSVREFE);
HAL_ADC_Start(&hadc1);
if(HAL_ADC_PollForConversion(&hadc1, 100) == HAL_OK)
{
sensorValue = (int32_t)HAL_ADC_GetValue(&hadc1);
HAL_ADC_Stop(&hadc1);
sensorValue = sensorValue * ADC_REFERENCE_VOLTAGE_MV / ADC_MAX_OUTPUT_VALUE;
temperature = (int32_t)((sensorValue - TEMP_SENSOR_VOLTAGE_MV_AT_25) / TEMP_SENSOR_AVG_SLOPE_MV_PER_CELSIUS + 25);
}
else
{
temperature = -273;
}
return temperature;
--BEARBEITEN
#define TEMP_SENSOR_AVG_SLOPE_MV_PER_CELSIUS 2.5f
#define TEMP_SENSOR_VOLTAGE_MV_AT_25 760.0f
#define ADC_REFERENCE_VOLTAGE_MV 3300.0f
#define ADC_MAX_OUTPUT_VALUE 4095.0f
#define TEMP110_CAL_VALUE ((uint16_t*)((uint32_t)0x1FFF7A2E))
#define TEMP30_CAL_VALUE ((uint16_t*)((uint32_t)0x1FFF7A2C))
#define TEMP110 110.0f
#define TEMP30 30.0f
int32_t temperature;
float sensorValue;
float adcCalValue30 = (float)(*TEMP30_CAL_VALUE);
float adcCalValue110 = (float)(*TEMP110_CAL_VALUE);
__HAL_ADC_ENABLE(&hadc1);
// Disable Vbat signal from input channel and wake up temp sensor from power down mode
ADC->CCR |= ADC_CCR_TSVREFE;
ADC->CCR &= ~ADC_CCR_VBATE ;
HAL_ADC_Start(&hadc1);
if(HAL_ADC_PollForConversion(&hadc1, 100) == HAL_OK)
{
sensorValue = (float)HAL_ADC_GetValue(&hadc1);
HAL_ADC_Stop(&hadc1);
temperature = (int32_t)((TEMP110 - TEMP30) / ((float)(*TEMP110_CAL_VALUE) - (float)(*TEMP30_CAL_VALUE)) * (sensorValue - (float)(*TEMP30_CAL_VALUE)) + TEMP30);
}
else
{
temperature = -273;
}
return temperature;
ADC-Konfiguration:
ADC_ChannelConfTypeDef sConfig;
/**Configure the global features of the ADC (Clock, Resolution, Data Alignment and number of conversion)
*/
hadc1.Instance = ADC1;
hadc1.Init.ClockPrescaler = ADC_CLOCK_SYNC_PCLK_DIV4;
hadc1.Init.Resolution = ADC_RESOLUTION_12B;
hadc1.Init.ScanConvMode = DISABLE;
hadc1.Init.ContinuousConvMode = DISABLE;
hadc1.Init.DiscontinuousConvMode = DISABLE;
hadc1.Init.ExternalTrigConvEdge = ADC_EXTERNALTRIGCONVEDGE_NONE;
hadc1.Init.ExternalTrigConv = ADC_SOFTWARE_START;
hadc1.Init.DataAlign = ADC_DATAALIGN_RIGHT;
hadc1.Init.NbrOfConversion = 1;
hadc1.Init.DMAContinuousRequests = DISABLE;
hadc1.Init.EOCSelection = ADC_EOC_SINGLE_CONV;
if (HAL_ADC_Init(&hadc1) != HAL_OK)
{
Error_Handler();
}
/**Configure for the selected ADC regular channel its corresponding rank in the sequencer and its sample time.
*/
sConfig.Channel = ADC_CHANNEL_TEMPSENSOR;
sConfig.Rank = 1;
sConfig.SamplingTime = ADC_SAMPLETIME_480CYCLES;
sConfig.Offset = 0;
if (HAL_ADC_ConfigChannel(&hadc1, &sConfig) != HAL_OK)
{
Error_Handler();
}
Ich bekomme die Ausgabe um 35 Grad. Ist es in Ordnung, einen so großen Versatz zu haben?
Wie PeterJ betonte, besteht der erste Fehler darin, dass Sie das ADC_CCR_TSVREFE
Bit setzen und nicht zurücksetzen müssen.
Ich habe keine Ahnung, wie Sie die Abtast- und Haltezeit eingestellt haben, aber ich hoffe, es ist richtig. Sie muss für eine genaue Messung mindestens 10 µs betragen (Datenblattabschnitt Temperatursensor).
Ihr nächster großer Denkfehler ist, dass die Referenzspannung 1,21 V beträgt. Das ist der Nennwert für die . Diese Spannung ist nicht die Referenzspannung für den ADC. Die Referenzspannung ist in der Regel oder eine andere extern zugeführte Spannung an der -Stift. Aber höher darf es nicht sein es kann auch nicht niedriger sein als -1,2 V.
Mit Ihrem Umrechnungsergebnis von 950 und 3,3 V würden Sie am Ende 27,2 ° C erhalten, was wie ein guter Anfang erscheint. Wenn Sie 3 V haben, wären es -0,6 ° C, was auch in Ordnung zu sein scheint.
Warum halte ich -0,6 °C für einen guten Wert? Denn die Berechnung mit den Durchschnittswerten ist Mist.
Ich weiß nicht warum, aber STM bewirbt ihre kalibrierten Werte nicht sehr. Jedes Gerät hat zwei ADC-Rohwerte, die bei 30 °C und 110 °C bei 3,3 V aufgenommen wurden, intern gespeichert. Wenn Sie diese Werte verwenden, erhalten Sie sinnvollere Temperaturwerte, ohne eine Kalibrierung durchzuführen.
Etwas in dieser Richtung sollte tun:
// see datasheet for position of the calibration values, this is for STM32F429
const uint16_t* const ADC_TEMP_3V3_30C = reinterpret_cast<uint16_t*>(0x1FFF7A2C);
const uint16_t* const ADC_TEMP_3V3_110C = reinterpret_cast<uint16_t*>(0x1FFF7A2E);
const float CALIBRATION_REFERENCE_VOLTAGE = 3.3F;
const float REFERENCE_VOLTAGE = 3.0F; // supplied with Vref+ or VDDA
// scale constants to current reference voltage
float adcCalTemp30C = static_cast<float>(*ADC_TEMP_3V3_30C) * (REFERENCE_VOLTAGE/CALIBRATION_REFERENCE_VOLTAGE);
float adcCalTemp110C = static_cast<float>(*ADC_TEMP_3V3_110C) * (REFERENCE_VOLTAGE/CALIBRATION_REFERENCE_VOLTAGE);
uint16_t adcTempValue = SAMPLED VALUE;
float temperature = (static_cast<float>(adcTempValue) - adcCalTemp30C)/(adcCalTemp110C - adcCalTemp30C) * (110.0F - 30.0F) + 30.0F;
Ich bin an C++ gewöhnt, also vielleicht nicht Ihr Programmierstil, aber das sollte kein großes Problem sein.
// Disable Vbat signal from input channel and wake up temp sensor from power down mode
ADC->CCR &= ~(ADC_CCR_TSVREFE);
Es ist eigentlich genau gegenüber :)
Ablesen der Temperatur So verwenden Sie den Sensor: 3. Wählen Sie den Eingangskanal ADC1_IN18. 4. Wählen Sie eine Abtastzeit, die größer ist als die im Datenblatt angegebene Mindestabtastzeit. 5. Setzen Sie das TSVREFE-Bit im ADC_CCR-Register, um den Temperatursensor aus dem Abschaltmodus aufzuwecken. 6. Starten Sie die ADC-Umwandlung durch Setzen des SWSTART-Bits (oder durch externen Trigger). 7. Lesen Sie die resultierenden V SENSE-Daten im ADC-Datenregister 8. Berechnen Sie die Temperatur mit der folgenden Formel: Temperatur (in °C) = {(V SENSE – V 25 ) / Avg_Slope} + 25 Dabei gilt: – V 25 = V SENSE-Wert für 25 °C – Avg_Slope = durchschnittliche Steigung des Temperatur vs. V SENSE-Kurve (angegeben in mV/°C oder µV/°C) Die tatsächlichen Werte von V 25 und Avg_Slope finden Sie im Abschnitt zu den elektrischen Eigenschaften des Datenblatts.
bitsmack
VIPPER
bitsmack
Benutzer103380
0___________
VIPPER
Bence Kaulics
Kir
temperature = (int32_t)((TEMP110 - TEMP30) / ((float)(*TEMP110_CAL_VALUE) - (float)(*TEMP30_CAL_VALUE)) * (sensorValue - (float)(*TEMP30_CAL_VALUE))) + TEMP30;
Loufilouf
stm32xxxx_hal_adc.h
named zu berechnen__HAL_ADC_CALC_TEMPERATURE