STMicroelectronics / STM32CubeH7

STM32Cube MCU Full Package for the STM32H7 series - (HAL + LL Drivers, CMSIS Core, CMSIS Device, MW libraries plus a set of Projects running on all boards provided by ST (Nucleo, Evaluation and Discovery Kits))
https://www.st.com/en/embedded-software/stm32cubeh7.html
Other
518 stars 308 forks source link

Whether ADC Vref channel and temperature acquisition channel are consistent with channel 18 and 19 #250

Closed wdfk-prog closed 1 year ago

wdfk-prog commented 1 year ago

Caution

Describe the set-up

Additional context

issue

ARIOSTM commented 1 year ago

Hi @wdfk-prog,

In order to read Temperature or Vrefint using ADC, you need to enable each channel in the ADC_CCR register.

ADC_CCR_TSEN to enable the VSENSE channel for the temperature sensor. ADC_CCR_VREFEN to enable the Vrefint channel

When you call HAL_ADC_ConfigChannel with ADC_CHANNEL_TEMPSENSOR or ADC_CHANNEL_VREFINT the HAL driver automatically enable the corresponding channel. The temperature sensor and vrefint are not enabled by the HAL driver when Channel 18/19 are configured.

In your test, did you make sure ADC_CCR_TSEN and ADC_CCR_VREFEN were enabled ?

With regards,

wdfk-prog commented 1 year ago

Hi @ARIOSTM

I looked at the register values in KEIL5 and found some issues

After the HAL_ADCEx_Calibration_Start function is enabled, all capabilities are set to one

if (HAL_ADCEx_Calibration_Start(&hadc3, ADC_CALIB_OFFSET_LINEARITY, ADC_SINGLE_ENDED) != HAL_OK) 
{ 
Error_Handler();
}
  • Below is a screenshot of register values for ADC3 in KEIL5 image

I don't know if that's a problem

The result of my attempt to comment out the calibration function is as follows

image

/ ADC3 init function / void MX_ADC3_Init(void) {

/ USER CODE BEGIN ADC3_Init 0 /

/ USER CODE END ADC3_Init 0 /

ADC_ChannelConfTypeDef sConfig = {0};

/ USER CODE BEGIN ADC3_Init 1 /

/ USER CODE END ADC3_Init 1 /

/* Common config / hadc3.Instance = ADC3; hadc3.Init.Resolution = ADC_RESOLUTION_16B; hadc3.Init.ScanConvMode = ADC_SCAN_ENABLE; hadc3.Init.EOCSelection = ADC_EOC_SEQ_CONV; hadc3.Init.LowPowerAutoWait = DISABLE; hadc3.Init.ContinuousConvMode = ENABLE; hadc3.Init.NbrOfConversion = 2; hadc3.Init.DiscontinuousConvMode = DISABLE; hadc3.Init.ExternalTrigConv = ADC_SOFTWARE_START; hadc3.Init.ExternalTrigConvEdge = ADC_EXTERNALTRIGCONVEDGE_NONE; hadc3.Init.ConversionDataManagement = ADC_CONVERSIONDATA_DMA_CIRCULAR; hadc3.Init.Overrun = ADC_OVR_DATA_OVERWRITTEN; hadc3.Init.LeftBitShift = ADC_LEFTBITSHIFT_NONE; hadc3.Init.OversamplingMode = ENABLE; hadc3.Init.Oversampling.Ratio = 1024; hadc3.Init.Oversampling.RightBitShift = ADC_RIGHTBITSHIFT_10; hadc3.Init.Oversampling.TriggeredMode = ADC_TRIGGEREDMODE_SINGLE_TRIGGER; hadc3.Init.Oversampling.OversamplingStopReset = ADC_REGOVERSAMPLING_CONTINUED_MODE; if (HAL_ADC_Init(&hadc3) != HAL_OK) { Error_Handler(); }

/* Configure Regular Channel / sConfig.Channel = ADC_CHANNEL_VREFINT; sConfig.Rank = ADC_REGULAR_RANK_1; sConfig.SamplingTime = ADC_SAMPLETIME_810CYCLES_5; sConfig.SingleDiff = ADC_SINGLE_ENDED; sConfig.OffsetNumber = ADC_OFFSET_NONE; sConfig.Offset = 0; sConfig.OffsetSignedSaturation = DISABLE; if (HAL_ADC_ConfigChannel(&hadc3, &sConfig) != HAL_OK) { Error_Handler(); }

/* Configure Regular Channel / sConfig.Channel = ADC_CHANNEL_TEMPSENSOR; sConfig.Rank = ADC_REGULAR_RANK_2; if (HAL_ADC_ConfigChannel(&hadc3, &sConfig) != HAL_OK) { Error_Handler(); } / USER CODE BEGIN ADC3_Init 2 /

/ USER CODE END ADC3_Init 2 /

}

void HAL_ADC_MspInit(ADC_HandleTypeDef* adcHandle) {

RCC_PeriphCLKInitTypeDef PeriphClkInitStruct = {0}; if(adcHandle->Instance==ADC3) { / USER CODE BEGIN ADC3_MspInit 0 /

/ USER CODE END ADC3_MspInit 0 /

/* Initializes the peripherals clock / PeriphClkInitStruct.PeriphClockSelection = RCC_PERIPHCLK_ADC; PeriphClkInitStruct.AdcClockSelection = RCC_ADCCLKSOURCE_CLKP; if (HAL_RCCEx_PeriphCLKConfig(&PeriphClkInitStruct) != HAL_OK) { Error_Handler(); }

/* ADC3 clock enable */
__HAL_RCC_ADC3_CLK_ENABLE();

/* ADC3 DMA Init */
/* ADC3 Init */
hdma_adc3.Instance = DMA1_Stream3;
hdma_adc3.Init.Request = DMA_REQUEST_ADC3;
hdma_adc3.Init.Direction = DMA_PERIPH_TO_MEMORY;
hdma_adc3.Init.PeriphInc = DMA_PINC_DISABLE;
hdma_adc3.Init.MemInc = DMA_MINC_ENABLE;
hdma_adc3.Init.PeriphDataAlignment = DMA_PDATAALIGN_HALFWORD;
hdma_adc3.Init.MemDataAlignment = DMA_MDATAALIGN_HALFWORD;
hdma_adc3.Init.Mode = DMA_CIRCULAR;
hdma_adc3.Init.Priority = DMA_PRIORITY_LOW;
hdma_adc3.Init.FIFOMode = DMA_FIFOMODE_DISABLE;
if (HAL_DMA_Init(&hdma_adc3) != HAL_OK)
{
  Error_Handler();
}

__HAL_LINKDMA(adcHandle,DMA_Handle,hdma_adc3);

/ USER CODE BEGIN ADC3_MspInit 1 /

/ USER CODE END ADC3_MspInit 1 / } }

