![](templates/subSilver/images/CCSLogo.jpg) |
![CCS C Software and Maintenance Offers](templates/subSilver/images/forumAd6.jpg) |
View previous topic :: View next topic |
Author |
Message |
xxopiumxx
Joined: 01 Jul 2011 Posts: 20
|
Problem on frequency measurement |
Posted: Wed Nov 14, 2012 10:53 am |
|
|
Regards,
I am trying of create a frequency tester using the two comparators of the PIC18F4550. Particularly I need to count how many FE and RE edges I am getting in exactly 1 second (generated by RTCC and successfully tested with oscilloscope).
With another PIC I created a square pulse of 20khz, also using the RTCC, which I have also successfully tested.
The problem is that the tester only register half of the pulses.
The pic code is:
Code: |
#include <18F4550.h>
int32 seconds_counted=0;
int16 re_edge_counter=0, fe_edge_counter=0;
int1 stop_flag=0;
#INT_RTCC
void isr_rtcc(){
output_toggle(PIN_B3);
disable_interrupts(GLOBAL);
setup_timer_0(RTCC_OFF);
set_timer0(18661);
seconds_counted++;
printf("[%ld]",seconds_counted);
stop_flag=1;
}
#INT_CCP2
void isr_ccp2(){
re_edge_counter++;
}
#INT_CCP1
void isr_cpp1(){
fe_edge_counter++;
}
void main() {
printf("HZ TESTER\r\n");
setup_ccp1(CCP_CAPTURE_FE);
setup_ccp2(CCP_CAPTURE_RE); // Configuro captura de 1er flanco de subida
enable_interrupts(INT_CCP1);
enable_interrupts(INT_CCP2);
enable_interrupts(INT_RTCC);
setup_timer_0(RTCC_INTERNAL|RTCC_DIV_256);
set_timer0(18661);
enable_interrupts(GLOBAL);
while(true){
if(stop_flag){
printf("Edges in 1 second: %ld RE %ld FE\r\n", re_edge_counter,fe_edge_counter);
re_edge_counter=0;
fe_edge_counter=0;
stop_flag=0;
enable_interrupts(GLOBAL);
setup_timer_0(RTCC_INTERNAL|RTCC_DIV_256);
}
}
}
|
and an example of the outcome is:
Quote: |
[538]Edges in 1 second: 9984 RE 9984 FE
[539]Edges in 1 second: 9984 RE 9984 FE
[540]Edges in 1 second: 9984 RE 9984 FE
[541]Edges in 1 second: 9984 RE 9984 FE
[542]Edges in 1 second: 9984 RE 9984 FE
[543]Edges in 1 second: 9984 RE 9984 FE
[544]Edges in 1 second: 9984 RE 9984 FE
[545]Edges in 1 second: 9984 RE 9984 FE
[546]Edges in 1 second: 9984 RE 9984 FE
[547]Edges in 1 second: 9984 RE 9984 FE
[548]Edges in 1 second: 9984 RE 9984 FE
[549]Edges in 1 second: 9984 RE 9984 FE
[550]Edges in 1 second: 9984 RE 9984 FE
[551]Edges in 1 second: 9984 RE 9984 FE
[552]Edges in 1 second: 9984 RE 9984 FE
[553]Edges in 1 second: 9984 RE 9984 FE
|
any clues?
thanks! |
|
![](templates/subSilver/images/spacer.gif) |
Mike Walne
Joined: 19 Feb 2004 Posts: 1785 Location: Boston Spa UK
|
|
Posted: Wed Nov 14, 2012 2:36 pm |
|
|
You don't tell us you're crystal frequency, compiler version etc.
Code, as offered, is not complete and compilable for us to test.
How long does it take to execute each of your rising/falling edge interrupt routines?
Does your code work correctly at 5kHz or less?
Mike |
|
![](templates/subSilver/images/spacer.gif) |
Ttelmah
Joined: 11 Mar 2010 Posts: 19365
|
|
Posted: Wed Nov 14, 2012 3:38 pm |
|
|
Glaring thing, disable_interrupts(GLOBAL), won't work in the int_rtcc. The global interrupt is _already_ disabled when you enter an interrupt routine. The hardware does this. It is _automatically re-enabled_ when the routine exits...
Don't actually use the interrupt handler for this, instead:
Code: |
void main() {
printf("HZ TESTER\r\n");
setup_ccp1(CCP_CAPTURE_FE);
setup_ccp2(CCP_CAPTURE_RE); // Configuro captura de 1er flanco de subida
enable_interrupts(INT_CCP1);
enable_interrupts(INT_CCP2);
while (TRUE);
re_edge_counter=fe_edge_counter=0;
enable_interrupts(GLOBAL);
set_timer0(18661);
clear_interrupts(INT_RTCC);
while (!interrupt_active(INT_RTCC)); //wait for RTCC to trigger
disable_interrupts(GLOBAL);
printf("Edges in 1 second: %ld RE %ld FE\r\n", re_edge_counter,fe_edge_counter);
}
|
However some more comments:
Rising edges will always match falling edges. Since a pulse always has two edges, unless your timeout is exactly in the middle of a pulse, the two counts are always going to be the same....
Then a potential problem is time. You don't tell us your CPU frequency, but at (say) 8MHz, the chip executes just 2MIPS. So in 1/20000th second, just 100 instructions. It takes typically just over 65 instructions to get into and out of an ISR, plus typically another four instructions to increment a 16bit number. There wouldn't then be time for both ISR's to execute in the available time. This could easily explain your shortfall in counting.
However, your 18661 setting with RTCC/256, will only give one second, if your chip is running at 48MHz. So, this shouldn't be the problem.
Personally I'd double check that your source really is 20KHz. Remember that has a half cycle pulse width of just 25uSec. I'd suspect you might be confusing a pulse train at 20000 edges/second. with one at 20000Hz (40000 edges). Unless your other chip is running very fast, the problem of just how much it can do in 1/40000th second applies again.
Best Wishes |
|
![](templates/subSilver/images/spacer.gif) |
|
|
You cannot post new topics in this forum You cannot reply to topics in this forum You cannot edit your posts in this forum You cannot delete your posts in this forum You cannot vote in polls in this forum
|
Powered by phpBB © 2001, 2005 phpBB Group
|