Obtener temperatura interna o voltaje STM32L0

2

Estoy tratando de obtener el voltaje interno y la temperatura de mi STM32L073RZ con la biblioteca mbed (Intializar y leer un canal interno con ADC). Actualmente no sabía cómo hacerlo y todos los tutoriales hablan sobre 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 (); }

    
pregunta Simon NOWAK

3 respuestas

3

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();
}
    
respondido por el Simon NOWAK
2

He estado trabajando con el sensor de temperatura interno del STM32 basado en el dat Sheet y manual de referencia .

Puede encontrar la guía paso a paso para el sensor en el manual de referencia:

  

Leyendo la temperatura

     
  1. Seleccione el canal de entrada ADC_IN18

  2.   
  3. Seleccione un tiempo de muestreo apropiado especificado en la hoja de datos del dispositivo (TS_temp).

  4.   
  5. Establezca el bit TSEN en el registro ADC_CCR para activar el sensor de temperatura desde el modo de apagado y esperar su tiempo de estabilización (tSTART)

  6.   
  7. Comience la conversión de ADC configurando el bit ADSTART en el registro ADC_CR (o mediante un activador externo)

  8.   
  9. Lea los datos resultantes de VSENSE en el registro ADC_DR

  10.   
  11. Calcule la temperatura con la siguiente fórmula:

  12.   

    

Donde:

    

•TS_CAL2eselvalordecalibracióndelsensordetemperaturaadquiridoa130°C

    

•TS_CAL1eselvalordecalibracióndelsensordetemperaturaadquiridoa30°C

    

•TS_DATAeselvalordesalidadelsensordetemperaturarealconvertidoporADC  Consultelaespecífica   HojadedatosdeldispositivoparaobtenermásinformaciónacercadeTS_CAL1y  PuntosdecalibraciónTS_CAL2.

Lascaracterísticasdelsensordetemperaturasepuedenencontrarenlahojadedatos.ElTS_temp,eltSTARTylasdireccionesdedatosdecalibración.

Yfinalmente,elmanualdereferenciatieneuncódigodeejemploparaconfigurarycalcularelvalordelatemperatura.Desdealli

  

Ejemplodecódigodeconfiguracióndetemperatura

/*(1)SelectHSI16bywriting00inCKMODE(resetvalue)*//*(2)Selectcontinuousmode*//*(3)SelectCHSEL18fortemperaturesensor*//*(4)Selectasamplingmodeof111i.e.239.5ADCclktobegreaterthan2.2us*//*(5)Wake-uptheTemperaturesensor(onlyforTempsensorandVRefInt)*///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)*/
  

Ejemplodecódigodecálculodetemperatura

/*Temperaturesensorcalibrationvalueaddress*/#defineTEMP130_CAL_ADDR((uint16_t*)((uint32_t)0x1FF8007E))#defineTEMP30_CAL_ADDR((uint16_t*)((uint32_t)0x1FF8007A))#defineVDD_CALIB((uint16_t)(300))#defineVDD_APPLI((uint16_t)(330))//<--changethistoaccordingtoyoursupplyvoltageint32_tComputeTemperature(uint32_tmeasure){int32_ttemperature;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);}

Lareferenciadevoltajeinternosepuedeconfigurardeunamanerasimilar.LafuentedevoltajedereferenciaestáhabilitadaporelbitdecontrolVREFENenelregistroADC_CCR.

Lascaracterísticasdelvoltajedereferenciasepuedenencontrarenlahojadedatosaligualquelossensoresdetemperaturayelmanualdereferenciacontienealgunasecuacionesútiles.Porejemplo,cómocalcularelVDDAreal Voltajeusandoelvoltajedereferenciainterno.

TambiénestanotadeaplicaciónparalaserieL1esunbuenrecursotantoparaelsensordetemperaturainternocomoparalareferenciadevoltaje: AN3964 STM32L1x ejemplo de sensor de temperatura .

    
respondido por el Bence Kaulics
0

Algunas cosas a tener en cuenta:

  • El reloj ADC máximo es de 16MHz, por lo que si está ejecutando la CPU a 32MHz, asegúrese de usar PCLK / 2 o un prescaler apropiado
  • El tiempo mínimo de muestra para el sensor de temperatura es 10uS, que requiere que elija el tiempo máximo de muestra en ADC1- > SAMPR (que apenas te lleva a 10us).
  • La referencia de voltaje interno también requiere al menos 10us tiempo de muestra.

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 a la calefacción, pero yo esperaría que fuera más consistente ya que se está leyendo en un sistema de registro de datos alimentado por batería. Estoy comparando las lecturas con dos sensores de temperatura digitales + -1C en la misma placa que se toman 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 40mv 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 (máx.), y 16x sobremuestreo. Calibro el ADC al inicio y uso los valores de calibración de fábrica almacenados (130/30).

    
respondido por el David Albert

Lea otras preguntas en las etiquetas