static int adc_init(void) { / DMA controller clock enable / __HAL_RCC_DMA1_CLK_ENABLE(); / DMA1_Stream3_IRQn interrupt configuration / HAL_NVIC_SetPriority(DMA1_Stream3_IRQn, 15, 0); HAL_NVIC_EnableIRQ(DMA1_Stream3_IRQn); MX_ADC3_Init();

if (HAL_ADCEx_Calibration_Start(&hadc3, ADC_CALIB_OFFSET_LINEARITY, ADC_SINGLE_ENDED) != HAL_OK) 
{ 
  Error_Handler();
}

adc3_data = (rt_uint16_t *)rt_malloc_align(ADC3_BUFFER_LEN,16);

if (HAL_ADC_Start_DMA(&hadc3, (uint32_t *)adc3_data, ADC3_BUFFER_LEN) != HAL_OK)
{
    Error_Handler();
}

return RT_EOK;

}

typedef enum { VREFINT_CHANNEL = 0x00, TEMP_CHANNEL, }ADC1_CHANNEL;

define ADC3_CHANNEL_NUM 2

define ADC3_BUFFER_SIZE 8

define ADC3_BUFFER_LEN ADC3_BUFFER_SIZE * ADC3_CHANNEL_NUM

rt_uint16_t* adc3_data = RT_NULL;

static int adc_vol_sample(void) { rt_uint16_t vref_mv,temp_mv; rt_uint32_t vref_value,temp_value; rt_uint32_t sum = 0;

for(int i = VREFINT_CHANNEL; i < ADC3_BUFFER_LEN; i += ADC3_CHANNEL_NUM)
{
  sum += adc3_data[i];
}
vref_value = sum / ADC3_BUFFER_SIZE;

sum = 0;
for(int i = TEMP_CHANNEL; i < ADC3_BUFFER_LEN; i += ADC3_CHANNEL_NUM)
{
  sum += adc3_data[i];
}
temp_value = sum / ADC3_BUFFER_SIZE;

rt_kprintf("Vref  is %u.\n", vref_value);
rt_kprintf("Temp is %u.\n" , temp_value);

// Calculating Vref voltage
vref_mv = __HAL_ADC_CALC_VREFANALOG_VOLTAGE(vref_value, ADC_RESOLUTION_16B);
rt_kprintf("Vref voltage is %u mV.\n", vref_mv);

// Calculate Temperature
rt_kprintf("%d are Temperature in Degree C.\n",
__HAL_ADC_CALC_TEMPERATURE(vref_mv, temp_value, ADC_RESOLUTION_16B));
return RT_EOK;

}


## In addition, I manually modified the configuration code to use the 18/19 channel

![image](https://user-images.githubusercontent.com/66928464/208803275-e263eafd-a2c5-4eae-b164-f68bfccf7641.png)

![image](https://user-images.githubusercontent.com/66928464/208803298-2d3c6dd1-9c8f-4638-89ef-b84c36e07222.png)

- Calibration enabled, all flags at position one
![image](https://user-images.githubusercontent.com/66928464/208803329-22e756f4-0a02-4bbd-b5dc-86875b19a648.png)

- The results of uncalibration are as follows

![image](https://user-images.githubusercontent.com/66928464/208803515-b8ee66ab-6c24-4e2d-bdca-25a2045d5d2d.png)

![image](https://user-images.githubusercontent.com/66928464/208803526-4feed21f-12c3-4760-9aff-f29c23fafb77.png)

## Finally, a graph is attached comparing the operating temperature and reference voltage to the register values using the 18/19 channel. You can see that the register values are the same
-  temperature and reference voltage 
![image](https://user-images.githubusercontent.com/66928464/208804605-94694cf9-93ee-4faf-8d08-36ffea3d8b48.png)

- 18/19 channel
![image](https://user-images.githubusercontent.com/66928464/208805855-36018290-607c-4576-82e7-490217e0c3d2.png)
RJMSTM commented 1 year ago

Hello @wdfk-prog ,

Would you please share the project you have used to reproduce the problem. Could you give us more information about the context of execution

BeST Regards,

Rania.

RJMSTM commented 1 year ago

Hello @wdfk-prog

Please allow me to close this thread as no activity. You may reopen it at any time if you have any details to share with us in order to help you to solve the issue. Thank you for your comprehension.

With regards