2024-03-16 08:31 AM
Hi,
The ADC test has only 2 channels: Vrefint and TempSensor. The following ADC result (convertedData) is read out through DMA:
tick = 1s - convertedData[0] = 113968573 convertedData[1] = 0
tick = 2s - convertedData[0] = 113837503 convertedData[1] = 0
tick = 3s - convertedData[0] = 96339657 convertedData[1] = 0
tick = 4s - convertedData[0] = 113837502 convertedData[1] = 0
tick = 5s - convertedData[0] = 113837503 convertedData[1] = 0
tick = 6s - convertedData[0] = 96405193 convertedData[1] = 0
tick = 7s - convertedData[0] = 113837503 convertedData[1] = 0
tick = 8s - convertedData[0] = 113837502 convertedData[1] = 0
tick = 9s - convertedData[0] = 96405192 convertedData[1] = 0
Where convertedData[0] is the ADC reading of Vrefint which should be 4095, the other is that of TempSensor which should not be 0.
The ADC configuration:
The code:
/* USER CODE BEGIN 2 */
HAL_ADCEx_Calibration_Start(&hadc1);
HAL_ADC_Start_DMA(&hadc1, convertedData, 2);
HAL_Delay(1);
startTick = HAL_GetTick();
/* USER CODE END 2 */
/* Infinite loop */
/* USER CODE BEGIN WHILE */
while (1)
{
/* USER CODE END WHILE */
/* USER CODE BEGIN 3 */
if (dmaTransferStatus == DMA_COMPLETED)
{
Vrefint = convertedData[0] * 3300 / 4095; /* VREF = VDDA = 3300mV */
Vsense = convertedData[1] * 3300 / 4095;
Tmcu = ((1430 - Vsense) / 4.3) + 25; /* Temperature (in °C) = {(V_25 - V_SENSE ) / Avg_Slope} + 25 */
dmaTransferStatus = DMA_NOT_STARTED;
}
if ((HAL_GetTick() - startTick) > 1000)
{
tick++;
startTick = HAL_GetTick();
printf("tick = %ds - convertedData[0] = %d convertedData[1] = %d\n",
tick, convertedData[0], convertedData[1]);
convertedData[0] = 0;
convertedData[1] = 0;
HAL_ADC_Start_DMA(&hadc1, convertedData, 2);
dmaTransferStatus = DMA_NOT_COMPLETED;
}
}
/* USER CODE END 3 */
}
/* USER CODE BEGIN 4 */
void HAL_ADC_ConvCpltCallback(ADC_HandleTypeDef *hadc)
{
dmaTransferStatus = DMA_COMPLETED;
}
PUTCHAR_PROTOTYPE
{
/* Place your implementation of fputc here */
/* e.g. write a character to the USART1 and Loop until the end of transmission */
HAL_UART_Transmit(&huart5, (uint8_t *)&ch, 1, 0xFFFF);
return ch;
}
/* USER CODE END 4 */
static void MX_ADC1_Init(void)
{
ADC_ChannelConfTypeDef sConfig = {0};
/** Common config
*/
hadc1.Instance = ADC1;
hadc1.Init.ScanConvMode = ADC_SCAN_ENABLE;
hadc1.Init.ContinuousConvMode = ENABLE;
hadc1.Init.DiscontinuousConvMode = DISABLE;
hadc1.Init.ExternalTrigConv = ADC_SOFTWARE_START;
hadc1.Init.DataAlign = ADC_DATAALIGN_RIGHT;
hadc1.Init.NbrOfConversion = 2;
if (HAL_ADC_Init(&hadc1) != HAL_OK)
{
Error_Handler();
}
/** Configure Regular Channel
*/
sConfig.Channel = ADC_CHANNEL_VREFINT;
sConfig.Rank = ADC_REGULAR_RANK_1;
sConfig.SamplingTime = ADC_SAMPLETIME_71CYCLES_5;
if (HAL_ADC_ConfigChannel(&hadc1, &sConfig) != HAL_OK)
{
Error_Handler();
}
/** Configure Regular Channel
*/
sConfig.Channel = ADC_CHANNEL_TEMPSENSOR;
sConfig.Rank = ADC_REGULAR_RANK_2;
sConfig.SamplingTime = ADC_SAMPLETIME_239CYCLES_5;
if (HAL_ADC_ConfigChannel(&hadc1, &sConfig) != HAL_OK)
{
Error_Handler();
}
}
static void MX_DMA_Init(void)
{
/* DMA controller clock enable */
__HAL_RCC_DMA1_CLK_ENABLE();
/* DMA interrupt init */
/* DMA1_Channel1_IRQn interrupt configuration */
HAL_NVIC_SetPriority(DMA1_Channel1_IRQn, 0, 0);
HAL_NVIC_EnableIRQ(DMA1_Channel1_IRQn);
}
Any suggestions and comments would be appreciated
Regards
Chao
Solved! Go to Solution.
2024-03-16 08:48 AM
You have likely defined convertedData as a uint32_t array instead of a uint16_t array.
2024-03-16 08:48 AM
You have likely defined convertedData as a uint32_t array instead of a uint16_t array.
2024-03-16 10:37 AM
Thanks. You are right.
After having changed to uint16_t, the readings are still wrong:
tick = 1s - convertedData[0] = 1470 convertedData[1] = 1742 Vrefint = 1184 Tmcu = 31
tick = 2s - convertedData[0] = 1470 convertedData[1] = 1741 Vrefint = 1184 Tmcu = 31
tick = 3s - convertedData[0] = 1470 convertedData[1] = 1740 Vrefint = 1184 Tmcu = 31
tick = 4s - convertedData[0] = 1740 convertedData[1] = 1470 Vrefint = 1184 Tmcu = 31
tick = 5s - convertedData[0] = 1470 convertedData[1] = 1740 Vrefint = 1184 Tmcu = 31
tick = 6s - convertedData[0] = 1471 convertedData[1] = 1741 Vrefint = 1185 Tmcu = 31
tick = 7s - convertedData[0] = 1740 convertedData[1] = 1470 Vrefint = 1185 Tmcu = 31
tick = 8s - convertedData[0] = 1471 convertedData[1] = 1740 Vrefint = 1185 Tmcu = 31
tick = 9s - convertedData[0] = 1470 convertedData[1] = 1740 Vrefint = 1184 Tmcu = 31
tick = 10s - convertedData[0] = 1740 convertedData[1] = 1470 Vrefint = 1184 Tmcu = 31
And the data pattern looks like the readings of the two channels are mixed up.
Not like with G070, F103 does not have configuration options on sequence conversion.
What I expect for the ADC behaviour is:
1. it completes a conversion every second
2. for each conversion, it converts the both channel one after another
3. the DMA transfers the conversion result into convertedData once a second
I am not sure whether or not it does what I expect.
The room temperature is around 21 degree centigrade while the reading is 31.
The temperature sensor characteristics:
2024-03-16 11:18 AM - edited 2024-03-16 11:19 AM
You have continuous conversions on, so the ADC is constantly running. For what you are doing, this seems like the right thing to do. Just set it to convert those 2 channels forever, and put them in a circular buffer. Read them out whichever you want. Only call HAL_ADC_Start_DMA once at the start.
> The room temperature is around 21 degree centigrade while the reading is 31.
This is consistent. The reading you are getting is the junction temperature on the chip, which will be higher than ambient as the chip is using power and heating up. A delta of 10 C is normal. Slowing down your chip so it uses less power and heats up more will reduce the difference. If you want to measure ambient temp, you will need an external sensor that stays at ambient temperature.
2024-03-17 01:43 PM
I will try the circular buffer later.
But if we put the temperature value aside, the converted Vrefint is definitely wrong, it should be very close to 3300mV rather than 1184mV.
I tested on a Nucleo-G070RB board, the Vrefint is quite stable at 3300mV, and the Tmcu is about 23 -25 C while the room temperature is at 20 C. The both tests are at the same place.
There must be something wrong somewhere in the code or the configuration.
2024-03-17 01:48 PM
Your on F103 - ds:
So 1184mV is in spec.
2024-03-17 04:13 PM
> But if we put the temperature value aside, the converted Vrefint is definitely wrong, it should be very close to 3300mV rather than 1184mV.
Why do you think that? What does the data sheet or reference manual say? It should generally be ~1.2 V which is what you're seeing.
2024-03-18 12:05 PM
Thank you for reminding me of that.
I checked it in the datasheet, I think I mixed up the concepts and usages of VREF and Vrefint, I thought they are the same because VREF is internally connected to VDDA, and Vrefint is the internal reference voltage. So what's the difference? How one should use Vrefint ?
2024-03-18 12:44 PM
VREFINT is an internal ~ 1.2 V voltage. VREF+ is the reference voltage on the ADC converter (and other things). They are not related.
The uses for VREFINT are as follows: