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

please help

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



Joined: 09 Jun 2006
Posts: 3

View user's profile Send private message

please help
PostPosted: Fri Jun 09, 2006 2:36 am     Reply with quote

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);
}

}
Ttelmah
Guest







PostPosted: Fri Jun 09, 2006 5:18 am     Reply with quote

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
virtual



Joined: 09 Jun 2006
Posts: 3

View user's profile Send private message

Thanks
PostPosted: Sun Jun 11, 2006 5:34 am     Reply with quote

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
ckielstra



Joined: 18 Mar 2004
Posts: 3680
Location: The Netherlands

View user's profile Send private message

Re: Thanks
PostPosted: Sun Jun 11, 2006 6:19 am     Reply with quote

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
rberek



Joined: 10 Jan 2005
Posts: 207
Location: Ottawa, Canada

View user's profile Send private message

PostPosted: Sun Jun 11, 2006 6:21 am     Reply with quote

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.
Ttelmah
Guest







Re: Thanks
PostPosted: Sun Jun 11, 2006 1:14 pm     Reply with quote

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
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