CCS C Software and Maintenance Offers
FAQFAQ   FAQForum Help   FAQOfficial CCS Support   SearchSearch  RegisterRegister 

ProfileProfile   Log in to check your private messagesLog in to check your private messages   Log inLog in 

CCS does not monitor this forum on a regular basis.

Please do not post bug reports on this forum. Send them to CCS Technical Support

Problem on frequency measurement

 
Post new topic   Reply to topic    CCS Forum Index -> General CCS C Discussion
View previous topic :: View next topic  
Author Message
xxopiumxx



Joined: 01 Jul 2011
Posts: 20

View user's profile Send private message

Problem on frequency measurement
PostPosted: Wed Nov 14, 2012 10:53 am     Reply with quote

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!
Mike Walne



Joined: 19 Feb 2004
Posts: 1785
Location: Boston Spa UK

View user's profile Send private message

PostPosted: Wed Nov 14, 2012 2:36 pm     Reply with quote

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
Ttelmah



Joined: 11 Mar 2010
Posts: 19513

View user's profile Send private message

PostPosted: Wed Nov 14, 2012 3:38 pm     Reply with quote

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
Display posts from previous:   
Post new topic   Reply to topic    CCS Forum Index -> General CCS C Discussion All times are GMT - 6 Hours
Page 1 of 1

 
Jump to:  
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