![](templates/subSilver/images/CCSLogo.jpg) |
![CCS C Software and Maintenance Offers](templates/subSilver/images/forumAd6.jpg) |
View previous topic :: View next topic |
Author |
Message |
virtual
Joined: 09 Jun 2006 Posts: 3
|
please help |
Posted: Fri Jun 09, 2006 2:36 am |
|
|
I am writting follwing code to toggle bit on port b each time one clock is
counted using external timer-1 .frequency at external timer is 256KiloHz
but frequency at port b1 is only 36KiloHzWhich should be 256KiloHz .
MCU PIC16F877A ,Crystal 20Mhz.What is problem.
#include "D:\Timer\Freq.h"
//#bit TimerOn = 0x10.0
//#bit TimerFlag = 0x0C.0
//#byte TimerLow = 0x0E
//#BYTE TimerHigh = 0x0F
#bit Clk = 0x6.0
unsigned char Flag = 0;
void Check(void);
#int_TIMER1
TIMER1_isr()
{
Flag = 1;
output_bit( PIN_B1, 1);
set_timer1(0xFFFF);
}
void main()
{
setup_adc_ports(NO_ANALOGS);
setup_adc(ADC_OFF);
setup_psp(PSP_DISABLED);
setup_spi(FALSE);
setup_timer_0(RTCC_INTERNAL|RTCC_DIV_1);
setup_timer_1(T1_EXTERNAL|T1_DIV_BY_1);
setup_timer_2(T2_DISABLED,0,1);
enable_interrupts(INT_TIMER1);
enable_interrupts(GLOBAL);
//TimerOn = 0;
SET_TRIS_B(0xF0 );
SET_TRIS_D(0xFF );
set_timer1(0xFFFF);
//TimerHigh = 0xFF;
//TimerLow = 0xFF;
//Check();
Flag = 0;
output_bit( PIN_B0, 0);
output_bit( PIN_B1, 0);
//while(Clk);
do
{
do
{
}while(!Flag);
Flag = 0;
output_bit( PIN_B1, 0);
}while(1);
}
void Check(void)
{
int i;
for(i = 1 ;i<100;i++)
{
output_bit( PIN_B0, i%2);
delay_ms(100);
}
} |
|
![](templates/subSilver/images/spacer.gif) |
Ttelmah Guest
|
|
Posted: Fri Jun 09, 2006 5:18 am |
|
|
Calling an interrupt, has a significant overhead associated with it. Typically perhaps a total of about 60 instructions, to call an interrupt and return. At 20MHz, this is about 12uSec. Now you are not showing 'fast_io', so a single bit input or output instruction, itself involves about 3 instruction times, while the loop itself, also involves another couple of instruction times. So as it stands, you will get:
Event happens.
Appproximately 6uSec latter, you will arrive in the interrupt event.
About 1uSec latter, you set the timer. At this point, you will have missed one, and possibly two of the event edges. You then setthe counter, which itself prevents counting from taking place while the value is being changed, another 1 to 1.5uSec. The interrupt flag is cleared. Some 6uSec latter you arrive 'back' in the main code, and another interrupt event will have occured. You then execute one instruction, and immediately call the interrupt handler again.
Basically, you cannot handle an event at this sort of frequency, with an interrupt, on a system at 20MHz (in assembler, with care, it could possibly just be done, an you might be able to get 'close', with a custom 'int_global' handler, but I doubt it.
Start by not using the timer fo this. This brings the significant overhead, of needing to be reset to see the next event. The normal 'INT' input, is a better check for an edge. Then don't handle this usng an interrupt handler at all, but simply poll for the interrupt being set. Also use fast_io, to reduce the overhead on each I/O operation.
So:
(Learn to use the 'code' button, makes ce much easier to read)
Code: |
#use fast_io(B)
#bit INTF=0x0B.1
void main() {
setup_adc_ports(NO_ANALOGS);
setup_adc(ADC_OFF);
setup_psp(PSP_DISABLED);
setup_spi(FALSE);
setup_timer_0(RTCC_INTERNAL|RTCC_DIV_1);
setup_timer_1(T1_EXTERNAL|T1_DIV_BY_1);
setup_timer_2(T2_DISABLED,0,1);
enable_interrupts(INT_EXT);
//Set your required 'edge' here, with 'ext_int_edge'
//enable_interrupts(GLOBAL);
//Do not enable the global interrupt
SET_TRIS_B(0xF1 );
//Set B0 to an input and use this to detect the edge - feed signal into
//B0.
SET_TRIS_D(0xFF );
//Setting tris, only saves time is 'fast_io' is selected.
//set_timer1(0xFFFF);
//output_bit( PIN_B0, 0);
//Use B0 a an input
INTF=0;
while (TRUE) {
output_bit( PIN_B1, 0);
//Wait for the edge
while (INTF==0) ;
output_bit( PIN_B1, 0);
INTF=0;
}
}
|
This won't probably actually do what you want from the final code, but shows how to _poll_an interrupt flag, to avoid the latency associated with interrupt servicing.
Best Wishes |
|
![](templates/subSilver/images/spacer.gif) |
virtual
Joined: 09 Jun 2006 Posts: 3
|
Thanks |
Posted: Sun Jun 11, 2006 5:34 am |
|
|
Hello
I am happy for quick reply But microchip asks upto 50 Mhz frequency couting can be done with timer 1 how is it possible as my rate is 255 KILOhZ
ONLY |
|
![](templates/subSilver/images/spacer.gif) |
ckielstra
Joined: 18 Mar 2004 Posts: 3680 Location: The Netherlands
|
Re: Thanks |
Posted: Sun Jun 11, 2006 6:19 am |
|
|
virtual wrote: | I am happy for quick reply But microchip asks upto 50 Mhz frequency couting can be done with timer 1 how is it possible as my rate is 255 KILOhZ ONLY | Meet the nice guys of marketing! They don't lie to you but they tend to 'forget' to mention some details.
For example, where did you read about the 50MHz? My guess is that it was a general Microchip datasheet and there will be chips meeting those specifications, but when you look at Table 17-6 for the PIC16F87xA datasheet you'll see the absolute minimum timing for Timer1 is 30ns, or 33.3MHz.
Then when Microchip tells you the chip can count up to this high frequency then you have to remember 'marketing' again. When you are reading the maximum specifications there will always be a catch. In this case Timer1 is configured as a hardware counter, it will count the pulses on one of the I/O-pins. A complete different implementation of counting than your program does perform, you can't compare the results.
Edit: Fixed typo.
Last edited by ckielstra on Sun Jun 11, 2006 6:33 am; edited 2 times in total |
|
![](templates/subSilver/images/spacer.gif) |
rberek
Joined: 10 Jan 2005 Posts: 207 Location: Ottawa, Canada
|
|
Posted: Sun Jun 11, 2006 6:21 am |
|
|
Read Ttelmah's post again.
Your problem has nothing to do with the speed of your timer, but rather the speed of your program. Your program is written in such a way that it cannot react to every edge of the timer so your toggle rate of port B is a fraction of the timer's rate.
Don't forget that instructions take time to execute, and if your program takes longer than a timer period to toggle port b, the apparent toggle rate will be slower than the timer rate.
r.b. |
|
![](templates/subSilver/images/spacer.gif) |
Ttelmah Guest
|
Re: Thanks |
Posted: Sun Jun 11, 2006 1:14 pm |
|
|
virtual wrote: | Hello
I am happy for quick reply But microchip asks upto 50 Mhz frequency couting can be done with timer 1 how is it possible as my rate is 255 KILOhZ
ONLY |
You are not trying to count the signal, but to do work on each pulse of the signal.
If you leave the timer to free run, it'll only interrupt every 65536 edges, and will happily count every single one, right up to the specified maximum.
It is like the difference between a car that is capable of 200mph in a straight line, and driving the car in a busy town. The car 'is' capable of 200mph, yet can only average perhaps 10, because of the corners, bends, limits etc.. You are using the input, not as a counter, but just as an interrupt 'trigger', and then overriding the hardware on every cycle, adding a lot of complexity, and not letting the hardware do it's actual job...
Best Wishes |
|
![](templates/subSilver/images/spacer.gif) |
|
|
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
|