STM32 Counter Mode Example – Frequency Counter | Timer In Counter Mode

Previous Tutorial Previous Tutorial Tutorial 14 Next Tutorial Next Tutorial
STM32 Timers – STM32 Counter Mode LAB
STM32 Course Home Page ????

 

STM32 Frequency Counter Project - Timer Module Counter Mode Frequency Counter

 

In this article, we’ll be discussing the timer module operation in counter mode (STM32 Counter). How to configure a timer as a counter, and what are the possible configuration options. And we’ll do a couple of practical LABs, first of which is a basic digital counter and the second one is a frequency counter mini-project. Let’s get into it!

[toc]


   Required Components For LABs   

 

All the example code/LABs/projects in the course are going to be done using those boards below.

QTY Component Name ???? Amazon.com ???? eBay.com
2 BreadBoard Amazon eBay
1 LEDs Kit Amazon Amazon eBay
1 Resistors Kit Amazon Amazon eBay
1 Capacitors Kit Amazon Amazon eBay & eBay
2 Jumper Wires Pack Amazon Amazon eBay & eBay
1 9v Battery or DC Power Supply Amazon Amazon Amazon eBay
1 Micro USB Cable Amazon eBay
1 Push Buttons Amazon Amazon eBay

★ Check The Full Course Complete Kit List

Some Extremely Useful Test Equipment For Troubleshooting:

Affiliate Disclosure: When you click on links in this section and make a purchase, this can result in this site earning a commission. Affiliate programs and affiliations include, but are not limited to, the eBay Partner Network (EPN) and Amazon.com.


   STM32 Counter Mode LAB Preface   

 

As we’ve discussed in an earlier tutorial, the timer modules can operate in counter mode. Where the timer gets clocked from an external source (input pin) and it counts the number of pulses. However, STM32 timer modules do have multiple modes for the counting mode itself. Here is a brief description for each of them, but at the end of the day, we’ll be using the up-counting mode.

1  Up-counting Mode

In up-counting mode, the counter counts from 0 to the auto-reload value (the content of the TIMx_ARR register), then restart from 0 and generates a counter overflow event. An Update event can be generated at each counter overflow or by setting the UG bit in the TIMx_EGR register (by software or by using the slave mode controller).

2  Down-counting Mode

In down counting mode, the counter counts from the auto-reload value (the content of the TIMx_ARR register) down to 0, then restarts from the auto-reload value and generates a counter underflow event. An Update event can be generated at each counter underflow or by setting the UG bit in the TIMx_EGR register (by software or by using the slave mode controller).

3  Center-Aligned Mode (Up/Down)

In center-aligned mode, the counter counts from 0 to the auto-reload value (the content of the TIMx_ARR register) – 1, generates a counter overflow event, then counts from the auto-reload value down to 1 and generates a counter underflow event. Then it restarts counting from 0. In this mode, the direction bit (DIR from TIMx_CR1 register) cannot be written. It is updated by hardware and gives the current direction of the counter.

 


   STM32 Counter LAB9 Objectives   

 

LAB Number 9
LAB Title Counter Mode – Basic Digital Counter
  • Configure the general-purpose timer (TIM2) to operate in counter mode
  • Set The Preload value to 20, so the counter overflows after 20 ticks and generates an interrupt
  • Set The Timer input GPIO pin
  • Configure the USART1 module to print the counter ticks value for monitoring it
  • Print special message within the ISR routine (counter overflow event) to check that the interrupt firing and handling functionality is being done properly

 


   STM32 Timer – Counter Mode LAB Config.   

 

Step1: Open CubeMX & Create New Project

Step2: Choose The Target MCU & Double-Click Its Name

STM32 CubeMX Choose The Part Step

Step3: Configure Timer2 Peripheral To Operate In Counter Mode

Note that now the clock source is an external pin (timer2 input pin ETR2) which is highlighted as A0 as you can see. We can also configure a digital filter for this input channel to reject noise due to switch bouncing. The filter value can range from 0 upto 15. And last but not least, the edge selection for the counter. I want the counter to count on each rising edge of the input pin.

I’ll also enable the auto-reload function and set the upper count limit to 20 “the Preload value”. Now, whenever the counter counts 20 ticks, it overflows and generates an interrupt signal!

