Estoy tratando de obtener el voltaje interno y la temperatura de mi STM32L073RZ con la biblioteca mbed (Inicialice y lea un canal interno con ADC). Actualmente no sabía cómo hacerlo y todos los tutoriales hablan de otra versión de mi chip.
¿Cómo obtengo la temperatura interna de mi STM32L0?
EDITAR: Este script funciona para mí
/#define TEMP130_CAL_ADDR ((uint16_t*) ((uint32_t) 0x1FF8007E))
/#define TEMP30_CAL_ADDR ((uint16_t*) ((uint32_t) 0x1FF8007A))
/#define VDD_CALIB ((uint16_t) (300))
/#define VDD_APPLI ((uint16_t) (330))
int32_t ComputeTemperature(uint32_t measure)
{
int32_t temperature;
temperature = ((measure * VDD_APPLI / VDD_CALIB) - (int32_t)*TEMP30_CAL_ADDR );
temperature = temperature *(int32_t)(130-30);
temperature = temperature /(int32_t)(*TEMP130_CAL_ADDR -*TEMP30_CAL_ADDR);
temperature = temperature + 30;
return(temperature);
}
void ConfigTemperature(void){
RCC->APB2ENR |= RCC_APB2ENR_ADC1EN;
ADC1->CFGR2 |= ADC_CFGR2_CKMODE;
if ((ADC1->CR & ADC_CR_ADEN) != 0) /* (1) */
{
ADC1->CR &= (uint32_t)(~ADC_CR_ADEN); /* (2) */
}
ADC1->CR |= ADC_CR_ADCAL; /* (3) */
while ((ADC1->ISR & ADC_ISR_EOCAL) == 0) /* (4) */
{
pcMain.printf("Calib");
}
ADC1->ISR |= ADC_ISR_EOCAL;
ADC1->ISR |= ADC_ISR_ADRDY; /* (1) */
ADC1->CR |= ADC_CR_ADEN; /* (2) */
if ((ADC1->CFGR1 & ADC_CFGR1_AUTOFF) == 0)
{
while ((ADC1->ISR & ADC_ISR_ADRDY) == 0) /* (3) */
{
pcMain.printf("Enable");
}
}
ADC1->ISR |= ADC_ISR_ADRDY; /* (1) */
ADC1->CR |= ADC_CR_ADEN; /* (2) */
ADC1->CFGR1 |= ADC_CFGR1_CONT; /* (2) */
ADC1->CHSELR = ADC_CHSELR_CHSEL18; /* (3) */
ADC1->SMPR |= ADC_SMPR_SMP; /* (4) */
ADC->CCR |= ADC_CCR_TSEN;
uint32_t measure = ADC1->DR;
pcMain.printf("Measure %i\n\r", measure);
pcMain.printf("The temperature value is %i\n\r",ComputeTemperature(measure));
}
int main(void)
{
ConfigTemperature();
}
Este script funciona para mí. Es muy importante inicializar y configurar ADC antes de configurar la parte del sensor de temperatura.
/#define TEMP130_CAL_ADDR ((uint16_t*) ((uint32_t) 0x1FF8007E))
/#define TEMP30_CAL_ADDR ((uint16_t*) ((uint32_t) 0x1FF8007A))
/#define VDD_CALIB ((uint16_t) (300))
/#define VDD_APPLI ((uint16_t) (330))
int32_t ComputeTemperature(uint32_t measure)
{
int32_t temperature;
temperature = ((measure * VDD_APPLI / VDD_CALIB) - (int32_t)*TEMP30_CAL_ADDR );
temperature = temperature *(int32_t)(130-30);
temperature = temperature /(int32_t)(*TEMP130_CAL_ADDR -*TEMP30_CAL_ADDR);
temperature = temperature + 30;
return(temperature);
}
void ConfigTemperature(void)
{
RCC->APB2ENR |= RCC_APB2ENR_ADC1EN;
ADC1->CFGR2 |= ADC_CFGR2_CKMODE;
if ((ADC1->CR & ADC_CR_ADEN) != 0)
{
ADC1->CR &= (uint32_t)(~ADC_CR_ADEN);
}
ADC1->CR |= ADC_CR_ADCAL;
while ((ADC1->ISR & ADC_ISR_EOCAL) == 0)
{
pcMain.printf("Calib");
}
ADC1->ISR |= ADC_ISR_EOCAL;
ADC1->ISR |= ADC_ISR_ADRDY;
ADC1->CR |= ADC_CR_ADEN;
if ((ADC1->CFGR1 & ADC_CFGR1_AUTOFF) == 0)
{
while ((ADC1->ISR & ADC_ISR_ADRDY) == 0)
{
pcMain.printf("Enable");
}
}
ADC1->ISR |= ADC_ISR_ADRDY;
ADC1->CR |= ADC_CR_ADEN;
ADC1->CFGR1 |= ADC_CFGR1_CONT;
ADC1->CHSELR = ADC_CHSELR_CHSEL18;
ADC1->SMPR |= ADC_SMPR_SMP;
ADC->CCR |= ADC_CCR_TSEN;
uint32_t measure = ADC1->DR;
pcMain.printf("Measure %i\n\r", measure);
pcMain.printf("The temperature value is %i\n\r",ComputeTemperature(measure));
}
int main(void)
{
ConfigTemperature();
}
He estado trabajando con el sensor de temperatura interno del STM32 según la hoja de datos y el manual de referencia .
Puede encontrar la guía paso a paso para el sensor en el manual de referencia:
Lectura de la temperatura
Seleccione el canal de entrada ADC_IN18
Seleccione un tiempo de muestreo adecuado especificado en la hoja de datos del dispositivo (TS_temp).
Configure el bit TSEN en el registro ADC_CCR para despertar el sensor de temperatura del modo de apagado y esperar su tiempo de estabilización (tSTART)
Inicie la conversión ADC configurando el bit ADSTART en el registro ADC_CR (o por disparador externo)
Lea los datos VSENSE resultantes en el registro ADC_DR
Calcule la temperatura usando la siguiente fórmula:
Dónde:
•TS_CAL2 es el valor de calibración del sensor de temperatura adquirido a 130°C
•TS_CAL1 es el valor de calibración del sensor de temperatura adquirido a 30°C
•TS_DATA es el valor de salida del sensor de temperatura real convertido por ADC Consulte la hoja de datos del dispositivo específico para obtener más información sobre los puntos de calibración TS_CAL1 y TS_CAL2.
Las características del sensor de temperatura se pueden encontrar en la hoja de datos. Las direcciones TS_temp, tSTART y de datos de calibración.
Y finalmente el manual de referencia tiene algún código de ejemplo tanto para configurar como para calcular el valor de la temperatura. Desde allí
Ejemplo de código de configuración de temperatura
/* (1) Select HSI16 by writing 00 in CKMODE (reset value) */
/* (2) Select continuous mode */
/* (3) Select CHSEL18 for temperature sensor */
/* (4) Select a sampling mode of 111 i.e. 239.5 ADC clk to be greater
than 2.2us */
/* (5) Wake-up the Temperature sensor (only for Temp sensor and
VRefInt) */
//ADC1->CFGR2 &= ~ADC_CFGR2_CKMODE; /* (1) */
ADC1->CFGR1 |= ADC_CFGR1_CONT;/* (2) */
ADC1->CHSELR = ADC_CHSELR_CHSEL18;/* (3) */
ADC1->SMPR |= ADC_SMPR_SMP;/* (4) */
ADC->CCR |= ADC_CCR_TSEN;/* (5) */
Ejemplo de código de cálculo de temperatura
/* Temperature sensor calibration value address */
#define TEMP130_CAL_ADDR ((uint16_t*) ((uint32_t) 0x1FF8007E))
#define TEMP30_CAL_ADDR ((uint16_t*) ((uint32_t) 0x1FF8007A))
#define VDD_CALIB ((uint16_t) (300))
#define VDD_APPLI ((uint16_t) (330)) // <-- change this to according to your supply voltage
int32_t ComputeTemperature(uint32_t measure)
{
int32_t temperature;
temperature = ((measure * VDD_APPLI / VDD_CALIB) - (int32_t)*TEMP30_CAL_ADDR );
temperature = temperature *(int32_t)(130-30);
temperature = temperature /(int32_t)(*TEMP130_CAL_ADDR -*TEMP30_CAL_ADDR);
temperature = temperature + 30;
return(temperature);
}
La referencia de tensión interna se puede configurar de forma similar. La fuente de voltaje de referencia está habilitada por el bit de control VREFEN en el registro ADC_CCR.
Las características del voltaje de referencia se pueden encontrar en la hoja de datos al igual que los sensores de temperatura y el manual de referencia contiene algunas ecuaciones útiles. Por ejemplo, cómo calcular el voltaje V DDA real usando el voltaje de referencia interno.
Además, esta nota de aplicación para la serie L1 es un buen recurso tanto para el sensor de temperatura interno como para la referencia de voltaje: ejemplo de sensor de temperatura AN3964 STM32L1x .
measure
es el valor convertido de ADC, así que sí, es el valor de ADC_DR. Estos ejemplos no cubren la parte de medición de ADC, ¿estás seguro de que el proceso de lectura de ADC es correcto? ¿Utiliza algún otro canal o solo el ADC_CHANNEL_TEMPSENSOR?__IO uint32_t DR; /*!< ADC data register, Address offset:0x40 */
(dentro de la ADC_TypeDef
estructura). Así que acceder sería como uint32_t measure = ADC1->DR
. Asegúrese de iniciar la conversión ADC correctamente, espere a que se complete la conversión y solo lea el valor DR después de eso.Algunas cosas a tener en cuenta:
He encontrado que la precisión generalmente está dentro de +3C, pero a veces es significativamente peor (y el error siempre es demasiado alto); es posible que esto se deba al calentamiento del troquel, pero espero que sea más consistente ya que se lee en un sistema de registro de datos alimentado por batería. Estoy comparando lecturas con dos sensores de temperatura digitales de +-1C en la misma placa tomadas al mismo tiempo.
La medición del voltaje de la batería usando la referencia de voltaje interno también tiene algún error (alrededor de 40 mv bajo) que no puedo explicar y esto puede estar relacionado con el error en el sensor de temperatura ya que depende del voltaje.
Estoy usando CKMODE=PCLK/2->ADC_CLK=16MHz SMPR=160.5clks (max), y sobremuestreo 16x. Calibre el ADC al inicio y uso los valores de calibración de fábrica almacenados (130/30).
marcus muller
Simón NOWAK
marcus muller
Bence Kaulics
Simón NOWAK
Simón NOWAK
Simón NOWAK
Bence Kaulics
Simón NOWAK
Bence Kaulics
Bence Kaulics
Simón NOWAK
Simón NOWAK
Bence Kaulics
Simón NOWAK
Bence Kaulics