Skip to main content
Graduate
March 16, 2024
Solved

STM32F103RC Wrong ADC Readings on Vrefint and TempSensor Channels

  • March 16, 2024
  • 1 reply
  • 5363 views

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:

Chao_0-1710602367613.png

Chao_1-1710602395741.png

Chao_2-1710602434590.png

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

 

 

 

    This topic has been closed for replies.
    Best answer by TDK

    You have likely defined convertedData as a uint32_t array instead of a uint16_t array.

     

    1 reply

    TDKAnswer
    Super User
    March 16, 2024

    You have likely defined convertedData as a uint32_t array instead of a uint16_t array.

     

    ChaoAuthor
    Graduate
    March 16, 2024

    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:

    Chao_0-1710610664326.png

     

    Super User
    March 16, 2024

    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.