2017-03-23 12:24 PM
STM32F437 processor
I have no experience using the stm32 timers with DMA so I wish to solicit suggestions before banging my head against the wall.
I have set up a counter using an ISR to count pulses (RPM) and it works quite well for low speed and extremely low speeds. If the speed is real slow the timer overflows and triggers an interrupt. I just count the overflows until I get a real trigger event and shift the overflow count << 16 and add the new count. While this method works good at low speed it become a processor hog at higher speeds since there is an interrupt for each pulse, plus since I am using an OS (Micrium III) the isr is twice removed, so to speak. A system with one magnet or tit per revolution is fine up to a few thousand RPM. But some systems I will encounter will count flywheel teeth (perhaps 460 per revolution). Or it might be a 60000RPM turbo with 6 pulses per revolution.
I am not experienced with using a timer and DMA together but I could see how it might allow me to collect a group of samples without an ISR. I have found some ST.com examples of using timers with dma but they are for pwm and transfer from memory from peripheral and don't seem too use DMA interrupts.
Another scheme would be to count pulses within a time window. If I determine how to setup and gate it. I may be able to use some timers together but not in cascade as RPM1 is fed to TIM3 ch2 and TIM4 ch1 while RPM2 is fed to TIM1 ch 1 and TIM9 - ch 1.
So while I am figuring out how to use timers and DMA together I thought I would ask for articles or examples where you have measured pulses at rates up to 36000 pulses per second. I will have a look up table for normal operating speed and pulses per revolution (could actually be 0.5 if timing off the camshaft) so that will at least help with the prescaler setup.
Thanks,
JH2017-03-23 02:13 PM
DMA is going to pull a singular value, not fetch a collection of timers at different memory locations.
Each timer has a single counter.
Most of the timers permit an external clock/count input, 16-bit would hold 64K counts. Typically you could read on 1Hz or 1KHz ticker. ie integration of counts over defined period. DMA could read on defined period if interrupt latency a bit sketchy, or you could latch into a CCRx channel register.
Sounds like you are doing a timebase (period measurement), a 32-bit TIM (TIM2) could free run at a reasonable pace and have a longish wrap time. CH1-4 could be used to timestamp inputs. Inputs can be decimated with a prescaler (1, 2, 4 or 8). ie trigger every 8 counts, period measurement now for 8 cycles. You could get DMA to read TIM2->CCRx into a larger buffer to decimate interrupt loading, and deal with high frequency inputs.
2017-03-23 03:40 PM
Thanks for posting, but (there's that word again) I don't quite follow. I understand about the prescaler. What I currently do is use channel one to count at a 1MHz rate (as a starting point). Then when my external event causes an interrupt, CCR1 is saved and the counter is reset. So I have a time stamp for the events but they come too often for using an ISR.
Since the external events come in through TIM4 channel 1 how would I use 2-3 to record timestamps?
Also I have thought of another possible scheme. Timer S would simply count the external events. It would count events for time window controlled by timer (or channel?)M. At the end of the time window the count would saved off. A DMA couold be involved but if the window is a reasonable time length an ISR might suffice.
Thanks again Clive for taking the time to read my wordy posts.
John
2017-03-23 04:38 PM
You may want to use the timer as a counter, which in the RM is hidden under 'external clock'.
JW
2017-03-24 03:23 PM
I'm going to sit and digest this and the other info you've supplied.
As a general rule I don't think I'd use Input Capture with a reset (or PWM Input basically), The input prescaler would allow the measurement of up to 8 periods. And I would delta measurements from one IRQ to the next. The delta would be 1/8 th micro-second ticks, if maximal timer clicked at 1MHZ, and we prescaled the input. But you'd get 1/8th of the interrupt loading.
Now PWM Input would allow you to read the most current Freq/Duty from the CCR1/CCR2 registers at your leisure, with not interrupts. You could check them every 200ms
Then for the External Count mode, this interrupts every 100 ticks, I think I'd use maximal count here
I don't think I can wire internally, be if you had spare pins you could have a sample/epoch pulse on one of the other TIM channels to latch the TIMx->CNT value into the TIMx->CCRx.
Alternatively we could get another TIM as a timebase, which would set the sample rate at 200ms (say) and it would trigger a DMA of the TIMx->CNT into a 10 element array, and interrupt at each half (1Hz) where you could inspect the last 5 counts. Without tracking the phase of the count, you could do ((array[4] - array[0]) * 60 * 5) / 4 to get RPM (assuming 1 pulse per rev, quick back of the envelope computation, pulse count in 800ms, assuming timer doesn't wrap in 1 second, so 65.5 KHz ceiling)
I'll mock something up tonight
2017-03-25 09:07 AM
If you only want to count pulses, just use SPI SCK input pin, configure the SPI as slave. In 16 bit mode, you get interrupt at 1/16th the initial frequency. Plug a DMA in cycling buffer and it will be possible to get to khz frequencies. The SPI should be able to accept input frequency up to SYSCLK/4
2017-03-25 12:05 PM
Thanks for the idea but I have had no success getting DMA to do anything, with any peripheral. But it sounds feasible.
Actually I did not know you count SPI clock pulses but it sounds interesting. If you see any examples of this please pass them along to rest of us.
Thanks again,
JH
2017-03-25 12:23 PM
Alternatively, use a timer in external clock source to count pulses directly.
ETR or Channel 1 or 2 as clock input. Please also note that timers have a special feature to XOR CC1, 2, 3 (triple phase) prior to count.
2017-03-25 03:09 PM
John and I have been discussing this off-board, I have demonstration code with the DMA triggered by one TIM, sampling the TIMx->CNT register of another. The mechanics of this are reasonable straight forward, but the STM32 hardware has a lot of specific requirements, and it is very sensitive to exact alignment of all settings. ie It is very easy not to have success