cancel
Showing results for 
Search instead for 
Did you mean: 

STM32H723ZG Frequency measure issue.

CYi A.1
Associate

Currently using NUCLEO-STM32H723ZG board.

I'm setting TIMER1 as a PWM output, TIMER2 set as Input Capture direct mode

try to measrue the frequency output from TIMER1.

Clock Configuration : APB1/ APB2 Timer Clocks 100 (MHZ)

Timer 1 :

  • Prescaler : 1-1
  • Counter Period : 100-1
  • PWM output

Timer 2 :

  • Input Capture direct mode
  • Prescaler : 0
  • Counter Period: 4294967295


_legacyfs_online_stmicro_images_0693W00000bjeX4QAI.png
_legacyfs_online_stmicro_images_0693W00000bjeOSQAY.png
_legacyfs_online_stmicro_images_0693W00000bjeLdQAI.pngWhenever I modify the TIMER1 output PWM over 200KHZ, I can't get the stable value or even zero from the ​HAL_TIM_ReadCapturedValue.

I set the TIMER1

  • prescaler : 2-1
  • Counter Period : 100-1
  • Which will generate the PWM to 100M / 2 / 100 = 500MHZ.

But I got read back like this.


_legacyfs_online_stmicro_images_0693W00000bjeZiQAI.png 

Idealy TIMER2 run under 100MHZ( APB/PSC) should be able to capture up to 10MHZ signal.

eventually I need to measure a signal up to 100MHZ, If i set the APB bus to Max frequency (137MHZ) will this method works? or is there any other way to measure it?

#define TIMCLOCK 100000000
#define PRESCALER 1
uint32_t IC_Value1 = 0;
uint32_t IC_Value2 = 0;
uint32_t Difference = 0;
float Frequency = 0;
 
int Is_First_Captured = 0; // is the first value captured? 0 - no, 1- yes
 
void HAL_TIM_IC_CaptureCallback(TIM_HandleTypeDef *htim) // input capture callback
{
	if (htim->Instance == TIM2)
	{
		if (htim -> Channel == HAL_TIM_ACTIVE_CHANNEL_1) // if the source is channel 1
		{
			// first we need to check for either the first value is capture or not
			if (IC_Value1 == 0)
			{
				IC_Value1 = HAL_TIM_ReadCapturedValue(htim, TIM_CHANNEL_1);
	//			IC_Value1 = __HAL_TIM_GET_COUNTER(htim);
			}
 
			else
			{
				IC_Value2 = HAL_TIM_ReadCapturedValue(htim, TIM_CHANNEL_1);
	//			IC_Value2 = __HAL_TIM_GET_COUNTER(htim);
				if (IC_Value2 > IC_Value1 )
				{
					Difference = IC_Value2 - IC_Value1 ;
 
				}
				else if (IC_Value2 < IC_Value1)
				{
					Difference = (0xffffffff-IC_Value1)+ IC_Value2 ;
				}
 
				float refClock = TIMCLOCK / PRESCALER;
				float frequency = refClock / Difference;
				printf("frequency = %2f Hz\r\n",frequency);
 
				IC_Value1 = 0;
			}
		}
//		float frequency = (TIMCLOCK / PRESCALER) / __HAL_TIM_GET_COUNTER(&htim2);
//		printf("Frequency = %10.0f\r\n", frequency);
//		__HAL_TIM_SET_COUNTER(&htim2, 0); // reset the counter
	}
}
int main(void)
{
  /* USER CODE BEGIN 1 */
 
  /* USER CODE END 1 */
 
  /* MCU Configuration--------------------------------------------------------*/
 
  /* Reset of all peripherals, Initializes the Flash interface and the Systick. */
  HAL_Init();
 
  /* USER CODE BEGIN Init */
 
  /* USER CODE END Init */
 
  /* Configure the system clock */
  SystemClock_Config();
 
  /* USER CODE BEGIN SysInit */
 
  /* USER CODE END SysInit */
 
  /* Initialize all configured peripherals */
  MX_GPIO_Init();
  MX_DMA_Init();
  MX_USB_OTG_HS_USB_Init();
  MX_TIM1_Init();
  MX_USART3_UART_Init();
  MX_TIM2_Init();
  /* USER CODE BEGIN 2 */
 
  HAL_UARTEx_ReceiveToIdle_DMA(&huart3, RxBuf, RxBuf_SIZE);
  TIM1 ->CCR1 = 50;
  HAL_TIM_PWM_Start(&htim1, TIM_CHANNEL_1);
  HAL_TIM_IC_Start_IT(&htim2, TIM_CHANNEL_1);
 
  while (1)
  {
 
  }
 
}

