2023-08-11 01:29 AM - edited 2023-08-11 01:43 AM
Hello,
I'm measuring Channel AN11 (Pin PB10) and the internal Temperature of the CPU of my STM32G071RB Nucleoboard via DMA. DMA is necessary, because later on the project will scale a lot. I really hope, someone has a good solution for this.
When changing the voltage on AN11, the internal Temperature Value also changes. Here Some Examples:
Raw Value of AN11 | Converted Temperature of CPU in °C |
70 | -104 |
74 | -106 |
819 | -25 |
1449 | 23 |
1924 | 47 |
2170 | 34 |
3288 | 31 |
4001/ 4095 | 30 |
My Configuration is this:
/*
* ADC.c
*
* Created on: 10.08.2023
* Author: scheichpa
*/
#include <CubeMX_ADC.h>
ADC_HandleTypeDef hadc1;
DMA_HandleTypeDef hdma_adc1;
/**
* @brief ADC1 Initialization Function
* None
* @retval None
*/
void MX_ADC1_Init(void)
{
ADC_ChannelConfTypeDef sConfig = {0};
/** 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_DIV2;
hadc1.Init.Resolution = ADC_RESOLUTION_12B;
hadc1.Init.DataAlign = ADC_DATAALIGN_RIGHT;
hadc1.Init.ScanConvMode = ADC_SCAN_DISABLE;
hadc1.Init.EOCSelection = ADC_EOC_SINGLE_CONV;
hadc1.Init.LowPowerAutoWait = DISABLE;
hadc1.Init.LowPowerAutoPowerOff = DISABLE;
hadc1.Init.ContinuousConvMode = ENABLE; // Enable continuous conversion mode
hadc1.Init.NbrOfConversion = 2; // Number of conversions in continuous mode
hadc1.Init.ExternalTrigConv = ADC_SOFTWARE_START;
hadc1.Init.ExternalTrigConvEdge = ADC_EXTERNALTRIGCONVEDGE_NONE;
hadc1.Init.DMAContinuousRequests = ENABLE;
hadc1.Init.Overrun = ADC_OVR_DATA_PRESERVED;
hadc1.Init.SamplingTimeCommon1 = ADC_SAMPLETIME_1CYCLE_5;
hadc1.Init.SamplingTimeCommon2 = ADC_SAMPLETIME_1CYCLE_5;
hadc1.Init.OversamplingMode = DISABLE;
hadc1.Init.TriggerFrequencyMode = ADC_TRIGGER_FREQ_HIGH;
if (HAL_ADC_Init(&hadc1) != HAL_OK)
{
// Error_Handler();
}
/** Configure Regular Channels
*/
// sConfig.Channel = ADC_CHANNEL_0;
// sConfig.Rank = ADC_REGULAR_RANK_1;
// sConfig.SamplingTime = ADC_SAMPLINGTIME_COMMON_1;
// if (HAL_ADC_ConfigChannel(&hadc1, &sConfig) != HAL_OK)
// {
//// Error_Handler();
// }
sConfig.Channel = ADC_CHANNEL_11;
sConfig.Rank = ADC_REGULAR_RANK_1;
sConfig.SamplingTime = ADC_SAMPLINGTIME_COMMON_1;
if (HAL_ADC_ConfigChannel(&hadc1, &sConfig) != HAL_OK)
{
// Error_Handler();
}
sConfig.Channel = ADC_CHANNEL_TEMPSENSOR;
sConfig.Rank = ADC_REGULAR_RANK_2; // Set the rank for the second conversion
sConfig.SamplingTime = ADC_SAMPLINGTIME_COMMON_1;
if (HAL_ADC_ConfigChannel(&hadc1, &sConfig) != HAL_OK)
{
// Error_Handler();
}
HAL_ADC_MspInit(&hadc1);
}
/**
* @brief ADC MSP Initialization
* This function configures the hardware resources used in this example
* hadc: ADC handle pointer
* @retval None
*/
void HAL_ADC_MspInit(ADC_HandleTypeDef* hadc)
{
GPIO_InitTypeDef GPIO_InitStruct = {0};
RCC_PeriphCLKInitTypeDef PeriphClkInit = {0};
if(hadc->Instance==ADC1)
{
/** Initializes the peripherals clocks
*/
PeriphClkInit.PeriphClockSelection = RCC_PERIPHCLK_ADC;
PeriphClkInit.AdcClockSelection = RCC_ADCCLKSOURCE_SYSCLK;
if (HAL_RCCEx_PeriphCLKConfig(&PeriphClkInit) != HAL_OK)
{
// Error_Handler();
}
/* Peripheral clock enable */
__HAL_RCC_ADC_CLK_ENABLE();
__HAL_RCC_GPIOA_CLK_ENABLE();
/**ADC1 GPIO Configuration
PA0 ------> ADC1_IN0
*/
GPIO_InitStruct.Pin = GPIO_PIN_0;
GPIO_InitStruct.Mode = GPIO_MODE_ANALOG;
GPIO_InitStruct.Pull = GPIO_NOPULL;
HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);
/* ADC1 DMA Init */
/* ADC1 Init */
hdma_adc1.Instance = DMA1_Channel1;
hdma_adc1.Init.Request = DMA_REQUEST_ADC1;
hdma_adc1.Init.Direction = DMA_PERIPH_TO_MEMORY;
hdma_adc1.Init.PeriphInc = DMA_PINC_DISABLE;
hdma_adc1.Init.MemInc = DMA_MINC_ENABLE;
hdma_adc1.Init.PeriphDataAlignment = DMA_PDATAALIGN_WORD;
hdma_adc1.Init.MemDataAlignment = DMA_MDATAALIGN_WORD;
hdma_adc1.Init.Mode = DMA_CIRCULAR;
hdma_adc1.Init.Priority = DMA_PRIORITY_LOW;
if (HAL_DMA_Init(&hdma_adc1) != HAL_OK)
{
// Error_Handler();
}
__HAL_LINKDMA(hadc,DMA_Handle,hdma_adc1);
}
}
/**
* @brief ADC MSP De-Initialization
* This function freeze the hardware resources used in this example
* hadc: ADC handle pointer
* @retval None
*/
void HAL_ADC_MspDeInit(ADC_HandleTypeDef* hadc)
{
if(hadc->Instance==ADC1)
{
/* Peripheral clock disable */
__HAL_RCC_ADC_CLK_DISABLE();
/**ADC1 GPIO Configuration
PA0 ------> ADC1_IN0
*/
HAL_GPIO_DeInit(GPIOA, GPIO_PIN_0);
/* ADC1 DMA DeInit */
HAL_DMA_DeInit(hadc->DMA_Handle);
}
}
My Application Code is:
void FDI::run()
{
char val_string[32] = {};
while (1)
{
uint32_t val = this->adc->getData(1);
this->temperature = __HAL_ADC_CALC_TEMPERATURE(3300, val, ADC_RESOLUTION_12B);
sprintf(val_string, "A0: %d, Temp: %i\n", this->adc->getData(0), temperature);
uart->send((uint8_t*)val_string, sizeof(val_string));
MEF_SPIMessage mes = MEF_SPIMessage();
mes.DevieID = 0;
mes.TX_Data = (uint8_t*)val_string;
mes.TX_DataLength = sizeof(val_string);
this->spi->Send(mes);
HAL_Delay(1000);
}
}
Solved! Go to Solution.
2023-08-11 02:07 AM
The sampling time of the internal temperature sensor is probably too short!
You must wait at least a minimum of 5µs. Can you please verify this point?
Best Regards,
Gwénolé
2023-08-11 01:49 AM
Dear @Patsch36,
Considering the variation of CPU temperature and your external measurements, it seems that you are using the external conversion result to compute the internal CPU temperature.
Can you please check by converting the internal TEMP_SENSOR only while keeping variation on your external sensor?
Best Regards,
Gwénolé
2023-08-11 01:53 AM - edited 2023-08-11 01:55 AM
That's what I do. I convert the second value of the dma and send the first value only as reference (Take a look at the last code lines I provided). When turning my potentiometer from left to right, the value of AN0 changes from about 10 to 4095. I think that's the right value, so the other one must be the temperature value.
I also tried different pins for the external signal but all of them have the same result. I hardly doubt that my CPU has a temperature of -100°C :D
2023-08-11 02:07 AM
The sampling time of the internal temperature sensor is probably too short!
You must wait at least a minimum of 5µs. Can you please verify this point?
Best Regards,
Gwénolé