Attached sample project.
- 401 working at 84MHz with external 25MHz crystal.
- TIM2 is the frequency counter. Slave Reset mode, taking TRGO signal from TIM3, external clock, no prescaler.
- TIM3 is the master. Prescaler=1399+1, 84MHz/1400=60KHz input clock.
PWM match happens at 60.000 (1000ms), triggers a DMA transfer from TIM2 counter, overflows at 60.000+1 (16us later), resetting TIM2.
If you want faster readings (ex. every 100/10mS, adjust TIM3 prescaler:
Prescaler TIM3 clock Update rate Resolution
1399 60KHz 0,999983Hz 1Hz
139 600KHz 9,99983Hz 10Hz
13 6MHz 99,9983Hz 100Hz
My clock generator is not very accurate, neither will the chinesium 25MHz crystal, yet results were pretty good (50ppm error):
Freq Counter
10KHz 10.000
100KHz 99.995
10MHz 9.999.543
25MHz 24.998.860
The whole thing takes just 4 lines, excluding the initialization generated by CubeMX:
volatile uint32_t counter;
HAL_DMA_Start(htim3.hdma[TIM_DMA_ID_CC4], (uint32_t)&TIM2->CNT, (uint32_t)&counter, 1);
__HAL_TIM_ENABLE_DMA(&htim3, TIM_DMA_CC4);
__HAL_TIM_ENABLE(&htim3);
__HAL_TIM_ENABLE(&htim2);
Ensure to read the STM32F401
datasheet, you'll find the AC characteristics there.
For the timer clock input input, max frequency is Ftim/2, where Ftim is the peripheral clock.
In this case, it's working at 84MHz, so max external clock will be 42MHz.
Also check:
Reference manual,
Timer cookbook.
Faster STM32 will sample faster frequencies, ex. the STM32G431 works at 170MHz, timer will be able to sample up to 85MHz.