He estado tratando de medir la temperatura de la MCU (STM32F103RB) como parte de una aplicación FreeRTOS. He intentado inicializar el ADC con las funciones HAL de bajo y alto nivel, pero cada vez que trato de obtener datos, la variable que los almacena tiene un valor de aproximadamente 68 (cuando normalmente debería estar entre 1500 y 1600 a temperatura ambiente). ). ¿Alguna idea?
El código sigue aquí: TempMsr.c - HAL
#include "Peripherals/TempMsr.h"
volatile int32_t sensorData = 0;
volatile int32_t temp = 0;
ADC_HandleTypeDef adc1_config;
ADC_ChannelConfTypeDef adc1_channel;
int32_t getTemp()
{
sensorData = HAL_ADC_GetValue(&adc1_config);
temp = (int32_t)( ( (10 * V25 - 8 * sensorData) / (AVGSLOPE * 10) ) + 25 + BIAS);
//manufacturer's formula for determining the temperature in Celsius, adjusted for unit
//compliance and for minimizing errors due to possible floating-point operations
return sensorData;
}
void ADC_TempMsr_Init()
{
ADC_Config();
HAL_ADC_Init(&adc1_config);
HAL_ADC_ConfigChannel(&adc1_config, &adc1_channel);
}
void ADC_Config()
{
adc1_config.Instance = ADC1;
adc1_config.Init.ScanConvMode = ADC_SCAN_DISABLE;
adc1_config.Init.ContinuousConvMode = ENABLE;
adc1_config.Init.DiscontinuousConvMode = DISABLE;
adc1_config.Init.ExternalTrigConv = ADC_SOFTWARE_START;
adc1_config.Init.DataAlign = ADC_DATAALIGN_RIGHT;
adc1_config.Init.NbrOfConversion = 1;
adc1_channel.Channel = ADC_CHANNEL_TEMPSENSOR;
adc1_channel.Rank = ADC_REGULAR_RANK_1;
adc1_channel.SamplingTime = ADC_SAMPLETIME_239CYCLES_5; //~17 us, manufacturer-suggested time for temp sampling
}
TempMsr.c - Low-level
:
void ADC_TempMsr_Init()
{
ADC_Config();
LL_ADC_Enable(ADC1);
LL_ADC_StartCalibration(ADC1);
}
void ADC_Config()
{
LL_APB2_GRP1_EnableClock(LL_APB2_GRP1_PERIPH_ADC1); //enable the clock for ADC1
LL_ADC_SetCommonPathInternalCh(__LL_ADC_COMMON_INSTANCE(ADC1), LL_ADC_PATH_INTERNAL_TEMPSENSOR);
uint32_t wait_loop_index = 80; //CPU cycles which correspond to ~10 us, suggested stabilization time for temp.sensor stabilization
while(wait_loop_index != 0)
{
wait_loop_index--;
}
/* Set ADC group regular trigger source */
LL_ADC_REG_SetTriggerSource(ADC1, LL_ADC_REG_TRIG_SOFTWARE);
/* Set ADC group regular continuous mode */
LL_ADC_REG_SetContinuousMode(ADC1, LL_ADC_REG_CONV_SINGLE);
/* Set ADC group regular sequencer length and scan direction */
LL_ADC_REG_SetSequencerLength(ADC1, LL_ADC_REG_SEQ_SCAN_DISABLE);
/* Set ADC group regular sequence: channel on the selected sequence rank. */
LL_ADC_REG_SetSequencerRanks(ADC1, LL_ADC_REG_RANK_1, LL_ADC_CHANNEL_TEMPSENSOR);
LL_ADC_SetChannelSamplingTime(ADC1, LL_ADC_CHANNEL_16, LL_ADC_SAMPLINGTIME_239CYCLES_5);
}
El archivo de encabezado correspondiente ( TempMsr.h
):
#ifndef INC_TEMPMSR_H_
#define INC_TEMPMSR_H_
#include "stm32f1xx_hal.h"
//#include "stm32f1xx_ll_adc.h"
//#include "stm32f1xx_ll_bus.h"
#define AVGSLOPE 4.3
//average slope of T-V chart according to datasheet pg 79
//(min is 4 mV/C, max 4.6, default (4.3): typical)
#define V25 1430
//voltage of temperature sensor at 25C according to datasheet pg 79 (in mV)
//(min is 1340, max is 1520, default(1430): typical)
#define BIAS 20
//according to the manual (pg 235), due to mfg processes
//there is an offset in the V(T) plot different
//to every chip (up to +-45oC) that needs to be found.
//(default is 0 so it MUST be calculated before any meaningful measurements
//are made)
int32_t getTemp(); //returns current MCU temp. in Celsius
void ADC_TempMsr_Init(); //initializes the ADC, this needs to be run in prvHardwareSetup()
void ADC_Config();
Finalmente, la tarea de FreeRTOS:
void vTempTask(void *pvParameters)
{
while(1)
{
xSensorData.temp = getTemp(); //continually update the appropriate variable inside the sensor data struct
vTaskDelay(pdMS_TO_TICKS(1000)); //1 second per measurement is enough
}
}
Gracias de antemano.