Pulse & Frequency meter using CCP FC6

Tips, Tricks and methods for programming, learn ways of making your programming life easier, and share your knowledge with others.

Moderators: Benj, Mods

Post Reply
medelec35
Matrix Staff
Posts: 9520
Joined: Sat May 05, 2007 2:27 pm
Location: Northamptonshire, UK
Has thanked: 2585 times
Been thanked: 3815 times
Contact:

Pulse & Frequency meter using CCP FC6

Post by medelec35 »

Attached is a flowchart that is created with Flowocde V6
Flowchart is not all my work so credit to Sean who use to work at Matrix.
The objective is to use CCP (Capture Compare & Pulse width modulation) function of a 16F1937.
This should also work for a majority of microcontrollers that have a 16bit timer 1 interrupt and CCP.

Eblocks used:
Eb006 v9 Programmer with J18&J19 set to A6&A7
Eb005 2x16 LCD connected to portD
EB070USB Test pod

Target device = 16F1937
Oscillator mode : Internal @ 32MHz
Pulse/ Frequency input connected to CCP1 (port C2)
Pulse / Frequency range = 7143ms/70Hz to 5uS/100000Hz
For an example, connected the USB Test Pod to port C and set frequency going to pin C2 at 50KHz:
sig gen 50KHz.png
(61.3 KiB) Downloaded 7117 times
The LCD displayed:
Frequency 50KHz.jpg
Frequency 50KHz.jpg (28.23 KiB) Viewed 13870 times
Accuracy was very good for the range stated above.
ICT was also displaying correct pulse duration of 10uS:
ICT reading 10us.png
(17.51 KiB) Downloaded 7117 times
For any users not yet got Flowcode V6, you can down download a 30day trial From here

How CCP works to measure pulse with is:
when CCP interrupt is first triggered (by a positive edge going to port C2) then Timer1 is enabed (t1con = 0x01;) and timer1 is set for falling edge (ccp1con = 0x04; ).
When falling edge occurs, timer1 CCP interrupt service routine is again accessed, the values stored in ccpr1h & ccpr1l 8 bit CCP registers are converted in to 16bit unsigned integer that is supported by Flowcode6
The secret of converting to a pulse width is using the value from the CCP register and diving by 8 this works because with prescaler set to 1:1 each count in duration is 1/(32MHz/4) = 125nS then x 8 = 1uS = 8 time longer.
Therefore after the value of ccpr1h & ccpr1l registers are divided by 8 (ControlVal = PulseWidth >> 3 ) the result is directly in microseconds.

Hope this helps if trying to use CCP interrupt to measure pulse width or frequencies.

Martin
Attachments
Pulse & frequency Meter using CCP R1_v6.fcfx
(9.7 KiB) Downloaded 1190 times
Martin

maxtisc
Posts: 110
Joined: Mon Dec 23, 2013 9:34 pm
Has thanked: 2 times
Been thanked: 9 times
Contact:

Re: Pulse & Frequency meter using CCP FC6

Post by maxtisc »

Hello everyone
I would like to put this program on a 18f87k22 , I would like to know what are the changes to be done on the block that controls the interrupt , I tried to make some changes but I can not make it work always shows 0Hz
thank you

User avatar
Jay Dee
Posts: 398
Joined: Tue Aug 18, 2009 6:42 pm
Has thanked: 121 times
Been thanked: 154 times
Contact:

Re: Pulse & Frequency meter using CCP FC6

Post by Jay Dee »

Hi,
Looking to use this CCP method but in FC8, the sample FC does not compile correctly.
With the change of compiler in FC8 (I think) could that be a part ofthe issue?
the custom interupt sets register bits with a method i've not used before, is this still valid?

Code: Select all

ccp1con =0x05;    //capture on rising edge of CCP1
pir1.CCP1IF = 0; // Clear pending CCP1 interrupts
pie1.CCP1IE = 1; // Enable CCP1 interrupts
intcon.PEIE = 1; // Enable peripheral interrupts
intcon.GIE = 1; // Enable global interrupts
any ideas?

User avatar
Jay Dee
Posts: 398
Joined: Tue Aug 18, 2009 6:42 pm
Has thanked: 121 times
Been thanked: 154 times
Contact:

Re: Pulse & Frequency meter using CCP FC6

Post by Jay Dee »

So... I may have just found a different route to the same result and uses the same register values but this worked for me.
Changes in the CCP1 Interrupt component.
Enable Code

Code: Select all

CCP1CON = 0x05;    //capture on rising edge of CCP1
PIR1 = PIR1 & ~(1<<2);  // Clear CCP1IF
PIE1 = PIE1 | 0x04;  // Set CCP1IE
INTCON = INTCON | 0x40;  //Enable peripheral interrupts
INTCON = INTCON | 0x80; // Enable global interrupts

and handler code

Code: Select all

if ((PIR1 >>2)&1)
{
FCM_%n(); // call selected macro
PIR1 = PIR1 & ~(1<<2);  // Clear CCP1IF Flag
}
then rewrote the C code boxes in the CCP1isr macro in capitals. Not sure if that is essential but it compiled OK after that.
I'm using it on a ECIO40P so just playing about with the scaler and offset values in 'Main' and stuff to output correct numbers.

Post Reply