A basic frequency counter is a gate coupled to a counter enable/read/status register.
The SysTick is clocked by the CPU clock, so you could use it to get the gate generated.
Then use a 24 bit UDB counter, a 20 bit basic counter in Utility logic component library, or a
combination of 7 bit counter and software counting its overflow, since that will be relatively low
What is the range, resolution ( I see the 1 Mhz), and accuracy of F you want to measure ?
Since you solved the first part of your project by introducing a crystal driven clock, the rest will be easy enough. Instead of counting interrupt-driven the single pulses, which would consume a lot of MIPS at 1 MHz, you can use a counter and an interrupt when the counter overflows. Both counters, counting the pulses and counting the number pf periods could use this combination of software and hardware method without getting busted the amount of resources availlable.
Nonetheless you may use the Systick-timer and generate an interrupt when it counted down. Have a look into the System Reference Guide (accessible from Creator Help-menu) chapter 15.
When counting low frequencies a reciprocal counter is more practical.
Attached info, more than you want to know about counters.
AN52-1 Fundamentals of Time and Frequency
AN200-3 Fundamentals of Time Interval Measurement
AN200-4 Understanding Frequency Counter Specifications
AN-1289 Science of Timekeeping
AN52-1 Fundamentals of Time and FrequencyAN200-3 Fundamentals of Time Interval Measurementhttp://www.google.com/url?sa=t&rct=j&q=&esrc=s&source=web&cd=1&ved=0CCAQFjAA&url=http%3A%2F%2Fwww.leapsecond.com%2Fpdf%2Fan200-3.pdf&ei=sp6pVOqHL8yfgwSlxIHwBw&usg=AFQjCNERngBpwCsPHkaobtnn_gVsr9XOeQ&bvm=bv.82001339,d.eXYAN200-4 Understanding Frequency Counter Specificationshttp://www.google.com/url?sa=t&rct=j&q=&esrc=s&source=web&cd=1&ved=0CCwQFjAA&url=http%3A%2F%2Fwww.leapsecond.com%2Fpdf%2Fan200-4.pdf&ei=C5-pVPirNsKVNv-AhKgB&usg=AFQjCNHmildQb5hs3se65lD1nrycOqhjDw&bvm=bv.82001339,d.eXYAN-1289 Science of Timekeeping
Hi Dana, Bob,
Thank you, you've given me a lot of info, which will take a bit of digesting -- I havn't yet looked at all the links you've given to counters.
Anyway, to answer your first questions:
Range is 7Hz to 100kHz.
I'd like accuracy of one part in 50000 at all frequencies. This is probably well beyond what my analog circuitry can achieve in stability, but I have set that as a target.
A 1MHz counting clock will give about 143000 counts at the low end, which is OK.
At the high end I'll get 10 counts per period, so will need to count for >5000 periods to get the resolution I want.
[ You mention that a reciprocal counter is more practical for low frequencies. If I understand correctly that is what I'm doing -- I am measuring the input signal period and converting to frequency in the processor. ]
You both seem to suggest using a modest number of counting stages in hardware, and capturing its overflow to continue the count in software. This seems to me to be the simplest way, and if I understand correctly would not involve using SysTick timer.
Now my problem is: How to get the overflow pulse to the processor ?
I think it will need to be an interrupt, so should I use the Interrupt Component ?
(Up til now I have only used the Status Register Component to capture data)
The Interrupt Component datasheet gives some basic API info on coding, but a more complete example would be very helpful. I have looked through the example projects on the PSoC Creator Start page, but cannot find anything that demonstrates Interrupts. I wonder if you can give me a link to an example?
Many thanks again. Regards, Ken.
Using SysTick and the basic counter set at 20 bits or greater you will
not have to count rollover pulses to effect cascade, the counter is big
enough to capture largest value.
Two ways to implement ISR, one w/o using ISR component, look at your
component (like a counter/timer) ISR file (your enabling an interrupt
in its global properties or with API call creates this file ) you will see
placeholders for definitions/variable declarations at top of file and another
in the ISR place itself. Putting your code there prevents compiler from
overwriting that code on rebuilds.
The other way is using ISR component, that creates its own file, or you
can create C ISR, shown in ap note.
http://www.cypress.com/?rID=38267 AN54460 - PSoC® 3, PSoC 4, and PSoC 5LP Interrupts
Remember to declare variables volatile used in ISR.
If you declare a value, like a global in main.c -
uint32 volatile myfreq = 0;
And then inc that in ISR which is located in another file other than main.c, you
have to declare that variable as external in that file -
extern uint32 volatile myfreq;
I am using an 18 bit basic counter to count the 1MHz pulses. This is big enough.
For counting the number of signal pulses at higher frequencies I reckon I should use the ISR component to allow counting in software. I have downloaded app note AN90799 on Interrupts, and this gives very comprehensive guidance plus examples, so I think I should be able to work out what to do from that. Thanks for directing me to that app note.
Your further notes in your reply are helpful, and suggest it should not be too hard.
So now I will go away and get on with it, although I might need to come back again if I get stuck !
Many thanks again. Regards, Ken.
If you are trying to run your ISR at a very high frequency you will eat up
all the machine MIPS. I can't speak to a fixed value, but << 100 Khz
would be prudent I think. Use HW for >> 100 Khz.
My plan is to have a few stages of division in hardware first, so that the frequency I will be counting with interrupts is about 1kHz ( ~1 pulse per mS). Do you think that will be OK ?
You can find PSoC3 implementation of the reciprocal counter by "HLi" here (FreqMeter bundle):
And explanaltion here:
and demo here:
I have just downloaded the freq counter by "HLi".
This is a really good starting point for my project.
Also, I was unaware of Logisim, so have downloaded that as well.
It seems to be a useful and easy to use simulator. Up til now I have used the free version of ModelSim from Mentor, but this is really intended for FPGA design, so is not well suited to general purpose logic simulation.
Many thanks for posting these links for me.
As the mentioned author, I should add some corrections:
- the PSoC5 / PSoC3 implementation in that article is not a reciprocal counter, but a simple gated one
- (For that, the earlier articles show the PSoC4 implementation, so the OP might want to look at that)
- the introduction OTOH is about a reciprocal counter, that I implemented in a CPLD back then.
I have an implementation of a reciprocal frequency meter on a PSoC5 somewhere, since this was the intended next step in my PSoC series. But I never came around to write that part :(
Also, its difficult to fit that in a PSoC4. There are just enough UDBs for two 16bit counters. One could use the fixed-function-block, but I doubt they can be chained so easily to get two 32bit counters. Maybe I can get around that somewhere in the future...
Thanks HLi for your correction note, but no problem, I am now back on track with my frequency meter project.
As an aside, Logisim is straightforward and easy to use, but has one major drawback -- no built-in waveform viewer.
Now the rest of this reply is on a slightly different topic, but still but related to pulse width/frequency measurement. So I am wondering if I should start a new thread? I will put my question here for the moment, as follows:
I've had further thougts on how to implement a reciprocal fequency counter, using SysTick Timer.
Set number of ticks to the maximum, eg, TICK = 0x00FFFFFF.
On a rising signal edge, use interrupt to enable the SysTick timer with the API SysTick_Config(TICKS).
On next rising signal edge, use another interrupt to read the SysTick Current Value Register.
The difference from max will be an accurate measure of length of one signal pulse.
(Assuming an accurate external xtal)
BUT, my problem is: How do I read the SysTick Current Value Register?
I have read the Knowledge Base Article "Using the SysTick Timer in PSoC® 4 – KBA91374".
It lists the SysTick Timer Registers, including Current Value Register, and says that
"...in the PSoC 4 family, these registers can be accessed using a pointer to the structure
defined in the core_cm0.h file."
This implies that what I suggest can be done, but how do I go about writing the code?
I've had a look at the core_cm0.h file, but it is well beyond my very limited understanding of c code.
I've also had a look in the Cortex M0 User Guide, but that is equally unhelpful for a code rookie.
Can you offer advice ? Many thanks.