I have not used the CubeMX HAL very much but I did recently work on a project that made use of the timer input capture function. Based on this experience, I think I can make a good guess as to what the “PERIOD” and “PRESCALER” values do.
Generally speaking, the STM32 timers are fed by the system core clock (sometimes, depending on the timer, it can be core clock *2 or /2). For sake of this discussion, I’ll assume it’s the SystemCoreClock.
If you want to do an input capture on a signal with a nominal 50 Hz period (sounds like a AC line frequency application, something I’ve had some past experience with ) then you’ll want to set PRESCALER to a value 1 larger than the integer result of:
SystemCoreClock / (Input capture signal nominal frequency) / (PERIOD + 1)
It is important that you set PRESCALER to a value that will divide the timer’s base clock by enough so the timer’s counter is not clocked at a rate less than 0x10000 times (assuming it’s a 16-bit timer) over the worst-case (longest) period of the signal you want to measure the frequency/period of. So, assuming you’re dealing with a AC line frequency application with a nominal line frequency of 50 Hz, you should probably plan on a worst-case line frequency of 47 Hz. I’ll assume this application is running on a F0 series device with a 48 MHz SystemCoreClock:
PRESCALER = 48000000U / 47 / 0x10000 = 15.58 = (round to lowest integer) 15
Note that the PRESCALER value (or, at least, the value that gets loaded into TIMx->PSC) is actually 1 less than the actual
division factor. If TIMx->PSC is set to 15, the clock will be divided by 16 (15 + 1).
I’m assuming that PERIOD is the value that is programmed into the timer’s ARR (Auto Reload Register). This represents the terminal value of the timer’s CNT register if counting up - that is, the CNT register is reset to 0 when reaching this value - or the value that CNT is reset to when it underflows if counting down. I’d recommend leaving this at 0xFFFF.
To measure period, configure the timer channel(s) that you’re feeding your input signal to for input capture mode, set their edge sensitivity as needed/desired, and set up a timer interrupt to be generated on an input capture event.
Inside the timer ISR, you’ll need to allocate a static variable to hold the ‘previous capture’ value. Then, to get the period of your signal, do the following:
static uint16_t previous;
capture = TIMx->CCRx;
period = capture - previous;
previous = capture;
If the timer you’re working with is 32 bits wide (e.g. TIM2), make all varaibles uint32_t instead of uint16_t
To convert the (period) value to frequency, do this:
extern uint32_t SystemCoreClock; // defined in system_stm32xxxx.c
frequency = SystemCoreClock / (TIMx->PSC + 1) / period
If you want more resolution; i.e. if you’d like the measurement in 1/100 Hz units, you could do this:
frequency = SystemCoreClock * 10U / ((uint32_t) period * 10U) / (TIMx->PSC + 1)
The order of operations and reason for doing two *10’s instead of one *100 is to get the best possible resolution and minimum rounding loss while avoiding 32-bit unsigned integer overflow in intermediate results.