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

CCP1 rollover

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



Joined: 22 Sep 2003
Posts: 119

View user's profile Send private message

CCP1 rollover
PostPosted: Wed Oct 26, 2016 1:39 pm     Reply with quote

I'm using CCP1 tied to an IR RX/TX pair to measure the speed of an object passing by (18F2553). I've never used the CCP module before but I do have working code modified from the code library that works but my issue is, how do I handle the pulse count delta when an object passes by that is slower than the 16 bit timer can store? I have TIMER1 set to the slowest count rate (div_8). Since the delta is generated by the difference of the start and stop edges, I can't even monitor if TIMER1 rolled over since the start edge may have been near 65535 at the starting (falling in my case) edge.

Any insight is appreciated.

Thanks,

Dan
Ttelmah



Joined: 11 Mar 2010
Posts: 19541

View user's profile Send private message

PostPosted: Wed Oct 26, 2016 1:45 pm     Reply with quote

The CCP doesn't roll over. The timer does.
When the timer rolls over, it can generate an interrupt.
Increment a counter in the interrupt for the timer.
Then when the CCP interrupts, you can use a 32 bit value from the CCP (low 16bits) combined with the counter from the timer interrupt (make32, or combine the values using a union).
Just make sure the timer interrupt has higer priority than the CCP one. The CCP 'holds' the logged time, so can be read at any point until the next edge.
dan king



Joined: 22 Sep 2003
Posts: 119

View user's profile Send private message

PostPosted: Wed Oct 26, 2016 2:02 pm     Reply with quote

Would that require that the initial TIMER1 value be 0 at the instant the starting CCP interrupt occurred? The code sample I'm using allows TIMER1 to free run and the ISR captures the start and stop values from TIMER1 so the first TIMER1 interrupt may not indicate an overflow for the first time through. Can I set_TIMER1(0) at the start of a capture in the CCP ISR?


I will generate a small test program to show my code shortly.

I understand the CCP doesn't roll over, poor word choice on my part.

Thanks for the fast response.
dan king



Joined: 22 Sep 2003
Posts: 119

View user's profile Send private message

PostPosted: Wed Oct 26, 2016 2:11 pm     Reply with quote

Excellent, that works. Thanks for the guidance.

Dan
Ttelmah



Joined: 11 Mar 2010
Posts: 19541

View user's profile Send private message

PostPosted: Thu Oct 27, 2016 1:16 am     Reply with quote

Good.

No, you don't want to set the timer to zero in the first ISR (actually this is OK for slow signals, but otherwise can cause problems, since it takes time to get into the ISR). All of these approaches are best done by working holding the 'last' and 'current' values, and then calculating using the 'delta' between these.

Though you have got it working, it is worth looking at an approach like:
Code:

union {
    int16 word16[2];
    int32 whole;
} CCPval;
int32 delta=0;

#INT_TIMER1
void timer_overflow(void)
{
    CCPval.word16[1]++; //increments the high 16 bits
}

#INT_CCP1
void ccp_got_edge(void)
{
    static int32 old;
    static int1 OK=FALSE;
    CCPval.word16[0]=CCP1; //copy the 16bits from the CCP register
    if (OK)
    {
       delta=CCPval.whole-old; //calculate the delta between the calls
    }
    else
       OK=TRUE; //start working after second call
    old=CCPval.whole;
}


Now, this requires _two_ calls before it'll update delta (this is the point of the 'OK' flag). Does the maths as 32bit, combining the 16bits from the CCP, with the timer overflow count. delta is the 32bit difference count between the calls. Smile

In the 'main', once delta is non zero, you have a working value.
Beware though. Remember that the chip only accesses 'byte at a time', so you need to disable interrupts, and copy 'delta; into the value you are going to use in the main (or do a repeated copy, and check that it hasn't changed). So:
Code:

    int32 local_delta;

    //then to read delta.
    //either
    disable_interrupts(GLOBAL);
    local_delta=delta;
    enable_interrupts(GLOBAL);

    //or
    while (local_delta != delta)
       local_delta=delta;
 
    //then work with the local copy
dan king



Joined: 22 Sep 2003
Posts: 119

View user's profile Send private message

PostPosted: Thu Oct 27, 2016 10:19 am     Reply with quote

I just used the principle of your example extending the timing to 32 bits and the results are excellent. That makes much better sense in that I don't need to worry about the state of the timer1 overflow and just let everything run. Thanks again for the help.

Dan
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