Estoy tratando de leer el sensor de temperatura interna. Cada vez, el valor de la conversión ADC es 296, lo que da como resultado una temperatura negativa. ¿Debo agregar algo al código a continuación, habilitar algún periférico o mis cálculos son incorrectos?
#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;
--EDITAR
#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;
Configuración ADC:
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();
}
Obtengo la salida alrededor de 35 grados. ¿Está bien tener una compensación tan grande?
Como señaló PeterJ, el primer defecto es que tienes que configurar el ADC_CCR_TSVREFE
bit y no restablecerlo.
No tengo idea de cómo configura la muestra y el tiempo de espera, pero espero que sea correcto. Tiene que ser de al menos 10 µs para una medición precisa (sección de la hoja de datos sobre el sensor de temperatura).
Su próxima gran falla está en pensar que el voltaje de referencia es 1.21 V. Ese es el valor nominal para el . Este voltaje no es el voltaje de referencia para el ADC. El voltaje de referencia suele ser o un voltaje diferente suministrado externamente en el -alfiler. Pero no puede ser más alto que ni puede ser inferior a -1,2 V.
Con su resultado de conversión de 950, y tomando 3,3 V, terminaría con 27,2 °C, lo que parece un buen comienzo. Si tiene 3 V, sería -0.6 °C, lo que también parece estar bien.
¿Por qué considero que -0,6 °C es un buen valor? Porque el cálculo usando los valores promedio es una mierda.
No sé por qué, pero STM no promociona mucho sus valores calibrados. Cada dispositivo tiene dos valores brutos de ADC tomados a 30 °C y 110 °C a 3,3 V almacenados internamente. Usando esos valores, termina con valores de temperatura más razonables sin realizar la calibración.
Algo a lo largo de estas líneas debería hacer:
// 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;
Estoy acostumbrado a C ++, por lo que tal vez no sea su estilo de codificación, pero eso no debería ser un gran problema.
// Disable Vbat signal from input channel and wake up temp sensor from power down mode
ADC->CCR &= ~(ADC_CCR_TSVREFE);
En realidad está justo enfrente :)
Lectura de la temperatura Para usar el sensor: 3. Seleccione el canal de entrada ADC1_IN18. 4. Seleccione un tiempo de muestreo mayor que el tiempo de muestreo mínimo especificado en la hoja de datos. 5. Establezca el bit TSVREFE en el registro ADC_CCR para despertar el sensor de temperatura del modo de apagado 6. Inicie la conversión ADC configurando el bit SWSTART (o mediante un disparador externo) 7. Lea los datos V SENSE resultantes en el registro de datos ADC 8. Calcule la temperatura usando la siguiente fórmula: Temperatura (en °C) = {(V SENSE – V 25 ) / Avg_Slope} + 25 Donde: – V 25 = valor V SENSE para 25° C – Avg_Slope = pendiente promedio de la temperatura frente a la curva V SENSE (dada en mV/°C o µV/°C) Consulte la sección de características eléctricas de la hoja de datos para conocer los valores reales de V 25 y Avg_Slope.
bitsmack
VIPPER
bitsmack
usuario103380
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
nombre__HAL_ADC_CALC_TEMPERATURE