STM32 Timer Input Capture: Measure Frequency & Pulse Width (HAL)
Measuring signal frequency and pulse width in hardware — not with software loops, not with HAL_Delay() counting — is what the STM32 Timer Input Capture mode exists for. The timer peripheral timestamps signal edges at the exact clock cycle they occur, giving you microsecond-level accuracy at frequencies far too high for software polling.
This is Part 4 of the STM32 Timer Series. It covers how to configure TIM2 in Input Capture mode using CubeMX and HAL, connect it to a PWM signal from TIM1, and implement HAL_TIM_IC_CaptureCallback() to calculate both signal frequency (rising-edge to rising-edge) and pulse width (rising-edge to falling-edge). Results are verified in the CubeIDE debugger against a known 10 kHz PWM signal.
Before starting, you should be familiar with PWM output configuration — this tutorial uses TIM1 as the signal source for TIM2. See Part 1: PWM Output with/without DMA.
STM32 Timer Series — all parts:
- Part 1 — PWM Output with / without DMA
- Part 2 — Measure PWM Input Signal
- Part 3 — Timer Encoder Mode
- Part 4 — Input Capture Mode ← you are here
- Part 5 — Timer Sync with Slave Trigger Mode
- Part 6 — Timer Sync for 3-Phase PWM
- Part 7 — Timer Sync using Slave Reset Mode
- Part 8 — Cascading Timers: 48-Bit Counter
- Part 9 — One Pulse Mode (OPM)
- Part 10 — Timer in Gated Mode
STM32 Input Capture: How It Works
Measuring the frequency or pulse width of an external signal is a very common requirement in embedded systems. Whether you’re working with sensors, PWM signals, communication protocols, or frequency counters, you need a reliable and accurate way to measure the time between signal edges.
STM32 microcontrollers make this task simple through a built-in Input Capture feature in their timers. Instead of relying on software loops or manual polling, the hardware captures timer values at the exact moment an input event occurs. This allows you to measure high-speed signals with excellent precision, without loading the CPU.
What is Input Capture in STM32?
Input Capture is a timer feature that lets the microcontroller record the value of a timer counter when an external signal edge (rising, falling, or both) is detected on a specific input pin.
Here’s how it works step by step:
- You configure a timer to run at a known clock frequency.
- You select one of the timer’s input capture channels and map it to a GPIO pin.
- When a signal transition occurs (for example, a rising edge), the hardware automatically stores the current timer value into a special capture register.
- An interrupt can be triggered, allowing your code to read the captured value immediately.
By recording the timer value at two consecutive edges, you can calculate the time difference between them. This time difference forms the basis for frequency and pulse width calculations.
For example:
- Capturing two rising edges gives the period of the signal, which can be converted to frequency.
- Capturing rising and falling edges lets you measure the high time of the pulse, which gives the pulse width or duty cycle.
The image below shows how STM32 Timer Input Capture uses three captured timer values to measure both signal frequency and pulse width. The timer runs continuously at a known clock rate, and each signal edge automatically stores the current timer count into a capture register. By capturing two consecutive rising edges, the signal period is obtained, which is then used to calculate the frequency. Capturing the falling edge between those rising edges allows measurement of the signal high time, which is used to determine pulse width and duty cycle.
Because this process is handled by the timer hardware, it’s extremely precise and works even at high signal speeds.
Why Use Input Capture for Frequency & Pulse Measurement?
While you could try to measure signal timing using software loops or delay functions, those methods are prone to errors, jitter, and CPU delays — especially at higher frequencies. Input Capture eliminates these issues by using hardware-level timestamping.
Here are some key advantages of using Input Capture on STM32:
- High Accuracy: The timer captures events at the exact clock cycle, giving very precise measurements.
- Handles High Frequencies: Since the CPU isn’t constantly polling the pin, input capture works even with fast input signals.
- Automatic Measurement: Once configured, the timer hardware captures edges and generates interrupts automatically.
- Low CPU Usage: The processor only handles calculations after capture events, leaving more time for other tasks.
- Flexible Edge Detection: You can measure on rising edges, falling edges, or both — allowing frequency, pulse width, and duty cycle measurements with a single setup.
STM32 Input Capture: Wiring & CubeMX Setup
In this tutorial, we’ll generate a PWM signal using TIM1 and feed it into TIM2 configured in Input Capture mode. This allows us to measure the frequency and pulse width of a known signal directly on the same STM32 board, without using any external signal generators.
This method is ideal for testing because both the signal generation and measurement happen inside the microcontroller. It reduces the chances of noise, wiring errors, or instability, giving you clean and accurate results.
Connecting TIM1 PWM Output to TIM2 Input Capture Pin
To measure a signal using Input Capture, we need a signal source. In this setup:
- TIM1 is configured in PWM output mode to generate a stable square wave signal at a known frequency (for example, 10 kHz).
- TIM2 is configured in Input Capture mode to measure this same signal.
- The PWM output pin of TIM1 is physically connected to the Input Capture pin of TIM2.
Here’s the basic connection:
| TIM1 (PWM Output) | TIM2 (Input Capture) | Connection Description |
|---|---|---|
| PA8 (TIM1_CH1) | PA0 (TIM2_CH1) | Connect this pin directly with a jumper wire |
PA8 is used because it corresponds to TIM1 Channel 1, which is a common pin for PWM output.
PA0 is selected for TIM2 Channel 1, which is frequently used for input capture on many STM32 boards.
Clock Configuration
Below is the image showing the clock configuration for the project.
- Here we will use two timers, i.e Timer 1 for the PWM output and Timer 2 for the Input Capture
- Timer 1 is connected to the APB2, which is running at 180 MHz.
- Timer 2 is connected to the APB1, which is running at 90 MHz.
TIM2 Input Capture Configuration (Frequency Mode)
Below is the image showing the configuration of the TIM2 for Input Capture Mode.
- Enable the Input capture Direct Mode on channel 1.
- The Prescaler is set to 90, which will divide the APB2 clock by 90, making the Timer 2 clock = 1 MHz.
- I am leaving the ARR to 0xffffffff (Max for 32 bit Timer).
Also Enable the Interrupt for the TIM2. This allow the input Capture to trigger the interrupt, whenever the Rising / Falling Edge is detected.
TIM1 PWM Output Configuration
The TIMER1 is configured to output a PWM signal. If you want to know more about PWM output, check out the tutorial PWM (Pulse Width Modulation) in STM32.
TIM2 Input Capture Configuration (Pulse Width Mode)
We need to modify the Input capture Configuration in CubeMX as shown below.
As you can see in the image above, I have switched the input capture Polarity to both the edges. This will make the interrupt to trigger for both the edges of the incoming signal.
Also Enable the Interrupt for the TIM2. This allow the input Capture to trigger the interrupt, whenever the Rising / Falling Edge is detected.
STM32 Input Capture Code & Results
Measuring Frequency: HAL Code & Result
In order to measure the Frequency of the input signal, we need to measure the time between the 2 rising edges, or between 2 falling edges.
- When the first Rising edge occurs, the counter value is recorded.
- Another counter value is recorded after the second rising edge occurs.
- Now the difference between these 2 counter values is calculated.
- This Difference in the counter values will give us the frequency.
This entire process is shown below.
#define TIMCLOCK 90000000
#define PRESCALAR 90
uint32_t IC_Val1 = 0;
uint32_t IC_Val2 = 0;
uint32_t Difference = 0;
int Is_First_Captured = 0;
/* Measure Frequency */
float frequency = 0;
void HAL_TIM_IC_CaptureCallback(TIM_HandleTypeDef *htim)
{
if (htim->Channel == HAL_TIM_ACTIVE_CHANNEL_1)
{
if (Is_First_Captured==0) // if the first rising edge is not captured
{
IC_Val1 = HAL_TIM_ReadCapturedValue(htim, TIM_CHANNEL_1); // read the first value
Is_First_Captured = 1; // set the first captured as true
}
else // If the first rising edge is captured, now we will capture the second edge
{
IC_Val2 = HAL_TIM_ReadCapturedValue(htim, TIM_CHANNEL_1); // read second value
if (IC_Val2 > IC_Val1)
{
Difference = IC_Val2-IC_Val1;
}
else if (IC_Val1 > IC_Val2)
{
Difference = (0xffffffff - IC_Val1) + IC_Val2;
}
float refClock = TIMCLOCK/(PRESCALAR);
frequency = refClock/Difference;
__HAL_TIM_SET_COUNTER(htim, 0); // reset the counter
Is_First_Captured = 0; // set it back to false
}
}
}- The above interrupt callback function is called whenever the Rising edge is detected.
- When called first time, Is_First_Captured was 0 so the hence the IC_Val1 will be recorded.
- When called after the second rising edge, the Is_First_Captured is 1 now so IC_Val2 will be recorded.
- We will calculate the Difference between the 2 IC values.
- Reference clock is calculated based on the setup we have done for our timer.
- Frequency is equal to the (Reference clock / Difference). This is because the counter value depends on the Timer clock.
In the main function, we have to start the TIMER in the Input capture interrupt mode.
I am also starting the Timer 1 in the PWM mode, so to provide the signal for the Timer2.
TIM1->CCR1 = 50;
HAL_TIM_PWM_Start(&htim1, TIM_CHANNEL_1);
HAL_TIM_IC_Start_IT(&htim2, TIM_CHANNEL_1);Measuring Frequency: result
Below is the image showing the output of the above code.
The Timer1 is configured to generate a PWM with frequency 10KHz. This PWM signal is fed to the input capture pin of Timer2. The image above shows the frequency measured by the Timer2 is equal to 10KHz.
Measuring Pulse Width: HAL Code & Result
To accurately measure the pulse width of an input signal, the timer interrupt must be configured to trigger on both the rising and falling edges of the signal. The rising edge marks the start of the pulse, while the falling edge indicates the end of the pulse. By capturing the timer value at both of these edges, we can calculate the exact high time of the signal. This high time represents the pulse width, which is especially useful when measuring PWM signals or duty cycles.
- When the first rising edge occurs, The counter value is stored in the ICVal1.
- The next interrupt will occur at the falling edge, and the counter value is stored in the ICVal2.
- The Pulse width can be calculated using this counter value.
The process for the same is shown below
/* Measure Width */
uint32_t usWidth = 0;
void HAL_TIM_IC_CaptureCallback(TIM_HandleTypeDef *htim)
{
if (htim->Channel == HAL_TIM_ACTIVE_CHANNEL_1) // if the interrupt source is channel1
{
if (Is_First_Captured==0) // if the first value is not captured
{
IC_Val1 = HAL_TIM_ReadCapturedValue(htim, TIM_CHANNEL_1); // read the first value
Is_First_Captured = 1; // set the first captured as true
}
else // if the first is already captured
{
IC_Val2 = HAL_TIM_ReadCapturedValue(htim, TIM_CHANNEL_1); // read second value
if (IC_Val2 > IC_Val1)
{
Difference = IC_Val2-IC_Val1;
}
else if (IC_Val1 > IC_Val2)
{
Difference = (0xffffffff - IC_Val1) + IC_Val2;
}
float refClock = TIMCLOCK/(PRESCALAR);
float mFactor = 1000000/refClock;
usWidth = Difference*mFactor;
__HAL_TIM_SET_COUNTER(htim, 0); // reset the counter
Is_First_Captured = 0; // set it back to false
}
}
}- The above callback function is called when either the Rising or Falling edge is detected.
- When called for the rising edge, Is_First_Captured was 0 so the hence the IC_Val1 will be recorded.
- When called for the falling edge, the Is_First_Captured is 1 now so IC_Val2 will be recorded.
- We will then calculate the Difference between the 2 values.
- This difference is the time for which the Pulse is high, and this time will depend on the timer configuration.
- To measure this time in microseconds, we have to use the reference clock.
- Reference clock is calculated based on the setup we have done for our timer.
- And finally, the usWidth will be calculated.
STM32 Timer Input Capture: Frequency & Pulse Width — Video Tutorial
This video walks through the complete STM32 Input Capture setup — configuring TIM1 for PWM output and TIM2 for input capture in CubeMX, connecting PA8 to PA0 with a jumper wire, writing HAL_TIM_IC_CaptureCallback() to measure frequency from two rising edges and pulse width from rising-to-falling edges, and verifying both results in the CubeIDE debugger against a 10 kHz source signal.
STM32 Input Capture: Troubleshooting & FAQs
Common Issues & Fixes
Even after setting up the project correctly, you might encounter issues such as inaccurate frequency readings, unstable pulse width measurements, or timer capture not working as expected. These problems usually occur due to configuration errors, timer limitations, or missing interrupt settings. Below are some of the most common issues and how to fix them.
Incorrect Frequency or Pulse Width Readings
One of the most frequent issues when working with STM32 Input Capture is getting incorrect or unstable frequency and pulse width values. Here are some possible reasons and solutions:
- Wrong Timer Clock or Prescaler Settings
If the timer clock or prescaler values are not set correctly in CubeMX, the calculated time difference between captured edges will be wrong. Double-check theTIMCLOCKandPRESCALARvalues in your code to ensure they match the actual CubeMX configuration. - Using the Wrong Capture Channel
Make sure the input capture pin is mapped to the correct channel (e.g., PA0 for TIM2_CH1). If the wrong channel is selected, the timer will not capture any edges. - Edge Selection Not Configured Properly
For frequency measurement, capturing only on rising edges is usually enough. But for pulse width, you must enable both edges. If this is not done, the measured pulse width will be inaccurate or always zero. - Unstable Signal Source
If you are measuring from an external source, make sure the signal is clean and has sharp edges. Noisy signals or slow transitions can cause irregular readings.
Timer Overflow and Edge Detection Problems
Timer overflow is another common issue, especially when measuring low-frequency signals. If the period of the input signal is longer than the timer’s maximum count, the counter will overflow before the second edge is captured. This leads to negative or incorrect difference values.
To solve this:
- Use a 32-bit Timer if available, such as TIM2 or TIM5 on STM32F4/F7/H7 series. A 32-bit counter significantly increases the measurable period range.
- Adjust the Prescaler to lower the timer frequency, which extends the maximum measurable time between edges.
- Handle Overflow in Code: If overflow is possible, add logic in the capture callback to detect and compensate for it (as shown in the code section of this tutorial).
Also, make sure the edge detection mode matches your measurement type:
- For frequency → use rising edge only.
- For pulse width → enable both rising and falling edges.
Any mismatch here will lead to irregular or missing capture events.
CubeMX Configuration Mistakes
Many input capture problems can be traced back to CubeMX configuration errors. Even a small mistake in pin mapping or clock setup can cause the entire measurement to fail. Common misconfigurations include:
- Incorrect Pin Selection: Ensure the GPIO pin you select actually supports the desired timer channel and function. Use the Pinout view in CubeMX to verify this.
- Forgetting to Enable TIM Interrupts: If interrupts are not enabled for the input capture timer, the callback function will never be triggered. Check both the NVIC settings and the timer’s interrupt configuration.
- Wrong Clock Source or APB Prescaler: If the timer clock source doesn’t match the code’s assumed frequency, all calculations will be off. Reconfirm the clock tree settings under Clock Configuration.
- Not Generating Code After Changes: If you modify CubeMX settings but don’t regenerate the code, your project might still use the old configuration.
Frequently Asked Questions
This is the most common issue and multiple readers have hit it. At high input frequencies, the HAL_TIM_IC_CaptureCallback() fires so frequently that the MCU has no CPU cycles left for the while(1) main loop — the interrupt handler is executing almost continuously. The fix is to use the callback only to set a flag and store the raw captured values, then move all the frequency/pulse calculation code into the main loop. This way the CPU services the interrupt quickly and returns to the main loop between captures. Increasing the system clock (as commenter "Isa" found — moving to 168 MHz from 16 MHz) also helps by giving the CPU more cycles to complete each interrupt before the next one arrives.
This is a valid concern: since the callback fires for both edges and Is_First_Captured starts at 0, whichever edge comes first is treated as the reference. If the MCU arms the interrupt mid-pulse, the first trigger might be a falling edge, causing the measurement to capture low-time instead of high-time. The robust solution is to read the pin state inside the callback — HAL_GPIO_ReadPin(GPIOx, GPIO_Pin) — immediately after the capture and use that to determine whether to update IC_Val1 (rising) or IC_Val2 (falling). This makes the measurement edge-aware rather than sequence-aware, and works correctly regardless of when the interrupt is armed.
Yes. Most STM32 timers support four input capture channels. Configure each channel independently in CubeMX (channel 1 → pin A, channel 2 → pin B, etc.), start each with its own HAL_TIM_IC_Start_IT() call, and distinguish between channels inside the callback using htim->Channel == HAL_TIM_ACTIVE_CHANNEL_1, CHANNEL_2, etc. Each channel maintains its own capture register, so simultaneous edge detection works correctly without interference between channels.
Duty cycle requires both the pulse high-time and the signal period. Configure the timer to capture both edges as described in the pulse width section. Calculate the high-time (rising to falling edge difference) and the period (rising to next rising edge difference). Duty cycle = (high_time / period) * 100. In practice, you need three captured values: first rising edge (IC_Val1), falling edge (IC_Val2), and second rising edge (IC_Val3). High-time = IC_Val2 - IC_Val1, period = IC_Val3 - IC_Val1. Some STM32 devices support PWM Input Mode (a dedicated timer mode) that measures both automatically using two channels of the same timer — check the PWM Input tutorial for that approach.
The maximum frequency is limited by the timer clock and the minimum measurable period. With a 1 MHz timer clock (prescaler = 90 on a 90 MHz APB1 as in this tutorial), the timer counts once per microsecond — so the minimum measurable period is 2 µs (500 kHz maximum). Using a faster timer clock (lower prescaler) raises the maximum. The minimum frequency is limited by the timer's counter size: a 32-bit timer at 1 MHz counts up to 4,294 seconds before overflowing, giving a theoretical minimum of well under 1 Hz. A 16-bit timer at the same rate overflows every 65.5 ms, limiting minimum measurable frequency to about 15 Hz. For low-frequency signals, lower the prescaler or use a 32-bit timer and reduce the timer clock.
Conclusion
In this tutorial you configured STM32 Timer Input Capture mode using TIM2, connected it to a TIM1 PWM signal, and implemented HAL_TIM_IC_CaptureCallback() to measure both frequency and pulse width. The frequency measurement captures two consecutive rising edges and divides the reference clock by the difference. The pulse width measurement captures a rising then falling edge and converts the difference to microseconds using the same reference clock.
The key things to carry forward: always match TIMCLOCK and PRESCALAR in your code to the actual CubeMX values — a mismatch here produces wrong readings without any error. Use a 32-bit timer (TIM2 or TIM5 on F4/F7/H7) for low-frequency signals to avoid counter overflow. And if the main loop starts behaving strangely at high input frequencies, you are saturating the MCU with interrupts — use a flag in the callback and do the calculation in while(1) instead.
In Part 5 of the Timer Series, we cover Timer Synchronization using Slave Trigger Mode — connecting two timers so one controls the start/stop of another, without CPU involvement.
Download STM32 Input Capture Project Files (STM32F4)
Complete CubeIDE project for STM32F4 — includes TIM1 PWM output, TIM2 input capture configuration, frequency measurement callback (rising-edge mode), and pulse width measurement callback (both-edges mode). Free to download — support the work if it helped you.
Browse More STM32 Timer Tutorials
STM32 Timers (Part 2): How to Measure PWM Input Signal
STM32 Timers (Part 3): How to use the Timer Encoder Mode
STM32 Timer Synchronization: Slave Trigger Mode with CubeMX & HAL
STM32 Timers (Part 6): Timer Synchronization for 3-Phase PWM Generation
STM32 Timers (Part 7): Timer synchronization using Slave Reset mode
Arun is an embedded systems engineer with 10+ years of experience in STM32, ESP32, and AVR microcontrollers. He created ControllersTech to share practical tutorials on embedded software, HAL drivers, RTOS, and hardware design — grounded in real industrial automation experience.
Recommended Tools
Essential dev tools
Categories
Browse by platform









