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 support@ccsinfo.com

Measuring period without ccp

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



Joined: 24 Jun 2005
Posts: 206

View user's profile Send private message Send e-mail

Measuring period without ccp
PostPosted: Sun Mar 15, 2015 1:50 am     Reply with quote

Hi All,

I need to measure a pulse width without using the ccp (already in use by PWM). So I come up with this:

Code:

//// Compiler Version:                  CCS 5.025               ////

#include <18F2685.h>
#fuses HS,NOWDT,PUT,NOPROTECT,NOLVP,NOMCLR

#use delay(clock=20M)

int16 period;
int1 timerRunning;
int1 timerReady;


#INT_EXT
void isr_ext()
{
    if(timerRunning)
      {
        period = get_timer0();
        timerReady = 1;
      }
    else
      {
         timerRunning = 1;
         set_timer0(0);
      }

}


void main()
{
    setup_ccp1(CCP_PWM);
    setup_timer_2(T2_DIV_BY_1, 199, 1);

    setup_timer_0(T0_INTERNAL | T0_DIV_16);
    ext_int_edge(H_TO_L);
   
    enable_interrupts(global);

    set_pwm1_duty(0);

    while(1)
      {
          period = 0;
          timerRunning = 0;
          timerReady = 0;

          enable_interrupts(INT_EXT);

          while(timerReady == 0);

          disable_interrupts(INT_EXT);

          delay_ms(3000);
      }
}


The input into B0 is nice and stable, with periods between 8ms and 70ms. The period only changes when I make it change and I can see it on my scope.
I am setting a breakpoint on the delay_ms(3000) and reading the period var in MPLAB.

Problem is the timer comes back with seemingly random numbers (last 5 readings I got were 2629, 8982, 6678, 43454, 452). I think for a period of 65ms I should get back ~20000? If I change the code to just count the pulses for one second I get numbers that make sense so I think the ext_int is working ok, just my timer code is not quite right.
Can anyone see what I am doing wrong?

Thanks
Ttelmah



Joined: 11 Mar 2010
Posts: 19326

View user's profile Send private message

PostPosted: Sun Mar 15, 2015 2:31 am     Reply with quote

CCP... Smile

One problem is 'what happens if there is an interrupt when the system is not reading'?.

Think about it. The interrupt is disabled, _but the hardware is still running_.
You delay for three seconds, and then if the interrupt has fired in this time, when you enable the interrupt, the interrupt is immediately called (the flag is still set). This could happen up to 3 seconds after the actual event, so you get a garbage reading.

Code:

    while(1)
      {
          period = 0;
          timerRunning = 0;
          timerReady = 0;
          clear_interrupt(INT_EXT); //need to clear the interrupt before enabling

          enable_interrupts(INT_EXT);

          while(timerReady == 0);

          disable_interrupts(INT_EXT);

          delay_ms(3000);
      }
Mike Walne



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

View user's profile Send private message

PostPosted: Sun Mar 15, 2015 4:46 am     Reply with quote

So, you're not measuring pulse width, but the period of a regularly repeating pulse stream.

What are:-

1) Period range to measure.
2) Required accuracy/resolution.
3) Update rate?

Mike
Markdem



Joined: 24 Jun 2005
Posts: 206

View user's profile Send private message Send e-mail

PostPosted: Mon Mar 16, 2015 2:16 am     Reply with quote

Ttelmah wrote:
CCP... Smile

One problem is 'what happens if there is an interrupt when the system is not reading'?.

Think about it. The interrupt is disabled, _but the hardware is still running_.
You delay for three seconds, and then if the interrupt has fired in this time, when you enable the interrupt, the interrupt is immediately called (the flag is still set). This could happen up to 3 seconds after the actual event, so you get a garbage reading.

Code:

    while(1)
      {
          period = 0;
          timerRunning = 0;
          timerReady = 0;
          clear_interrupt(INT_EXT); //need to clear the interrupt before enabling

          enable_interrupts(INT_EXT);

          while(timerReady == 0);

          disable_interrupts(INT_EXT);

          delay_ms(3000);
      }


Sir, I indebted to you Smile. Works perfect.
I knew it was something simple and I learnt something new today too. I always assumed that the disable_interrupts disabled the interrupt not just the handler.

Thanks
Ttelmah



Joined: 11 Mar 2010
Posts: 19326

View user's profile Send private message

PostPosted: Mon Mar 16, 2015 2:35 am     Reply with quote

This is actually a key realisation. It's why (for instance) it is possible to 'poll' an interrupt. Using the hardware to record that an event has happened, and then just testing the interrupt flag. You'll see quite a few threads about this.

The actual design is 'multi layer'.

The hardware triggers a flag (in this case INT_EXT).
Then there is an enable bit (this is what is set by the enable/disable for the individual interrupt).
Then there is a global enable bit.

The handler is called when all three are TRUE. The enable/disable, just turns of the enable flag, not the recording of the event.

This is also vitally important, since otherwise if (for instance) you had serial interrupts, and disabled these momentarily, so that the serial interrupt wouldn't take place while doing a critical timing, if the hardware recording was turned off, any character actually received in this moment, would be lost. Instead what happens is the hardware records that a character is waiting, and as soon as the interrupts are re-enabled, the handler gets called.
It's also how multiple interrupts can be used. If you realise that the hardware automatically disables interrupts (ignoring hardware priorities), when the handler is called, then again interrupts would be lost, if this stopped the actual recording of events.

With this knowledge, it makes using interrupts make a lot more sense!... Smile
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