2017-10-11 02:35 PM
Hello,
I am having some difficulties wrapping my head around what's happening with my TIM3 interrupt. I am creating a timer class for my application. It needs a 1 microsecond resolution. For some reason I can only achieve a 2 microsecond resolution. I started with the STM32F7Cube TIM_Base example for this Nucleo board. The system core clock is 216MHz. I have hopefully followed the instructions for configuring the timer using the method from the MCU documentation:
Update_event = TIM_CLK/((PSC + 1)*(ARR + 1)*(RCR + 1))
My code is as follows:
// Initialize TIMx peripheral as follows for a 1us tick (1MHz):
// + Period = SystemCoreClock/1000000 - 1
// + ClockDivision = 0
// + Counter direction = Up
TimHandle.Init.Period = (SystemCoreClock/TICK_RATE_HZ) - 1; // TICK_RATE_HZ = 1x10^6
TimHandle.Init.Prescaler = 0;
TimHandle.Init.ClockDivision = TIM_CLOCKDIVISION_DIV1;
TimHandle.Init.CounterMode = TIM_COUNTERMODE_UP;
TimHandle.Init.RepetitionCounter = 0;
TimHandle.Init.AutoReloadPreload = TIM_AUTORELOAD_PRELOAD_DISABLE;
if (HAL_TIM_Base_Init(&TimHandle) != HAL_OK)
{
/* Initialization Error */
Error_Handler();
}
//##-2- Start the TIM Base generation in interrupt mode ####################
if (HAL_TIM_Base_Start_IT(&TimHandle) != HAL_OK)
{
/* Starting Error */
Error_Handler();
}
Many thanks in advance!
Solved! Go to Solution.
2017-10-17 02:13 PM
If the clock runs at 108 MHz then the period needs to be 107 ie 108-1 to get to 1us (or 1 MHz)
Interrupting at MHz rates is not recommended, it will burn a ridiculous number of cycles, more so with HAL.
If you want clock signals, use the TIM to generate the signal in HW, not with interrupts.
1 MHz 0.5us width, Prescaler = 0, Period = 107, Pulse = 54 (50/50 Duty), PWM Mode
500 KHz 1us width, Prescaler = 0, Period = 215, Pulse = 108 (50/50 Duty), PWM Mode
2017-10-12 07:36 PM
On a general note, check the top level clock tree feeding the timer block diagram to see if there is a div2 prescaler not shown at the timer block diagram level.
2017-10-15 04:25 AM
Like KIC8462852 EPIC2024278916 wrote, check the clock source.
But you measured 50% only of the period. So in your case it is 1/4 of the desired frequency
and not a div2 prescaler.
- Joerg -
2017-10-16 10:58 AM
Hello,
Thank you both for the analysis. I took the existing example for TIM3 from the STM32CubeF7 example project and verified the clock source for TIM3. In this case TIM3CLK = PCLK1*2 where PCLK1=HCLK/4. Using that information TIM3CLK = HCLK/2 = SystemCoreClock/2. For this target the SystemCoreClock is 216 MHz. As a result TIM3CLK is 108 MHz.
Is there something I'm missing? I've played with all sorts of permutations of the Prescaler and Period but can't seem to achieve the 1us period I need. I even found a clock calculator from Mikroelectronica. Their ARR and PSC values correspond with what I calculated (PSC = 0, ARR = 215) but I still don't have the right 1 us clock rate desired.
Many thanks for any other tips.
2017-10-17 06:51 AM
To reproduce I wrote a simple app with Timer 3 using your values.
This is my init code created with CubeMX:
/* TIM3 init function */
static void MX_TIM3_Init(void) {TIM_ClockConfigTypeDef sClockSourceConfig;
TIM_MasterConfigTypeDef sMasterConfig;htim3.Instance = TIM3;
htim3.Init.Prescaler = 0; htim3.Init.CounterMode = TIM_COUNTERMODE_UP; htim3.Init.Period = 216; htim3.Init.ClockDivision = TIM_CLOCKDIVISION_DIV1; htim3.Init.AutoReloadPreload = TIM_AUTORELOAD_PRELOAD_DISABLE; if (HAL_TIM_Base_Init(&htim3) != HAL_OK) { _Error_Handler(__FILE__, __LINE__); }sClockSourceConfig.ClockSource = TIM_CLOCKSOURCE_INTERNAL;
if (HAL_TIM_ConfigClockSource(&htim3, &sClockSourceConfig) != HAL_OK) { _Error_Handler(__FILE__, __LINE__); }sMasterConfig.MasterOutputTrigger = TIM_TRGO_RESET;
sMasterConfig.MasterSlaveMode = TIM_MASTERSLAVEMODE_DISABLE; if (HAL_TIMEx_MasterConfigSynchronization(&htim3, &sMasterConfig) != HAL_OK) { _Error_Handler(__FILE__, __LINE__); }}
To test the frequency:
void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim)
{ if (htim->Instance == TIM3) { HAL_GPIO_TogglePin(dbgpin_GPIO_Port, dbgpin_Pin); } }The results are in the attached PDF. Almost perfect.
What are you looking for?
________________ Attachments : document.pdf : https://st--c.eu10.content.force.com/sfc/dist/version/download/?oid=00Db0000000YtG6&ids=0680X000006HyN0&d=%2Fa%2F0X0000000b6h%2FBb9RnZkSZliJLwuQCN6g9JoAnS9024K.aJpnbTzht8Y&asPdf=false2017-10-17 10:02 AM
Hi Joerg,
Thank you for providing the report. I too was able to get a 2us pulse width, originally. My desire is to get a 1us resolution (ie pulse width). If this is not possible then is there an explanation for that? The best I can seem to do is this:
Many thanks for taking the time for your above analysis.
2017-10-17 02:13 PM
If the clock runs at 108 MHz then the period needs to be 107 ie 108-1 to get to 1us (or 1 MHz)
Interrupting at MHz rates is not recommended, it will burn a ridiculous number of cycles, more so with HAL.
If you want clock signals, use the TIM to generate the signal in HW, not with interrupts.
1 MHz 0.5us width, Prescaler = 0, Period = 107, Pulse = 54 (50/50 Duty), PWM Mode
500 KHz 1us width, Prescaler = 0, Period = 215, Pulse = 108 (50/50 Duty), PWM Mode
2017-10-17 02:25 PM
Hi Mehmooed, It is a 1us resolution!
When you toggle the state of a signal every 1us you will get the half of the frequency, 2us.
Do you need the signal for software events or an extenal signal? PWM like
Turvey.Clive.002
mentionedis a better choice for external signal generation.
- Joerg-
2017-10-17 03:35 PM
Thank you to you both, Clive and Joerg. Clive provided exactly the solution I am seeking:
500 KHz 1us width, Prescaler = 0, Period = 215, Pulse = 108 (50/50 Duty), PWM Mode
2017-10-17 03:47 PM
There is also a very useful YouTube video I found that explains how the PSC and ARR are assigned for a desired frequency: