High Frequency Counter with a 10Mhz PIC

Thread Starter

adam555

Joined Aug 17, 2013
858
When I did those measurements I had the oscilloscope probe next to the output and there was nothing else connected.

In any case, even with that issue, I found a way to get the PIC reading up to 3.2Mhz by tunning the prescalers of both timers. I think it will probably go higher than that 3.2Mhz, but that's the maximum I'm getting out the MAX038 with the current configuration; so I can't verify it.

The only problem is that now I lost resolution in the lower ranges. The websites I mentioned above deal with this problem by adjusting the prescaler automatically depending on the frequency; but since I have the PIC also controlling the frequency range of the MAX, I'm currently adding the code to change the prescaler every time a different range is selected; and this way I don't need to have it constantly setting and calculating the prescaler.
 

BobTPH

Joined Jun 5, 2013
8,943
I don't think you have understood what others are saying about using the asynchronous TIMER1.
I was wrong. The built-in pre-scaler is asynchronous, so you can get to higher frequncies. However, data sheet for your PIC states that the shortest detectable period for Timer0 is 20 ns (assuming 50% duty cycle), which translates to 50MHz. If duty cycle is not 50%, then it's less than 50MHz.

However, the timer's sampling rate is 4MHz if you run your PIC at 8MHz (2MIPS), so at the very best you can detect after-prescaler frequencies up to 2MHz (in practice it's about 1.2MHz or so). Multipled by 8 (1:8 prescaler), this gives you about 10MHz. To get full theoretical 50MHz you will need at least 1:64 prescaler.
No, you can easily count up to 50MHz.

You use the 1:8 prescalar and then timer1 will overflow after 65536 * 6 = 524288 clocks. If you simply count for 1 second, you will get 95 such interrupts if the input frequency is 50MHz. On each interrupt you add 524288 to the count. When the one second is up, you add the value of TIMER1 * 8, and this is your frequency. The resolution will be 16 counts.

Bob
 

Thread Starter

adam555

Joined Aug 17, 2013
858
I don't think you have understood what others are saying about using the asynchronous TIMER1.
If you are referring to me... well, I agree.

To be honest, when I did that code last month I didn't know anything about all this -barely knew anything about PICs-, so I got it working by trial and error, and without making a single calculation. Furthermore, when I picked it up again this week, and adapted it to the function generator -and to a different PIC- I also kind of messed up between timer0, timer1 and their respective prescalers. And instead of starting from scratch and calculate everything, I kept working over and modifying the original code.

No, you can easily count up to 50MHz.

You use the 1:8 prescalar and then timer1 will overflow after 65536 * 6 = 524288 clocks. If you simply count for 1 second, you will get 95 such interrupts if the input frequency is 50MHz. On each interrupt you add 524288 to the count. When the one second is up, you add the value of TIMER1 * 8, and this is your frequency. The resolution will be 16 counts.

Bob
It's working fine now -though I have no means to test it over 3.5Mhz- but I'll give it a try the way you have just explained it. Thanks for the help.
 
Last edited:

NorthGuy

Joined Jun 28, 2014
611
No, you can easily count up to 50MHz.
I was talking about Timer0, which OP is using. Timer0 has asynchronous pre-scaler, but is, in itself, synchronous. Timer1, even though can be completely asynchronous, can only detect periods 60ns and above (unlike Timer0, which can do 20ns) - this is according to the data sheet for PIC6F88 (page 180). Which means that the highest frequency you can count with Timer1 is 17MHz. If you're after 50MHz, you have to go with Timer0.
 

Thread Starter

adam555

Joined Aug 17, 2013
858
Yes, I'm currently using Timer0 for the input signal (as a counter), and Timer1 as a timer.

I did it this way because it's the way I saw it on the websites I mentioned and also on the Microchip PDF that jjw linked above; though their PICs probably have different specs.

17Mhz would be good enough for this project.
 

BobTPH

Joined Jun 5, 2013
8,943
Ah, I missed that, I thought the 50MHz limit was for timer 1.

I still see no problem with counting up to the highest frequency that the prescaler can handle. The only thing you lose is precision, because you cannot read the prescaler.

Lets say you set the prescaler to 1:256. Now, with a 50MHz input you will get 195312 counts per second and ~763 interrupts per second. If you accurately time the interrupts in one second you get a resolution of 1/763 or 0.13% That is way, way better accuracy than the 1% internal clock.

Of course, you get lower resolution if you want to count a shorter period and get faster updates, but some of that can be regained by lowering the prescaler. The limit is when the time between interrupts becomes too short.

Bob
 

NorthGuy

Joined Jun 28, 2014
611
I still see no problem with counting up to the highest frequency that the prescaler can handle. The only thing you lose is precision, because you cannot read the prescaler.
Since the timer (Timer0) itself is synchronous, it only samples twice per cycle. If PIC's clock is 8MHz (2MIPS), then it samples at 4MHz, which is 250ns between samples. If you feed 50MHz (10ns pulses) to the pre-scaler and use, say 1:1 pre-scaler, there will be 25 pulses from the pre-scaler to the timer during the 250ns period between samples. All these pulses will go undetected, so timer will not be able to count 50MHz. To make sure all pulses get detected at 250ns sampling rate, you need pulses that are at least 250ns long. Otherwise, a pulse can slip between samples. Therefore, you wuld need at least 1:32 (better 1:64) pre-scaler to reasonably count 50MHz. Anything below that will not work. Of course, 1:256 will work too.
 

BobTPH

Joined Jun 5, 2013
8,943
Agree, you need to make sure the prescaler does not overflow more than once in an instruction cycle. At 50MHz in and 2MHz instruction rate, that means the presclaler has to be at least 25:1 to catch each presscaler overflow.

Bob
 

takao21203

Joined Apr 28, 2012
3,702
Agree, you need to make sure the prescaler does not overflow more than once in an instruction cycle. At 50MHz in and 2MHz instruction rate, that means the presclaler has to be at least 25:1 to catch each presscaler overflow.

Bob
If you want to measure MHz signals, you dont need high resolution.

Years ago I made a small frequency counter with just 2 display digits, in assembler. Its not difficult either.
 

BobTPH

Joined Jun 5, 2013
8,943
I guess that depends on your application.

If you are measuring the frequency of your FM radio station, 2 digits would not cut it, 10 might mean anywhere from 100.0 to 109.9.

Bob
 

takao21203

Joined Apr 28, 2012
3,702
I guess that depends on your application.

If you are measuring the frequency of your FM radio station, 2 digits would not cut it, 10 might mean anywhere from 100.0 to 109.9.

Bob
You could do it with 2 digits- treat it as X.X deviation from 100 MHz, and use 2 LEDs for the sign, as well 10s if any.
 

MMcLaren

Joined Feb 14, 2010
861
... The only thing you lose is precision, because you cannot read the prescaler. ...
Hi Bob (and gang),

Actually, you can read the prescaler. Early 50-MHz Frequency Counters like those from Phil Rice, VK3BHR, used TMR0 with prescaler 256. After you "gate" the counter (TMR0) off you simply pulse the T0SE "edge select" bit to bump the prescaler while keeping track of the number of pulses until TMR0 overflow. In this case, 256 minus 'flush' pulses becomes the least significant eight bits of your "Count" variable.

Here's an excerpt from an assembly language example;

Code:
;
;  add 8-bit TMR0 and 8-bit prescaler to the 'Count' variable
;
        movf    TMR0,W          ;                                 |B0
        movwf   CountH          ; add TMR0 value to result        |B0
        clrf    CountL          ; prep 'CountL'                   |B0
Flush
        bsf     STATUS,RP0      ; bank 1                          |B1
        bcf     OPTION_REG,T0SE ; pulse TMR0 edge select bit      |B1
        bsf     OPTION_REG,T0SE ;  "                              |B1
        bcf     STATUS,RP0      ; bank 0                          |B0
        decf    CountL,F        ; decrement counter LSB           |B0
        movf    CountH,W        ;                                 |B0
        xorwf   TMR0,W          ; a TMR0 overflow?                |B0
        bz      Flush           ; no, clock it again              |B0
;
Note that this is an undocumented behavior that will not show up in Simulator however it works on all real devices I've tried it on (12F683, 16F628A, 16F88, etc.).

Cheerful regards, Mike
 
Last edited:
Top