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

Output a pulse of 6.5us upon pin B0 interrupt

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



Joined: 10 Sep 2003
Posts: 60

View user's profile Send private message Send e-mail Yahoo Messenger MSN Messenger ICQ Number

Output a pulse of 6.5us upon pin B0 interrupt
PostPosted: Tue May 03, 2005 9:23 am     Reply with quote

Dear all,

I wish to do the following:
Whenever I receive a low to high interrupt on Pin B0, I will output a high pulse at Pin C0 and starts a timer 2 which will overflow after 6.5us. When timer 2 overflow, Pin C0 will be low again. This process repeats again when I receive another low to high interrupt. Below is my program:

#include <16f876.h>
#fuses hs,NOWDT,NOPROTECT,NOLVP
#use delay(clock=20000000)

#byte PORTA=5
#byte PORTB=6
#byte PORTC=7

#int_ext
void ads_isr()
{
output_high(PIN_C0);
setup_timer_2(T2_DIV_BY_1,32,1);
enable_interrupts(INT_TIMER2);
}

#int_timer2
timer2_isr()
{
output_low(PIN_C0);
disable_interrupts(INT_TIMER2);
}

void main()
{
set_tris_b(0x01);
set_tris_b(0);

ext_int_edge(l_to_h);
enable_interrupts(global);
enable_interrupts(int_ext);
}

1) Does this line reset the timer 2 value and recount for 6.5us?
setup_timer_2(T2_DIV_BY_1,32,1);
2) Does the program above look logical (meet the requirements)?
I might be wrong in placing this line at the wrong place
setup_timer_2(T2_DIV_BY_1,32,1);
enable_interrupts(INT_TIMER2);

Thanks a lot...
_________________
Einly
Ttelmah
Guest







PostPosted: Tue May 03, 2005 10:31 am     Reply with quote

The setup line, sets the prescaler, and the 'limit'. If the timer was already running, it could contain a count already at this point, but from power up, it shouldn't. You should be setting the timer up in main, then resetting the _count_ in the interrupt, clearing the interrupt flag (since it will already have been triggered if the timer was running), then enabling the interrupt.
However, your big problem is _latency_. You cannot do what you want with an interrupt. The problem is that when the interrupt occurs, a global interrupt handler is called. This saves a number of registers, and then checks what has interrupted, and eventually calls the handler itself. All this takes time. The typical handler on the 16 family processor, will reach the interrupt routine, about 30 instruction times after the event occured. Then returning from the interrupt typically takes another 25 instruction times. So in your external interrupt, once everything is 'set', 25 instruction times occur before the code returns to the main flow. Only 7 instructions latter, the timer triggers (the first time, on latter loops, the timer interrupt will already have been triggered because the timer was still running), then another 30 instruction times pass, before the edge is generated.
Look instead at using timer1, and the CCP module. The special event setting of this, allows it to clear a pin automatically when a count is reached. This however has to use the CCP pin, not pin_c0.
With the approach you are currently using, the shortest pulse possible, would be about 11uSec, which is the time taken to exit the interrupt routine, enter again, and operate the pin...
Given that the code results in an amost immediate second interrupt, which will itself take about 13uSec to handle, you might as well use the other 'normally avoided' approach, and just operate the pin with a delay in the interrupt handler. However this will still occur some 5uSec after the actual event that triggered the interrupt...

Best Wishes

Best Wishes
Einly



Joined: 10 Sep 2003
Posts: 60

View user's profile Send private message Send e-mail Yahoo Messenger MSN Messenger ICQ Number

CCP module?
PostPosted: Mon May 09, 2005 8:38 pm     Reply with quote

"Look instead at using timer1, and the CCP module. The special event setting of this, allows it to clear a pin automatically when a count is reached. This however has to use the CCP pin, not pin_c0. "

I tried to look at the Microchip AN594 application note and found out that there is 2 mode associated with the CCP module, which is compare and capture. For my application, how do I use the CCP module? There will be pulses coming into a pin (external pulses with a maximum frequency of 300kHz). Upon receiving a high to low pulse, I will output a 6.5us high pulse on a pin.

May I know what should I do to achieve that? Is it possible using CCP module? Do you have any example lines of code to do that? Which pins should I use? (I need 2 pins, 1 for receiving the high to low pulse, 1 to output the 6.5us).
_________________
Einly
DragonPIC



Joined: 11 Nov 2003
Posts: 118

View user's profile Send private message

PostPosted: Tue May 10, 2005 2:10 pm     Reply with quote

Use a CCP module in compare mode. When external interrupt occurs, setup the compare module to a 6.5us (plus an instruction cycle needed to set the output high) value and make it so it will clear the CCP output on match. Clear the timer1. Set the CCP output to high and when the compare match occurs, the output will return low. Then use the compare interrupt to turn the CCP of until you need it again.

