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

Best Way of doing something

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







Best Way of doing something
PostPosted: Thu May 18, 2006 7:16 pm     Reply with quote

Hi im trying to work out the best way of doing something.

I am using a PIC16f877a

I use CCP1 to measure the time between falling edges of a pulse train.
This falling edge is used to generate a signal from the uP which is started 64us after the incoming falling edge.
The output pulse is of variable length from 500-1500us

I am wondering which is the best and easiest way to implement this.

This was one option, just simply using the delay_us in the interrupt although this is a messy way of doing it

Code:


#int_ccp1 
void isr()
{
  delay_us(50);                 //Should give 64us delay
  output_high(PIN_C3);     //Turn on output
   delay_us(pulse);            // pulse delay
  output_low(PIN_C3);      //Turn off  output
}


The other posibility i looked at was using the other CCP module in compare mode to generate the output, however i looked into this and it does not seem you can assosiate the second CCP module with timer3 which is what i had planned to do. Is it possible?

The third option is to use a timer overflow interrupt and just put the inverse (well sorta) of the values into the timer and letting it overflow and generate an interrupt, then loading it with the pulse variable in the timer interrupt

The 64us delay does not have to be that accurate but the pulse width output should be

Which way do u think is best and why?

Cheers

Pilt
Ttelmah
Guest







PostPosted: Fri May 19, 2006 3:04 am     Reply with quote

What other chip resources are you using?.
There is no 'point' in using the CCP, to trigger the start of the pulse, if the external interrupt is available.
What timers are you using for other things?.
As written, the code has several problems. The first is simply that you can't have a variable delay over 255uSec, using the delay_us functon. The second is that doing it this way, brings the big problem that you will be stuck inside this interrupt handler for a long time, and other handwre events may/will be missed. Also, using the delay function, implies that interrupts will be disabled in delays outside the interrupt handler, which makes the initial latency more likely to vary...
If you only want the pulse, not the timing, I'd consider a different approach:
1) Use 'int_ext' to trigger the start of the pulse. Program this to interrupt on the falling edge of the incoming signal.
2) Have timer1, programed to count in the 'units'required for your pulse width (uSec?).
3) In the handler for int_ext, wait for the initial pause, then set the output pin for CCP1 (or 2, whichever you want to use), clear timer1, and set CCP1, to the pulse time required. Have it programmed to 'compare mode, reset on match'. Exit the handler.

The CCP module, will _clear_ it's output, the programmed count latter, with high accuracy, without you having to do anything else. This gives the required pulse precision.
Also, use the 'trick', of having a seperate #use delay statement for the interrupt handler code, so that the short delay needed at the start of the interrupt handler, does not result in interrupts being disabled in external delays.

Now, if you do need to use CCP1, to measure the time between the pulses, generate the output pulse using CCP2 instead, starting it in the CCP1 interrupt as you show, and rather than clearing timer1 (which would give errors for the width timings), set CCP2, to the value read from timer1, plus the time delay rquired. This is probably what you will need to do.

Best Wishes
pilt1
Guest







PostPosted: Fri May 19, 2006 6:22 am     Reply with quote

Hi, these are the only interrupts i am using, the other timers are not being used for anything

Hi thanks for that, has given me ideas for how to do it

Here is my revised code

Code:

#use delay(clock=20000000,restart_wdt)
#int_ccp1  //
void isr()
{
   current = CCP_1;
   comp_count = (last+65536) - current; //comp_count is a int32
   last = get_timer1();   


   delay_us(50);         //Should give 64us delay
   output_high(CCP2_PIN); //Wotever pin it is
       
      pulse = last + width; //pulse is a 16bit value so will overflow
                            //in accordance with timer 1 to get correct value
       CCP_2 = pulse;                         

       setup_ccp2(CCP_COMPARE_CLR_ON_MATCH);

 
if(!TMR1IF) //If timer 1 has not overflowed subtract 65536 to value
  {
   comp_count -= 65536;
  }

if(TMR1IF) //If timer 1 has overflowed reset the flag
  TMR1IF = 0;
   

}

#int_ccp1
{
setup_ccp2(CCP_OFF);
}


Ok here goes

The time meausred between the falling edges of the incoming signal can be from about 3ms up to 150ms so i used timer 1 set to overflow at 104ms . By checking if an overflow has occured between two falling edges i can effectiverly mesaure 204ms.

Now i never reset the timer1 value so i need the last value (from last falling edge) to calculate the duration, at the top i add 65,536 to this because i just assume that the timer has overflowed as i did not want to put the if statement to check for this till the end of the interrupt.


After the delay i simply set the CCP2 pin high then load the CCP2 register and then setup the CCP2 module to go low when it reaches the value.

Int the CCP2 int the module is disabled. (mainly i think i may need to do this because the output_high(CCP2_PIN); wont work if the CCP is enabled?)

Does this look like it will work, i dont have a scope about at the moment to check any of this which is why i want to try get the code correct first.
Just wondering also if i need to perform the measurement at the top of the code, i did it this way as i want to calculate the last value ASAP and not add the delay to it.

Cheers for all your help!

Thanks

Pilt
pilt1
Guest







PostPosted: Fri May 19, 2006 6:50 am     Reply with quote

Bottom bit should be

Code:

#int_ccp2
void ccp2int()
{
setup_ccp2(CCP_OFF);
}
Ttelmah
Guest







PostPosted: Fri May 19, 2006 8:17 am     Reply with quote

Are you using 'delays' for anything in the main code?.
If so, add a seperate #use delay statement, in front of the interrupt code.
Lok through the forum for examples of how to do this. I think it was originally posted by PCM_programmer as a solution for this problem.
This will result in a seperate 'set' of delay code being generated for the interrupt code, and the main stuff, and avoid the problem which will otherwise occur with interrupts being disabled inside the delays in the non nterrupt code.
I'd leave CCP2 'running'. It shouldn't matter that it keeps resetting the pin, and you don't need an interrupt handler for it then (saves code, and the time involved in checking for another interrupt source).

Best Wishes
pilt1
Guest







PostPosted: Fri May 19, 2006 8:35 am     Reply with quote

Ttelmah wrote:
Are you using 'delays' for anything in the main code?.
If so, add a seperate #use delay statement, in front of the interrupt code.



Yes i am, but i did add a seperate delay statement in front of the interrupt like you said

Code:

#use delay(clock=20000000,restart_wdt)
#int_ccp1  //
........


Is this correct.

Thanks for all your help Ttelmah

Pilt
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