Skip to main content
ConfusedContrarian
Associate III
July 11, 2019
Question

Frequency limitation when trying to generate a 2us period on a Timerfor the STM32F7.

  • July 11, 2019
  • 1 reply
  • 743 views

Hi, I'm trying to generate a 500KHz counter on TIM1 on the STM32F7 to trigger an ADC conversion and I'm currently having issues as it seems to top out at 360KHz. I'm toggling a GPIO pin with a scope to the input and simply changing the Period on the timer to see what's happening.

Here's my current code:

With a period of 539, I get 200Khz as expected:

0690X000009YfWCQA0.png

With a period of 239, I get around 300kHz

0690X000009YfW2QAK.png

With a peroid of 215, I get around 330 kHz instead of the expected 500Khz.

With a period of 108, I get a frequency of around 369Khz:

0690X000009YfVYQA0.png

I'm using CubeMX to generate my project files and I initialise my timer like this:

static void MX_TIM1_Init(void)
{
 
 /* USER CODE BEGIN TIM1_Init 0 */
 
 /* USER CODE END TIM1_Init 0 */
 
 TIM_ClockConfigTypeDef sClockSourceConfig = {0};
 TIM_MasterConfigTypeDef sMasterConfig = {0};
 
 /* USER CODE BEGIN TIM1_Init 1 */
 
 /* USER CODE END TIM1_Init 1 */
 htim1.Instance = TIM1;
 htim1.Init.Prescaler = 0;
 htim1.Init.CounterMode = TIM_COUNTERMODE_UP;
 htim1.Init.Period = 108;
 htim1.Init.ClockDivision = TIM_CLOCKDIVISION_DIV1;
 htim1.Init.RepetitionCounter = 0;
 htim1.Init.AutoReloadPreload = TIM_AUTORELOAD_PRELOAD_DISABLE;
 if (HAL_TIM_Base_Init(&htim1) != HAL_OK)
 {
 Error_Handler();
 }
 sClockSourceConfig.ClockSource = TIM_CLOCKSOURCE_INTERNAL;
 if (HAL_TIM_ConfigClockSource(&htim1, &sClockSourceConfig) != HAL_OK)
 {
 Error_Handler();
 }
 sMasterConfig.MasterOutputTrigger = TIM_TRGO_OC1;
 sMasterConfig.MasterOutputTrigger2 = TIM_TRGO2_OC1REF;
 sMasterConfig.MasterSlaveMode = TIM_MASTERSLAVEMODE_DISABLE;
 if (HAL_TIMEx_MasterConfigSynchronization(&htim1, &sMasterConfig) != HAL_OK)
 {
 Error_Handler();
 }
 /* USER CODE BEGIN TIM1_Init 2 */
 
 /* USER CODE END TIM1_Init 2 */
 
}

I start the timer in interrupt mode:

if(HAL_TIM_Base_Start_IT(&htim1) != HAL_OK)
		{
			Error_Handler();
		}

I then toggle a GPIO Pin When Period has elapsed:

void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim)
{
	
	if(htim->Instance == TIM1)
	{
		
		HAL_GPIO_TogglePin(GPIOG, GPIO_PIN_6);
		 
	}
}

I've tried changing the speed of the GPIO pin:

 /*Configure GPIO pin : PG6 */
 GPIO_InitStruct.Pin = GPIO_PIN_6;
 GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;
 GPIO_InitStruct.Pull = GPIO_NOPULL;
 GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_VERY_HIGH;
 HAL_GPIO_Init(GPIOG, &GPIO_InitStruct);

but this doesn't seem to make any difference. Can someone please help shed some light on this?

This topic has been closed for replies.

1 reply

Tesla DeLorean
Guru
July 11, 2019

The TIM provide direct methods to toggling signals and triggering ADC, suggest you use those rather than determine the saturation point of the core with interrupt entry/exit and multi-layered overhead added by HAL.

Tips, Buy me a coffee, or three.. PayPal VenmoUp vote any posts that you find helpful, it shows what's working..
ConfusedContrarian
Associate III
July 11, 2019

Thanks for the reply, Clive. That's currently what I'm doing. I'm using ADC_EXTERNALTRIGCONV_T1_TRGO on Timer 1 to trigger a conversion on the ADC but I would like to reliably determine what this frequency is to know my sampling rate. I guess, I could just compute the FFT and do a back calculation to determine the sampling frequency. What is the best way to check the ADC is starting a conversion on the correct timings without using interrupts? Would toggling a GPIO on the

void HAL_ADC_ConvCpltCallback(ADC_HandleTypeDef* hadc)

work as well?