3 REPLIES 3

> Idealy TIMER2 run under 100MHZ( APB/PSC) should be able to capture up to 10MHZ signal.

Hardly so. With Cube/HAL, and optimizations switched off, hundreds of cycles per interrupt are the norm.

Even using DMA it would be a challenge to measure 1/10 of timer clock reliably by using captures.

Try timing a number of input clocks using external clock mode and a second timer as a time base.

JW

>>Which will generate the PWM to 100M / 2 / 100 = 500MHZ.

500 KHz ??

Don't expect to interrupt at these speeds.

Don't use printf() and other blocking / slow functions in a callback (you're under interrupt context)

Use the TIM in PWM Input Capture (pair of channels), that can report period and duty by reading the registers when you need the values.

For square waves there's also the Input Prescaler where you can measure time over multiple cycles.

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

Thank you for your reply. Sorry I'm new in here.

I have followed your suggestion and set up two timers to measure. and remove all the printf() in the related path. For this require only need to measure the frequency about 1M~100MHZ.

Currently, I am using TIMER1 to generate a 10KHZ PWM waveform and directly inputting it to TIM2 for measurement. I set TIM5 to trigger an interrupt after 1 second has passed to calculate the frequency.

This is the current setup for configuration.

Main CLK : 550MHZ , APB1/APB2 : 275MHZ

TIM1 : Internal Clock, PWM Generation CH1, PSC 275-1, Counter Period 100-1. ( Which will generate 10KHZ PWM output)

TIM2 : ETR Mode, PSC 275-1, Counter Period 65535. ( which mean I'm sampling in 1MHZ , and every time get 65535 count will into Interrupt)

TIM5 : Internal Clock, PSC 275-1, Counter Period 1000000-1. ( Which will into Interrupt every 1second)

However, every time I add the interrupt function for TIM5, it causes an error in my output. The value of __HAL_TIM_GET_COUNTER(&htim2) should always be less than 65535, as I have set it, but it always exceeds this limit. As you can see from the counter value below, it is over 65535.

I am not sure which part of my settings is incorrect.

void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim)
{
	static uint32_t  frequency = 0.0f;
	static uint32_t end_count = 0;
    if(htim -> Instance = TIM2)
    {
    	InterruptionTim2++;
    }
    if(htim -> Instance = TIM5)
	{
    	HAL_TIM_Base_Stop(&htim2);
    	HAL_TIM_Base_Stop(&htim5);
    	printf("%s","Calculating ........");
    	end_count = __HAL_TIM_GET_COUNTER(&htim2);
    	float time_period = 65535 * InterruptionTim2 + (float)end_count / (float)(APB2);
		frequency = 1.0f / time_period;
		printf("%10f",frequency);
	}
 
}


_legacyfs_online_stmicro_images_0693W00000bjmVZQAY.png 

#include "main.h"
 
 
#include "stdio.h"
#include "inttypes.h"
 
 
TIM_HandleTypeDef htim1;
TIM_HandleTypeDef htim2;
TIM_HandleTypeDef htim5;
TIM_HandleTypeDef htim16;
 
UART_HandleTypeDef huart3;
DMA_HandleTypeDef hdma_usart3_rx;
DMA_HandleTypeDef hdma_usart3_tx;
 