STM32 Counter Mode Example HAL Code - Timer Module Counter Mode

Step4: Enable The Timer Interrupt Signal In NVIC Tab

STM32 Counter Mode Interrupt Example HAL Code - Timer Module Counter Mode Frequency Counter

Step5: Configure USART1 Module To Operate In Async Mode With 9600bps

STM32 Counter Mode Example HAL Code - Timer Module Counter Mode Frequency Counter

Step6: Set The RCC External Clock Source

STM32 RCC External Clock Selection CubeMX

Step7: Go To The Clock Configuration

Step8: Set The System Clock To Be 72MHz Or Whatever You Want

STM32 Clock Tree Configuration CubeMX

Step9: Name & Generate The Project Initialization Code For CubeIDE or The IDE You’re Using

 

Then, open the project in the IDE you’re using. And head over to the main.c file. So we can start writing the application code and have a look at the initialization code generated by the STM32 CubeMX tool.

 


   The Application Code In CubeIDE   

 

Here is the generated initialization code in the main.c file

Now, the application we’re currently developing is to repeatedly read the Timer2 ticks count and print the vlaue via UART1 as a string to the terminal for monitoring. And whenever it reaches 20, an interrupt gets fired. And it’s the same interrupt signal for the previous tutorial and it’ll have the same handler function.

So, open the stm32f1xx_it.c file to find the timer interrupt handler, which is this function TIM2_IRQHandler(). Hover over the HAL_TIM_IRQHandler() function and right-click to navigate to its implementation.

After navigating to the timer interrupt handler routine, you’ll find the following implementation. In this code, we’re searching for the callback function’s name that gets called when an overflow interrupt occurs. You can notice that all sources share the same interrupt signal output compare match, overflow, input capture, etc.

Now, we’ve got the callback function’s name that gets called whenever timer overflow occurs. It’s HAL_TIM_PeriodElapsedCallback(). So, we’ll write our own implementation for it in the application file (main.c). And a mention-worthy point is that you also have to enable (start) the timer so it gets clocked and starts counting, otherwise it’ll remain IDLE.

Full LAB Code (main.c)

 

Build & Flash The Code And Let’s Test The Results!

 

Note: it’s worth noting that you have to start the timer in interrupt mode so it gets clocked and fires an interrupt signal on overflow and so. Otherwise, the timer will not work at all.

 


   Prototyping & Testing   

 

Step0: Refer To The Blue Pill Board Schematic & Pinout

Blue pill pinout

Step1: Connect The ST-Link To The USB Port & SWD Pins On Board

Step2: Click The Debug Button To Compile The Code & Flash It To The Board & Start A Debugging Session

Step3: You Can Stop The Debugging Session Or Keep It Going. But You Need To Restart The MCU Once To Run The New Application At The Booting Process.

Download CounterMode LAB9 Project

The Results For This LAB

Testing Board

Push-Button -> A0

USART1 -> USB-TTL Pins

STM32 Counter Mode Interrupt Example HAL Code - Timer Module Counter Mode Frequency Counter

Test Video

Note: even with setting the input channel filter to its maximum value, the pin is still capturing some bouncing noise from the push button and the counter’s value occasionally jumps over by some ticks. So, it may need an external RC filter on the input pin or any means of hardware debouncing.

 

 


   STM32 Frequency Counter – LAB10   

 

LAB Number 10
LAB Title Timer Module In Counter Mode – Frequency Counter Mini-Project
  • Set up TIM2 as a counter and hook its input pin to the signal source
  • Set up TIM3 as the measurement timer, and it should overflow every 50mSec (or any time interval you choose)
  • Count how many clock cycles in the ISR of TIM3 by reading TIM2 counter ticks and by multiplying this value by 20, you’ll get the actual signal frequency.
  • Configure USART1 in Async mode with baud rate = 9600bps
  • Print the calculated frequency to the serial port terminal

 


   STM32 Frequency Counter Project LAB   

 