Like Ttalmah said, you may be better off with:

Code:
#int_ext
void ads_isr()
{
output_high(PIN_C0);
delay_us(6.5);
output_low(PIN_C0);
}


I would then use #USE FAST_IO and setup the tris register myself so there is not time wasted while output_hi() or output_low() is setting the tris registers every time you use the functions. (tweek)
_________________
-Matt
sseidman



Joined: 14 Mar 2005
Posts: 159

View user's profile Send private message

PostPosted: Tue May 10, 2005 3:58 pm     Reply with quote

DragonPIC wrote:


Like Ttalmah said, you may be better off with:

Code:
#int_ext
void ads_isr()
{
output_high(PIN_C0);
delay_us(6.5);
output_low(PIN_C0);
}


I


Can delay_us take floats?

Scott
DragonPIC



Joined: 11 Nov 2003
Posts: 118

View user's profile Send private message

PostPosted: Wed May 11, 2005 12:38 pm     Reply with quote

I have used the decimal point before with the SX version with no problem. I used a constant and do not remember checking the accuracy. If needed, just use:

Code:
delay_us(6);
delay_cycles(2);//or 3 for 6.6us


about 6.4us (since each cycle is about 200ns) is as close as your gonna get.

or

delay_cycles(32);
_________________
-Matt


Last edited by DragonPIC on Wed May 11, 2005 12:49 pm; edited 1 time in total
sseidman



Joined: 14 Mar 2005
Posts: 159

View user's profile Send private message

PostPosted: Wed May 11, 2005 12:48 pm     Reply with quote

DragonPIC wrote:
I have used the decimal point before with the SX version with no problem. I used a constant and do not remember checking the accuracy. If needed, just use:

Code:
delay_us(6);
delay_cycles(2);//or 3 for 6.6us


about 6.4us (since each cycle is about 200ns) is as close as your gonna get.


If the 0.1 us is really critical, you might consider jumping up to an 18F chip and doubling the clock speed

Scott
PCM programmer



Joined: 06 Sep 2003
Posts: 21708

View user's profile Send private message

PostPosted: Wed May 11, 2005 12:49 pm     Reply with quote

No, it can't take a float.

Compile the following program with PCM vs. 3.224:
Code:
#include <16F877.H>
#fuses XT, NOWDT, NOPROTECT, BROWNOUT, PUT, NOLVP
#use delay(clock = 4000000)

void main()
{
delay_us(6.5);

delay_us(6);

while(1);
}


Here is part of the .LST file. You can see clearly that it's doing
a delay of 6 us for the delay_us(6) statement, because at 4 MHz,
one NOP instruction takes 1 us. With the float, it obivously isn't
isn't doing a 6 us delay.
Code:
0000                00348 .................... delay_us(6.5);   
0038 3014       00349 MOVLW  14
0039 1283       00350 BCF    03.5
003A 00A1       00351 MOVWF  21
003B 2804       00352 GOTO   004   
003C 3003       00353 MOVLW  03
003D 00A1       00354 MOVWF  21
003E 30C8       00355 MOVLW  C8
003F 00A2       00356 MOVWF  22
0040 281B       00357 GOTO   01B
0041 0BA1       00358 DECFSZ 21,F
0042 283E       00359 GOTO   03E
0000                00360 ....................   
0000                00361 .................... delay_us(6); 
0043 0000       00362 NOP
0044 0000       00363 NOP
0045 0000       00364 NOP
0046 0000       00365 NOP
0047 0000       00366 NOP
0048 0000       00367 NOP
0000                00368 ....................   
DragonPIC



Joined: 11 Nov 2003
Posts: 118

View user's profile Send private message

PostPosted: Thu May 12, 2005 10:25 am     Reply with quote

I beleive he is running at 20MHz. Retry with 20MHz. Your probably right anyway since it doesn't look right. The compiler should have come up with an error.
_________________
-Matt
DragonPIC



Joined: 11 Nov 2003
Posts: 118

View user's profile Send private message

PostPosted: Thu May 12, 2005 10:43 am     Reply with quote

sseidman wrote:
DragonPIC wrote:
I have used the decimal point before with the SX version with no problem. I used a constant and do not remember checking the accuracy. If needed, just use:

Code:
delay_us(6);
delay_cycles(2);//or 3 for 6.6us


about 6.4us (since each cycle is about 200ns) is as close as your gonna get.


If the 0.1 us is really critical, you might consider jumping up to an 18F chip and doubling the clock speed

Scott


Or you could check out one of the SX chips by Ubicom (marketing handled by parallax). These chips cruise at 50MHz+ and execute an instruction per cycle giving you 20ns/instruction by using a instruction pipeline. CCS makes a compiler for the SX also.
_________________
-Matt
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