/* USER CODE BEGIN PV */
 
/* USER CODE END PV */
 
/* Private function prototypes -----------------------------------------------*/
void SystemClock_Config(void);
static void MX_GPIO_Init(void);
static void MX_DMA_Init(void);
static void MX_USART3_UART_Init(void);
static void MX_USB_OTG_HS_USB_Init(void);
static void MX_TIM16_Init(void);
static void MX_TIM1_Init(void);
static void MX_TIM2_Init(void);
static void MX_TIM5_Init(void);
/* USER CODE BEGIN PFP */
 
/* USER CODE END PFP */
 
/* Private user code ---------------------------------------------------------*/
/* USER CODE BEGIN 0 */
 
/* For printf function ---------------------------------------------------------*/
#ifdef __GNUC__
#define PUTCHAR_PROTOTYPE int __io_putchar(int ch)
#else
#define PUTCHAR_PROTOTYPE int fputc(int ch, FILE *f)
#endif
 
PUTCHAR_PROTOTYPE
{
  HAL_UART_Transmit(&huart3, (uint8_t *)&ch, 1, HAL_MAX_DELAY);
  return ch;
}
 
uint32_t counter=0;
uint32_t InterruptionTim2;
uint8_t timer_overflow_flag = 0;
 
void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim)
{
    
	static uint32_t  frequency = 0.0f;
	static uint32_t end_count = 0;
    if(htim -> Instance = TIM2)
    {
    	InterruptionTim2++;
    }
 
    if(htim -> Instance = TIM5)
	{
        HAL_TIM_Base_Stop(&htim2);
        HAL_TIM_Base_Stop(&htim5);
        printf("%s","Calculating ........");
    	end_count = __HAL_TIM_GET_COUNTER(&htim2);
    	float time_period = 1000 * InterruptionTim2 + (float)end_count / (float)(APB2);
		frequency = 1.0f / time_period;
		printf("%10f",frequency);
	}
 
}
 
 
/* USER CODE END 0 */
 
/**
  * @brief  The application entry point.
  * @retval int
  */
int main(void)
{
  /* USER CODE BEGIN 1 */
  /* USER CODE END 1 */
 
  /* MCU Configuration--------------------------------------------------------*/
 
  /* Reset of all peripherals, Initializes the Flash interface and the Systick. */
  HAL_Init();
 
  /* USER CODE BEGIN Init */
 
  /* USER CODE END Init */
 
  /* Configure the system clock */
  SystemClock_Config();
 
  /* USER CODE BEGIN SysInit */
 
  /* USER CODE END SysInit */
 
  /* Initialize all configured peripherals */
  MX_GPIO_Init();
  MX_DMA_Init();
  MX_USART3_UART_Init();
  MX_USB_OTG_HS_USB_Init();
  MX_TIM16_Init();
  MX_TIM1_Init();
  MX_TIM2_Init();
  MX_TIM5_Init();
  /* USER CODE BEGIN 2 */
  HAL_UARTEx_ReceiveToIdle_DMA(&huart3, RxBuf, RxBuf_SIZE);
  __HAL_DMA_DISABLE_IT(&hdma_usart3_rx,DMA_IT_HT);
 
  /* Start the PWM and Timer  ---------------------------------------------------------*/
 
  HAL_TIM_Base_Start_IT(&htim2);
  HAL_TIM_Base_Start_IT(&htim5);
  __HAL_TIM_SET_COUNTER(&htim2, 0);
  __HAL_TIM_SET_COUNTER(&htim5, 0);
  TIM1 ->CCR1 = 50;
  HAL_TIM_PWM_Start(&htim1, TIM_CHANNEL_1);
  /* USER CODE END 2 */
 
  /* Infinite loop */
  /* USER CODE BEGIN WHILE */
  while (1)
  {
    /* USER CODE END WHILE */
    /* USER CODE BEGIN 3 */
 
  }
  /* USER CODE END 3 */
}