2022-01-07 03:36 PM
Looking at the clock in the MX Device Configuration Tool it says 204 to APB1 Timer Clocks (MHz).
To get to 10000 Hz I have to divide 204 MHz by 20400.
Fortunately there are a bunch of ways to do this. But on the first try I tried
Prescaler 51
Counter Period 100
Internal Clock Division Division by 4
The reason I did it this way is that I suspected 10000 Hz will be too fast and they will eventually go to 1000 Hz or something between 1000 Hz and 10000 Hz and it would be easy to change the counter period for the new value.
I saved it and generated new code.
static void MX_TIM14_Init(void)
{
/* USER CODE BEGIN TIM14_Init 0 */
/* USER CODE END TIM14_Init 0 */
TIM_OC_InitTypeDef sConfigOC = {0};
/* USER CODE BEGIN TIM14_Init 1 */
/* USER CODE END TIM14_Init 1 */
htim14.Instance = TIM14;
htim14.Init.Prescaler = 51;
htim14.Init.CounterMode = TIM_COUNTERMODE_UP;
htim14.Init.Period = 100;
htim14.Init.ClockDivision = TIM_CLOCKDIVISION_DIV4;
htim14.Init.AutoReloadPreload = TIM_AUTORELOAD_PRELOAD_ENABLE;
if (HAL_TIM_Base_Init(&htim14) != HAL_OK)
{
Error_Handler();
}
if (HAL_TIM_OC_Init(&htim14) != HAL_OK)
{
Error_Handler();
}
sConfigOC.OCMode = TIM_OCMODE_TIMING;
sConfigOC.Pulse = 0;
sConfigOC.OCPolarity = TIM_OCPOLARITY_HIGH;
sConfigOC.OCFastMode = TIM_OCFAST_DISABLE;
if (HAL_TIM_OC_ConfigChannel(&htim14, &sConfigOC, TIM_CHANNEL_1) != HAL_OK)
{
Error_Handler();
}
/* USER CODE BEGIN TIM14_Init 2 */
/* USER CODE END TIM14_Init 2 */
}
The generated code looks good.
The interrupt would toggle a GPIO and I can see the timing.
My USB logic Analyzer was set to sample at 25 Msamples/sec
And I was reading 25.72 and 25.76 microseconds (us) when I expected 100 us.
It was off by a factor of 4.
It made me think it was the divide by 4.
So I went back to MX Device Configuration Tool and changed the Divide by 4 to No Division.
The result was:
Prescaler 51
Counter Period 100
Internal Clock Division No Division
I saved and it generated the code
static void MX_TIM14_Init(void)
{
/* USER CODE BEGIN TIM14_Init 0 */
/* USER CODE END TIM14_Init 0 */
TIM_OC_InitTypeDef sConfigOC = {0};
/* USER CODE BEGIN TIM14_Init 1 */
/* USER CODE END TIM14_Init 1 */
htim14.Instance = TIM14;
htim14.Init.Prescaler = 51;
htim14.Init.CounterMode = TIM_COUNTERMODE_UP;
htim14.Init.Period = 100;
htim14.Init.ClockDivision = TIM_CLOCKDIVISION_DIV1;
htim14.Init.AutoReloadPreload = TIM_AUTORELOAD_PRELOAD_ENABLE;
if (HAL_TIM_Base_Init(&htim14) != HAL_OK)
{
Error_Handler();
}
if (HAL_TIM_OC_Init(&htim14) != HAL_OK)
{
Error_Handler();
}
sConfigOC.OCMode = TIM_OCMODE_TIMING;
sConfigOC.Pulse = 0;
sConfigOC.OCPolarity = TIM_OCPOLARITY_HIGH;
sConfigOC.OCFastMode = TIM_OCFAST_DISABLE;
if (HAL_TIM_OC_ConfigChannel(&htim14, &sConfigOC, TIM_CHANNEL_1) != HAL_OK)
{
Error_Handler();
}
/* USER CODE BEGIN TIM14_Init 2 */
/* USER CODE END TIM14_Init 2 */
}
Looking at the logic analyzer I got the exact same result. An interrupt every 25.72 and 25.76 us, when it should have been 1/4 that.
Like I said there multiple ways to do this, so I changed the prescaler from 51 to 204.
Prescaler 204
Counter Period 100
Internal Clock Division No Division
Saved and generated new code.
static void MX_TIM14_Init(void)
{
/* USER CODE BEGIN TIM14_Init 0 */
/* USER CODE END TIM14_Init 0 */
TIM_OC_InitTypeDef sConfigOC = {0};
/* USER CODE BEGIN TIM14_Init 1 */
/* USER CODE END TIM14_Init 1 */
htim14.Instance = TIM14;
htim14.Init.Prescaler = 204;
htim14.Init.CounterMode = TIM_COUNTERMODE_UP;
htim14.Init.Period = 100;
htim14.Init.ClockDivision = TIM_CLOCKDIVISION_DIV1;
htim14.Init.AutoReloadPreload = TIM_AUTORELOAD_PRELOAD_ENABLE;
if (HAL_TIM_Base_Init(&htim14) != HAL_OK)
{
Error_Handler();
}
if (HAL_TIM_OC_Init(&htim14) != HAL_OK)
{
Error_Handler();
}
sConfigOC.OCMode = TIM_OCMODE_TIMING;
sConfigOC.Pulse = 0;
sConfigOC.OCPolarity = TIM_OCPOLARITY_HIGH;
sConfigOC.OCFastMode = TIM_OCFAST_DISABLE;
if (HAL_TIM_OC_ConfigChannel(&htim14, &sConfigOC, TIM_CHANNEL_1) != HAL_OK)
{
Error_Handler();
}
/* USER CODE BEGIN TIM14_Init 2 */
/* USER CODE END TIM14_Init 2 */
}
This time I got the interrupt every 101.48 to 101.52 us which I was expecting.
I have not dug into your code to find out why the Divide by 4 it is not working. I am just saying it is not working.
The about says I am running:
Version: 1.8.0
Build: 11526_20211125_0815 (UTC)
Solved! Go to Solution.
2022-01-09 11:35 PM
Hi @KiptonM ,
at first look, the
htim14.Init.ClockDivision = TIM_CLOCKDIVISION_DIV1;
relate to
which is not related to counting clock, but rather the clock used for input capture filtering.
I agree CubeMx might be confusing (as my understanding is that CKD is useless except in capture mode).
Reference Manual should always be used whenever there is uncertainty (timers offers so many options that it is always complex to set up).
I think to achieve your required interrupt rate, you should just play with .Prescaler and .Period values.
Regards.
In order to give better visibility on the answered topics, please click on 'Select as Best' on the reply which solved your issue or answered your question. See also 'Best Answers'
2022-01-07 03:56 PM
In stm32mp1xx_hal_tim.c
around line 5959
is the code
if (IS_TIM_CLOCK_DIVISION_INSTANCE(TIMx))
{
/* Set the clock division */
tmpcr1 &= ~TIM_CR1_CKD;
tmpcr1 |= (uint32_t)Structure->ClockDivision;
}
I have no idea what IS_TIM_CLOCK_DIVISION_INSTANCE(TIMx) does, but it returns false.
So it does not do anything to change the Divide by.
Found it in stm32mp157axx_cm4.h around line 38907
/****************** TIM Instances : supporting clock division *****************/
#define IS_TIM_CLOCK_DIVISION_INSTANCE(INSTANCE)\
(((INSTANCE) == TIM1) || \
((INSTANCE) == TIM2) || \
((INSTANCE) == TIM3) || \
((INSTANCE) == TIM4) || \
((INSTANCE) == TIM5) || \
((INSTANCE) == TIM8) || \
((INSTANCE) == TIM15) || \
((INSTANCE) == TIM16) || \
((INSTANCE) == TIM17))
It does not have TIM14 -- Timer 14
2022-01-09 11:35 PM
Hi @KiptonM ,
at first look, the
htim14.Init.ClockDivision = TIM_CLOCKDIVISION_DIV1;
relate to
which is not related to counting clock, but rather the clock used for input capture filtering.
I agree CubeMx might be confusing (as my understanding is that CKD is useless except in capture mode).
Reference Manual should always be used whenever there is uncertainty (timers offers so many options that it is always complex to set up).
I think to achieve your required interrupt rate, you should just play with .Prescaler and .Period values.
Regards.
In order to give better visibility on the answered topics, please click on 'Select as Best' on the reply which solved your issue or answered your question. See also 'Best Answers'
2022-01-27 08:21 AM
Thanks that is what I did and it is working now.