cancel
Showing results for 
Search instead for 
Did you mean: 

Count external pulses

peterka
Associate II

I want to count external pulses for one second.

On STM32F030 / HAL-Lib I did not find

  • atomic read/reset counter
  • capture by a second timer did not work, thoug I studied well and tested a lot how to config it by STM32CubeIDE

Is there any example for a highly accurate count of external pulses by a tim (timers/capture/compare/pwm)?

Thanx, Peter

15 REPLIES 15

> On STM32F030 / HAL-Lib I did not find

If you *want* to do something, then don't look at some random library, read the real manual.

> atomic read/reset counter

Are you talking about the Timers?

There is no such operation (there is something resembling that, but I don't recommend to use it). But you don't need that: simply subtract values of consecutive readout (taking into account the registers' width, a.k.a. modulo arithmetics) in software.

> Is there any example for a highly accurate count of external pulses by a tim (timers/capture/compare/pwm)?

What do you mean by "highly accurate"?

Do you want run one timer as counter of external pulses, and sample its count by an other timer serving as a regular timebase?

If yes, at this point, I assume you know how to enable clocks in RCC and how to set pins in GPIO.

You need to use TIMx_ETR pin in the first timer (only a few timers have it) and set it count from that input, i.e. External clock mode 2, by setting TIMx_SMCR.ECE and enable counting by setting TIMx_CR1.CEN (at that point, you can check if it counts appropriately, in debugger; there's no point in changing TIMx_PSC/TIMx_ARR from their defaults here). Steer the second timer's TRGO (described below) as TRGI in this timer, by selecting appropriate ITRx in TIMx_SMCR.TS. Set input capture on the trigger, for example on CH1, by setting TIMx_CCMR1.CC1S to 0b11. Enable capture by setting TIMx_CCER.CC1E. Optionally, set interrupt on capture by setting TIMx_DIER.CC1IE and enable the given interrupt in NVIC, writing an ISR with appropriate name. (As a "higher level", you can use DMA to pull captured values).

Set TIMy_ARR/TIMy_PSC of second timer to provide the required timebase and set it to generate TRGO from Update by setting TIMy_CR2.MMS=0b010. Enable it by setting TIMy_CR1.CEN.

Then, in runtime, for polled operation, poll the first timer's TIMx_SR.CC1IF, and if set, read out TIMx_CCR1 and store. You don't need to clear TIMx_SR.CC1IF, it's cleared automatically by reading out TIMx_CCR1 (although you can if you know how to). Subtract two consecutive readouts for the difference.

When using interrupts, the procedure is the same, but I recommend to start with polling.

JW

S.Ma
Principal

As JW wrote, there are different hw methods that can be used around timers. Are you going next measure duty cycle? What frequency range? Are there time periods without pulses? What precision? Should it work in any low pwer modes?

Slh
Senior

I think using PA12 in TIM1 with ETR2 mode as External Timer Clock Input could be suitable for your work.

peterka
Associate II

Thank You. This is what I did / tried and I did read the original manuals.

I thought that these tims are so advanced, that they support counting in a very flexible way, saving CPU performance a lot ... and found out that they can do very well advanced ways of capture / compare / pwm ... but counting does not seem to be their favorite.

I want to do simple counting pulses during a periode of 60 seconds, with a resolution from 0.1 Hz to 100kHz.

Accurate in meaning of not loosing any pulse while counting.

It would be nice to use one timer to control a second counter (timer) to read the counted external pulses into the capture-register, reset the counter (timer), send an interrupt for the reading of the counts. But this was not possible.

Thank for Your hint. I will implement a read of the counter (timer) every second and calculate the difference regarding the wrap-around. That is a good solution as well, costing a bit more CPU-cycles.

Thanx, Peter

> It would be nice to use one timer to control a second counter (timer) to read the counted external

> pulses into the capture-register, reset the counter (timer), send an interrupt for the reading of the counts. But this was not possible.

This is exactly what I described above, except the "reset the counter (timer)".

Even that is possible, but I don't recommend it, as there's an inevitable and undocumented lag between the capture and reset. Most users ignore that lag and its consequences, and for most applications it's OK indeed, but my personal notion of "precise" is different than that. And subtracting two values is not that expensive in a 32-bit multimegahertz processor.

Here's how: set TIMx_SMCR.SMS to 0b100 for Reset mode. Done.

Do things one at a time. Learn to walk, before trying to run.

Read the TIM chapter in RM. Read it again and again. And ditch Cube, now.

JW

peterka
Associate II

I have been trying and reading for two entire days, tried the reset-mode as well ... and gave up. I never was able to generate a capture-interrupt.

But when there is a glitch, then anyway I`ll implement it with a bit more software.

> I have been trying and reading for two entire days,

I have been trying and reading for 25 entire years. Keep trying and reading. Do one thing at a time. Do you have a timer which counts the external pulses, yet? That's the first step.

JW

peterka
Associate II

Yes shure.

Counting on external pulses by a timer/counter and generating interrupts by a second timer did work quickly. I successfully tested a lot of other stuff as well , just by curiosity. But triggering capture by a second timer and generating interrupt on capture did not work in my test-projects.

peterka
Associate II

For the timers on stm32I412kb I did not find any overrun- and/or underrun-flags, nor interrupt-flags for this purpose.