In this LAB, our goal is to build a system that measures the digital signal’s frequency using the timer module in counter mode. The basic idea behind this technique is to set up another timer in timer mode and get it to overflow each specific time interval. Let’s say 50mSec for the sake of this experiment. Each 50mSec, the timer overflows and fires an interrupt signal, and in the ISR, we’ll check the ticks count in the counter register. This value is the number of complete signal cycles every 1/20 of a second. Therefore, the actual signal’s frequency is the counter CNT value multiplied by 20.

STM32 Counter Mode Interrupt Example HAL Code - Timer Module Counter Mode Frequency Counter Project

Note: this is not the best way to measure frequency. However, it should be a proof of concept and give you an idea for how to cooperatively set up multiple peripherals to do a specific task. The downsides for this technique will be mentioned at the end of the LAB after seeing the final results.

Step1: Open CubeMX & Create New Project

Step2: Choose The Target MCU & Double-Click Its Name

Step3: Configure Timer2 Peripheral To Operate In Counter Mode

STM32 Counter Mode Example - Timer Module Counter Mode Frequency Counter

Step4: Configure Timer3 Peripheral To Operate In Timer Mode (Tout = 0.05 sec)

STM32 Timer HAL Interrupt Formula - STM32 Timer Equation

FCLK is 72MHz, I’ll use Prescaler of 100. So, by solving for the preload register value. It turns out to be 36000. Therefore, we’ll write this value in the configurations tab.

STM32 Frequency Counter Example - Timer Module Counter Mode Frequency Counter

Enable Timer3 interrupts from the NVIC control tab.

Step5: Configure USART1 Module To Operate In Async Mode With 9600bps

Step6: Set The RCC External Clock Source

STM32 RCC External Clock Selection CubeMX

Step7: Go To The Clock Configuration

Step8: Set The System Clock To Be 72MHz

Step9: Name & Generate The Project Initialization Code For CubeIDE or The IDE You’re Using

 

Here is The Application Code For This LAB

Download The Frequency Counter LAB10 Project

 

The Resulting UART Messages Can Be Decoded By A DSO

As you can see on my DSO screen, the decoded message shows 2020Hz for a 2kHz signal which is pretty close.

STM32 Frequency Counter Example - Timer Module Counter Mode Frequency Counter Project

 

The Resulting UART Messages On Serial Port Terminal (Test Video)

 

My Comments On This LAB Results

The error (drift) in the frequency measurement is nearly 1% of the actual value. It’s not a constant flat rate, so we can compensate for it easily in code. And also the nature of the error suggests that it’s repeatable and can stem from a couple of reasons. First of all, the timer interrupt (every 50mSec) is an asynchronous signal. It arrives in no sync with the input signal, so a small drift in measurement is to be expected.

Another point is the interrupt latency can also contribute to a slight increase in the ticks count. And clearing both TIM2,3 at the end of ISR can help a little bit. We can actually eliminate this error percentage by some calibrations. However, there is and there will be a lot of limitations for this technique. The timer period (50mSec) defines the minimum allowed input signal that could be detected and measured.

So, as I’ve said earlier, it’s a good proof of concept and went successfully. But in the next tutorial, we’ll discuss the ICU (input capture unit) and how to set the timer module up so it can be used to detect external events in a very precise way. It’s the proper way to perform such measurement tasks and one of the most reliable options.

 


 

 

Stay tuned for the upcoming tutorials and don’t forget to SHARE these tutorials. And consider SUPPORTING this work to keep publishing free content just like this!

 

Previous Tutorial Previous Tutorial Tutorial 14 Next Tutorial Next Tutorial

 

Share This Page With Your Network!
Join Our +25,000 Newsletter Subscribers!

Stay Updated With All New Content Releases. You Also Get Occasional FREE Coupon Codes For Courses & Other Stuff!

Photo of author
Author
Khaled Magdy
Embedded systems engineer with several years of experience in embedded software and hardware design. I work as an embedded SW engineer in the Automotive & e-Mobility industry. However, I still do Hardware design and SW development for DSP, Control Systems, Robotics, AI/ML, and other fields I'm passionate about.
I love reading, writing, creating projects, and teaching. A reader by day and a writer by night, it's my lifestyle. I believe that the combination of brilliant minds, bold ideas, and a complete disregard for what is possible, can and will change the world! I will be there when it happens, will you?

Leave a Comment