cancel
Showing results for 
Search instead for 
Did you mean: 

Sampling rate calculation of STM32F7 ADC with GPIO Toggling

AE104
Senior

Hi,

I use internal ADC of the STM32F767 microprocessor. I set the ADC parameters like this,

static void MX_ADC2_Init(void)
{
 
  /* USER CODE BEGIN ADC2_Init 0 */
 
  /* USER CODE END ADC2_Init 0 */
 
  ADC_ChannelConfTypeDef sConfig = {0};
 
  /* USER CODE BEGIN ADC2_Init 1 */
 
  /* USER CODE END ADC2_Init 1 */
  /** Configure the global features of the ADC (Clock, Resolution, Data Alignment and number of conversion) 
  */
  hadc2.Instance = ADC2;
  hadc2.Init.ClockPrescaler = ADC_CLOCK_SYNC_PCLK_DIV4;
  hadc2.Init.Resolution = ADC_RESOLUTION_12B;
  hadc2.Init.ScanConvMode = ADC_SCAN_DISABLE;
  hadc2.Init.ContinuousConvMode = ENABLE;
  hadc2.Init.DiscontinuousConvMode = DISABLE;
  hadc2.Init.ExternalTrigConvEdge = ADC_EXTERNALTRIGCONVEDGE_NONE;
  hadc2.Init.ExternalTrigConv = ADC_SOFTWARE_START;
  hadc2.Init.DataAlign = ADC_DATAALIGN_RIGHT;
  hadc2.Init.NbrOfConversion = 1;
  hadc2.Init.DMAContinuousRequests = DISABLE;
  hadc2.Init.EOCSelection = ADC_EOC_SEQ_CONV;
  if (HAL_ADC_Init(&hadc2) != HAL_OK)
  {
    Error_Handler();
  }
  /** Configure for the selected ADC regular channel its corresponding rank in the sequencer and its sample time. 
  */
  sConfig.Channel = ADC_CHANNEL_1;
  sConfig.Rank = ADC_REGULAR_RANK_1;
  sConfig.SamplingTime = ADC_SAMPLETIME_3CYCLES;
  if (HAL_ADC_ConfigChannel(&hadc2, &sConfig) != HAL_OK)
  {
    Error_Handler();
  }
  /* USER CODE BEGIN ADC2_Init 2 */
 
  /* USER CODE END ADC2_Init 2 */
 
}

Based on these parameters, sampling rate is 1.6MHz. PCLK2 is 96MHz. Prescaler is 4, so I get ADC Clock as 24MHz (96MHz/4). Then 24MHz/(12bit+3 cycle) = 1.6MHz (1.6MSPS).

For verification this calculation, I wrote a toggle function in call back function like this,

void HAL_ADC_ConvCpltCallback(ADC_HandleTypeDef* hadc)
{
  ADC_data = HAL_ADC_GetValue(&hadc2);
	volt = (float)(ADC_data * (3.3 / 4096.0)); //
	testdata_in[i++]=volt;
	i %= 16;
	HAL_GPIO_TogglePin(LED_GPIO_Port,LED_Pin);
 
}

Then I measure the LED toggling pin on the oscilloscope. I got 2.78us pulse width and 5.66us period. So based on toggling, I collected 16 samples in 5.66 us toggling period. Hence, each sample time is 5.66 us/16=0.35375us. Then the sampling rate is 1/0.35375us= 2.82 MHz (MSPS).

So what is the true sampling rate, 2.82MSPS or 1.6 MSPS?

Thank you,

FYI, may target is 1MSPS.

2 REPLIES 2

Don't interrupt in this fashion, use a DMA buffer, say 100 samples, circular, and toggle in DMA completion interrupt. This way you won't saturate the processor.

For exact rates, trigger ADC with a TIM

Tips, Buy me a coffee, or three.. PayPal Venmo
Up vote any posts that you find helpful, it shows what's working..

Ok, I try DMA mode. But I didn't get any reading and toggling. What did I miss?

uint16_t ADC_data[100];
float volt;
float testdata_in[16];
int i=0;
 
int main(void)
{
...
HAL_ADC_Start_DMA(&hadc2, (uint32_t*)&ADC_data,100);
 
}
 
/* USER CODE BEGIN 4 */
 
void HAL_ADC_ConvCpltCallback(ADC_HandleTypeDef* hadc)
{
  
	for(i=0;i<100;i++)
	{
		ADC_data[i] = HAL_ADC_GetValue(&hadc2);
		testdata_in[i] = (float)(ADC_data[i] * (3.3 / 4096.0)); //
	}
	HAL_GPIO_TogglePin(LED_GPIO_Port,LED_Pin);
}
 
/* USER CODE END 4 */

 By the way, new ADC setting is

static void MX_ADC2_Init(void)
{
 
  /* USER CODE BEGIN ADC2_Init 0 */
 
  /* USER CODE END ADC2_Init 0 */
 
  ADC_ChannelConfTypeDef sConfig = {0};
 
  /* USER CODE BEGIN ADC2_Init 1 */
 
  /* USER CODE END ADC2_Init 1 */
  /** Configure the global features of the ADC (Clock, Resolution, Data Alignment and number of conversion) 
  */
  hadc2.Instance = ADC2;
  hadc2.Init.ClockPrescaler = ADC_CLOCK_SYNC_PCLK_DIV4;
  hadc2.Init.Resolution = ADC_RESOLUTION_12B;
  hadc2.Init.ScanConvMode = ADC_SCAN_DISABLE;
  hadc2.Init.ContinuousConvMode = ENABLE;
  hadc2.Init.DiscontinuousConvMode = DISABLE;
  hadc2.Init.ExternalTrigConvEdge = ADC_EXTERNALTRIGCONVEDGE_NONE;
  hadc2.Init.ExternalTrigConv = ADC_SOFTWARE_START;
  hadc2.Init.DataAlign = ADC_DATAALIGN_RIGHT;
  hadc2.Init.NbrOfConversion = 1;
  hadc2.Init.DMAContinuousRequests = ENABLE;
  hadc2.Init.EOCSelection = ADC_EOC_SEQ_CONV;
  if (HAL_ADC_Init(&hadc2) != HAL_OK)
  {
    Error_Handler();
  }
  /** Configure for the selected ADC regular channel its corresponding rank in the sequencer and its sample time. 
  */
  sConfig.Channel = ADC_CHANNEL_1;
  sConfig.Rank = ADC_REGULAR_RANK_1;
  sConfig.SamplingTime = ADC_SAMPLETIME_15CYCLES;
  if (HAL_ADC_ConfigChannel(&hadc2, &sConfig) != HAL_OK)
  {
    Error_Handler();
  }
  /* USER CODE BEGIN ADC2_Init 2 */
 
  /* USER CODE END ADC2_Init 2 */
 
}