cancel
Showing results for 
Search instead for 
Did you mean: 

What is the relationship between adc clock and sample rate? [STM32H7]

bnguy.1
Associate III

I understand the sampling rate for 16-bit can be a maximum of 3.6Msps depending on the chip package, number of ADCs, oversampling, and interleaving or regular..

I'm doing a regular 3 channels 16-bit scan from a single ADC, no oversampling.

The app note says the maximum fadc clock is 50mhz, but CubeMx's clock configuration tool allows values higher than that... so does that mean one must set the sampling cycles to be AT LEAST greater than 41.7ns when connected to FAST channels, and AT LEAST greater than 150ns when connected to SLOW channels, otherwise the readings will be bad?

If so, is it possible to run the ADC such that it continuously scan/convert without the use of a timer or without having to start it after scan completion?

void test_adc(){
  uint8_t buf[64];
  int len = 1;
  volatile float adcf;
  memset(&s_pAlignedAdcBuffer[0], 0xff, sizeof(s_pAlignedAdcBuffer));
  SCB_CleanDCache_by_Addr((uint32_t*)&s_pAlignedAdcBuffer[0], sizeof(s_pAlignedAdcBuffer));
  while(1){
    if (!isAdcWork){
      isAdcWork = true;
      SCB_InvalidateDCache_by_Addr((uint32_t*)&s_pAlignedAdcBuffer[0], sizeof(s_pAlignedAdcBuffer)); 
      //HAL_ADCEx_MultiModeStart_DMA(&hadc1, (uint32_t*)&s_pAlignedAdcBuffer[0], 6);
      dbg_res = HAL_ADC_Start_DMA(&hadc1,(uint32_t*)&s_pAlignedAdcBuffer[0], 6);
    }
    len = snprintf(buf, sizeof(buf), "%u %d\r\n", adcCounter, s_pAlignedAdcBuffer[0]);
    HAL_UART_Transmit(&huart3, buf, len, HAL_MAX_DELAY);
    HAL_Delay(1000);
  }

0693W000001rLjbQAE.png

2 REPLIES 2
Mr_M_from_G
Senior II

Hello,

I don't fully understand the calculations you do with the times ...

First you must set the input clock to a proper value ie equal or lower than the maximum given in the datasheet, and yes CubeMx does not complain if you set more. Watch out which rev you use, there are differences between Y and V.

The conversion period calculates as (sampling clock cyles + 0.5 + resolution/2) * 1/fADC (see data sheet).

You can set continous mode (bit CONT=1) which makes ADC start again immediately one sequence is done

Hope this helps

Martin

bnguy.1
Associate III

The minimum sampling times came this post :

https://community.st.com/s/question/0D50X00009ceWuc/h7-adc-minimum-sampling-time-for-slow-channels

Regarding the continuous mode, the generated code lists the trigger mode as EXTERNAL..

hadc1.Instance = ADC1;
  hadc1.Init.ClockPrescaler = ADC_CLOCK_ASYNC_DIV1;
  hadc1.Init.Resolution = ADC_RESOLUTION_16B;
  hadc1.Init.ScanConvMode = ADC_SCAN_ENABLE;
  hadc1.Init.EOCSelection = ADC_EOC_SEQ_CONV;
  hadc1.Init.LowPowerAutoWait = DISABLE;
  hadc1.Init.ContinuousConvMode = ENABLE;
  hadc1.Init.NbrOfConversion = 3;
  hadc1.Init.DiscontinuousConvMode = DISABLE;
  hadc1.Init.ExternalTrigConv = ADC_EXTERNALTRIG_EXT_IT11;   //******
  hadc1.Init.ExternalTrigConvEdge = ADC_EXTERNALTRIGCONVEDGE_RISING;
  hadc1.Init.ConversionDataManagement = ADC_CONVERSIONDATA_DMA_CIRCULAR;
  hadc1.Init.Overrun = ADC_OVR_DATA_PRESERVED;
  hadc1.Init.LeftBitShift = ADC_LEFTBITSHIFT_NONE;
  hadc1.Init.OversamplingMode = DISABLE;
 
 
static void MX_DMA_Init(void) 
{
 
  /* DMA controller clock enable */
  __HAL_RCC_DMA1_CLK_ENABLE();
 
  /* DMA interrupt init */
  /* DMA1_Stream0_IRQn interrupt configuration */
  HAL_NVIC_SetPriority(DMA1_Stream0_IRQn, 0, 0);
  HAL_NVIC_EnableIRQ(DMA1_Stream0_IRQn);
 
}

Unfortunately, CubeMx, doesn't allow any other option:

0693W000001rRSgQAM.png

Should I manually overwrite the generated code to something like:

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.NbrOfDiscConversion = 0;
hadc1.Init.DataAlign = ADC_DATAALIGN_RIGHT;
hadc1.Init.NbrOfConversion = 2;