Hii Good afternoon,
I am using STM32F401re nucleo board, for measure the input capture frequency
but in that i am seeing frequency rising edge is not detect by
“IC_Val1 = HAL_TIM_ReadCapturedValue(htim1, TIM_CHANNEL_1);”
this function so value remain 0 as per this code.
please suggest what i should do?
Or can you suggest any other function to read the rising edge from register in Input Capture
my function is
void CaptureCallback(TIM_HandleTypeDef *htim1)
{
if (htim1->Channel == HAL_TIM_ACTIVE_CHANNEL_CLEARED)
{
if (Is_First_Captured==0) // if the first rising edge is not captured
{
IC_Val1 = HAL_TIM_ReadCapturedValue(htim1, TIM_CHANNEL_1); // read the first value
Is_First_Captured = 1; // set the first captured as true
}
else // If the first rising edge is captured, now we will capture the second edge
{
IC_Val2 = HAL_TIM_ReadCapturedValue(htim1, TIM_CHANNEL_1); // read second value
if (IC_Val2 > IC_Val1)
{
Difference = IC_Val2-IC_Val1;
}
else if (IC_Val1 > IC_Val2)
{
Difference = (0xffffffff – IC_Val1) + IC_Val2;
}
else if (IC_Val1 == IC_Val2)
{
Difference = IC_Val2;
}
float refClock = TIMCLOCK/(PRESCALAR);
frequency = refClock/Difference;
__HAL_TIM_SET_COUNTER(htim1, 0); // reset the counter to start
Is_First_Captured = 0; // set it back to false
}
}
}
uint32_t HAL_TIM_ReadCapturedValue(TIM_HandleTypeDef *htim, uint32_t Channel)
{
uint32_t tmpreg = 0U;
switch (Channel)
{
case TIM_CHANNEL_1:
{
/* Check the parameters */
assert_param(IS_TIM_CC1_INSTANCE(htim->Instance));
/* Return the capture 1 value */
tmpreg = htim->Instance->CCR1;
break;
}
case TIM_CHANNEL_2:
{
/* Check the parameters */
assert_param(IS_TIM_CC2_INSTANCE(htim->Instance));
/* Return the capture 2 value */
tmpreg = htim->Instance->CCR2;
break;
}
case TIM_CHANNEL_3:
{
/* Check the parameters */
assert_param(IS_TIM_CC3_INSTANCE(htim->Instance));
/* Return the capture 3 value */
tmpreg = htim->Instance->CCR3;
break;
}
case TIM_CHANNEL_4:
{
/* Check the parameters */
assert_param(IS_TIM_CC4_INSTANCE(htim->Instance));
/* Return the capture 4 value */
tmpreg = htim->Instance->CCR4;
break;
}
default:
break;
}
return tmpreg;
}
Here are both functions for your reference, Please suggest what changes are need.
Thank you.
Hi
When you measure the width- because trigger is both edges, how do you know that the first interrupt is the rising? if duty cycle is NOT 50% as here , if the interrupt is will be due the falling you will measure the low width od the pulse.You have to check the cause to the interrrupt is falling or rising and calculate the 2 width of the signal – the high part and the low part.Is it? Can I know what was the edge while enter the interrupt?
incrivel artigo sobre stm32
can i have your tutorials in just register level based , using HAL and all makes it very convoluted and i guess its not the best practise to do so .
Thank you so much.
I have learned from you.
It is very clear and understandable even for the beginners.
i initially started with this technique, but found that with this model that the interrupts are proportional to the frequency being measured, and you quickly saturate the MPU with interrupts (as you noticed) leaving you with nothing but an interrupt generation machine as the freq of the signal to be measured goes up, with no cycles left for anything else. In my case I am trying to measure the freq of an external input. what i did was use one timer to provide/manage the “gate” for another timer, and CLOCK the second timer with the external freq to be measured. now the interrupt rate is independent of my “unknown” frequency, and i am readily able to measure frequencies over 30mhz, with a gate frequency of 250ms (created by the first timer by linking the second to the first timer). connect the input being measured to the external clock source of the second timer (note- not all STM32 timers allow external clock source). In my case, T3 gates T2, T3 is setup with MasterslaveOutTrig = TRG0_OC1REF and MasterSlaveMode enabled, T2 is setup with CLKSRC=ETRMODE2 and SLAVEMODE=SLAVEMODE_GATED ITR2. in the T3 PeriodElapsed callback, read T2’s counter directly as the frequency
I think I met your issue that jam the interrupts… and agree that alternative is best to measure some high speed tachometer PWM inputs.
unfortunately, I cant fully get your solution in your message.
Hi man, please how do I measure the speed of a bldc motor by capturing the hall sensor signals (H1,H2,H3) on an STM32. Do you mind refering me to a video or link if you have one?
Hi man, please how do I measure the speed of a bldc motor by capturing the hall sensor signals (H1,H2,H3)
Coming from article where the main issue was code getting stuck in the frequency counter loop.
I just wanted to share how I configured my project to get this working in STM32CubeIDE v1.4.0 and STM32F103C8T6 (aka blue pill) board.
I set my clock configuration as follows:
HCLK (Mhz) set to “72”
APB1 Prescaler set to “/4”
resulting in APB1 Timer clocks of 36 Mhz
By the same token I set my parameters as:
Prescaler (PSC – 16 bits value) = 0
Counter Period (AutoReload Register – 16 bits value) = 65535
Code wise on the frequncy calculation changed:
Frequency = 2 * HAL_RCC_GetPCLK1Freq() / Difference;
According to the calculation lowest measureable frequnechy is 549 Hz.
36 * 1000 * 1000 / 65536 = 549.316 Hz
What options do I have if I want to measure signals at 200 Hz? Adjust APB1 Prescaler from “/4” to “/16” seem to do the trick but is the right way to do it?
9 * 1000 * 1000 / 65536 = 137.329 Hz
yes you did it right. As per with this code, you need to reduce the sysclock inorder to measure the lower frequencies
Helo
I tried this code and working fine . But when frequency increase , after about 36kHz the main loop stops to work . When decrease the frequency , main loop begins to work again . But frequency measurement still fine even main loop stop. Do you have any advice ?
what you mean main loop stops ?
Inan want to say …. what ever he writes in while loop thats not working when frequency increases …. it is because when frequency increase callback function interrupts increases with it and cpu do not get extra time to perform while loop code out of interrupt … when decrease frequency cpu get out of interrupt for some time and get some extra time to run while loop code also …. if there is any way to fix it im also interested to know
i don’t think it will work. One way you could try is instead of putting the entire code in the callback, just use some flag, and put the code in the while loop.
maybe that could work
I’m facing a similar problem, I can read up to 115Khz, but anything high causes my stm32 to stop work properly, I’m also using serial com and the board stop to receive RX but still send TX.
Well that may be because the uart baud rate could be 115200.
i saw that if i use internal crystal and low working frequency(16 Mhz) at the cubemx , main loop stop to work at high frequency measures like 36 khz . I used external crystal and set max speed(168 Mhz) . now it is working perfect. thanks
thats great 😀😀 … always remember to put top gear 🚀🚀of ur hardware before exicute anything 😁😁😁
aswdf
Thanks for this example, works fine.
Thanks, this tutorial was super useful to get the capture inputs working. Showing both the code and cube mx configuration did the trick.
Hello! Thank you for your tutorial! Could I ask what to do if the rising edge will come in two channels at the same time?