各位大侠好:  
   小弟编写了一个测量频率的程序,TC1 工作在普通计数模式,用于记录外部输入的脉冲数,TC2 工作在比较定时模式,定时时间为20ms ,主程序每隔2s钟测量一次。可是测量时,发现当程序一运行“TIMSK |= BIT(OCIE2);  ”就立马进入 TC2 的中断服务程序,中断服务程序做完了才返回,然后我在“TIMSK |= BIT(OCIE2); ”前加了一句“TIFR |= BIT(OCF2);”程序能正常走不是立即进入中断服务程序,但是测量值大约是实际值的三分之一。这边小弟不理解为什么要加“TIFR |= BIT(OCF2);”,而且测量值怎么会偏低这么多,麻烦各位大侠帮我看一下,谢谢! 
程序: 
#include <iom8v.h> 
#include <macros.h> 
#include<stdio.h> 
#include<string.h> 
#include<stdlib.h> 
#define uint unsigned int 
#define ulint unsigned long int 
#define uchar unsigned char 
#define Led_ON    PORTB &= ~BIT(PB1) 
#define Led_OFF   PORTB |= BIT(PB1) 
#define Beep_ON   PORTB |= BIT(PB2) 
#define Beep_OFF  PORTB &= ~BIT(PB2) 
#define S0_ON     PORTC |= BIT(PC0) 
#define S0_OFF    PORTC &= ~BIT(PC0) 
#define S1_ON     PORTC |= BIT(PC1) 
#define S1_OFF    PORTC &= ~BIT(PC1) 
#define S2_ON     PORTC |= BIT(PC2) 
#define S2_OFF    PORTC &= ~BIT(PC2) 
#define S3_ON     PORTC |= BIT(PC3) 
#define S3_OFF    PORTC &= ~BIT(PC3) 
#define OE_ON     PORTD |= BIT(PD6) 
#define OE_OFF    PORTD &= ~BIT(PD6)      
 
void Init(); 
void InitUART(); 
void InitTC1(); 
void InitTC2(); 
void InitINT0(); 
void delayms(uint z); 
void Receive(uchar rbuf); 
void SendChar(uchar TempBuf); 
void SendString(const uchar *AddressPointer); 
void AnalysisCommand(); 
void DisposeValue(ulint temp_data); 
void ShowValue(uchar *p , signed char j); 
void TestRed(); 
void TestBlue(); 
void TestGreen(); 
void TestClear(); 
void TestAll(); 
ulint count = 0 ; 
uchar TimerONFlag ; 
uchar ConvertFlag ; 
uchar TestAllFlag ; 
const uchar  waittime=10; 
const uchar CommandPrompt[]={"Command error , please check ! "}; 
struct  
{ 
 uchar  index ; 
 uchar  index_end; 
 uchar  r_flag_end1; 
    uchar  r_flag_end2; 
 uchar  comm_infor[20]; 
} Receive_command={0,19,0,0,{0}}; 
void main() 
{ 
    
   Init(); 
   delayms(2000); 
   SendString("Color Test ! \r"); 
   SendString("Begin ..."); 
   SendChar('\r'); 
   while(1) 
     { 
     TestRed(); 
     delayms(2000); 
  } 
} 
void Init() 
{ 
 DDRD &= ~BIT(PD0) ;         // set PD0 ,   as input   RXD  
 DDRD &= ~BIT(PD5);         // set PD5 , as input TC1 
 DDRD |= BIT(PD1)+ BIT(PD6);              // set  PD1, PD6(OE) as output TXD  
 DDRB |= BIT(PB1) + BIT(PB2) ;           // set PB1 , PB2 as output  
 DDRC |= BIT(PC0) + BIT(PC1) + BIT(PC2) + BIT(PC3) + BIT(PC4) + BIT(PC5) ;  // PC0--PC5,(S0--S3) as output 
  
 TimerONFlag=0 ;     // not open Timer , test 
 CLI(); 
  
 InitUART();  
 InitTC1(); 
 InitTC2(); 
// InitINT0(); 
 S0_ON;                    // 100% output 
 S1_ON;  
     
 SEI();                       // open global interrupt 
} 
void InitUART() 
{ 
     UCSRA = 0X00 ; 
  UCSRB = 0X00 ; 
  UCSRC = 0X00 ;                                   // control register clear  
  UCSRA |= BIT(UDRE) ;                             // data buf empty  , could receive data 
  UCSRB |= BIT(RXCIE) + BIT(RXEN) + BIT(TXEN);     // enable RXB interrupt  
  UCSRC |= BIT(URSEL) + BIT(UCSZ1)+ BIT(UCSZ0);                     // SET 1 
  UBRR=0x2F;                                       // Baud 9600  7.3728 Mhz U2X = 0   
} 
void InitTC1() 
{ 
   TCCR1A &= ~BIT(WGM11) + ~BIT(WGM10); 
  TCCR1B &= ~BIT(WGM12) + ~BIT(WGM13);                // usual mode 
     TCCR1B &=  ~BIT(CS12) + ~BIT(CS11) + ~BIT(CS10);   // unable TC1 
  TCNT1 = 0X00 ;                                    // clear TCNT1  
} 
void InitTC2() 
{ 
   TCCR2 &=  ~BIT(WGM20);  
  TCCR2 |=  BIT(WGM21) + BIT(CS22) + BIT(CS21) + BIT(CS20);  // 1024 divide frequency , CTC mode 
  TCNT2 = 0X00;             // clear TCNT2 
  OCR2 = 0X8F;              // 20ms    
} 
/*void InitINT0() 
{ 
  // MCUCR |= BIT(ISC01) + BIT(ISC00) ;     // INT0 rise edge trigger 
  MCUCR |= BIT(ISC01) ; 
  MCUCR &= ~BIT(ISC00); 
}*/ 
void TestRed() 
{ 
    S2_OFF; 
 S3_OFF; 
 OE_OFF; 
 delayms(waittime); 
 ConvertFlag=0; 
 SendString("R :"); 
  
 TCNT1 = 0X00 ; 
 TIFR |= BIT(OCF2);                              // for test 
 TIMSK |= BIT(OCIE2);                            // enable TC2COMP 
 TCCR1B |=  BIT(CS12) + BIT(CS11) + BIT(CS10);   // rise edge trigger counter 
  
 while(ConvertFlag==0); 
    DisposeValue(count); 
} 
/*void TestBlue() 
{ 
 S2_OFF; 
 S3_ON; 
 OE_OFF; 
 delayms(waittime); 
 ConvertFlag=0; 
 SendString("B :"); 
 GICR |= BIT(INT0);                            // enable INT0 
} 
void TestGreen() 
{ 
 S2_ON; 
 S3_ON; 
 OE_OFF; 
 delayms(waittime); 
 ConvertFlag=0; 
 SendString("G :"); 
 GICR |= BIT(INT0);                            // enable INT0 
} 
void TestClear() 
{ 
 S2_ON; 
 S3_OFF; 
 OE_OFF; 
 delayms(waittime); 
 ConvertFlag=0; 
 SendString("I :"); 
 GICR |= BIT(INT0);                            // enable INT0 
} 
void TestAll() 
{ 
 TestRed(); 
 while(ConvertFlag==0); 
 TestGreen(); 
 while(ConvertFlag==0); 
 TestBlue(); 
    while(ConvertFlag==0); 
 TestClear(); 
 while(ConvertFlag==0); 
}*/ 
void SendChar(uchar TempBuf) 
{       
       UCSRB &= ~BIT(RXCIE) ;               // unable RXB interrupt 
     UDR = TempBuf ; 
       while((UCSRA & BIT(TXC))==0);   
    UCSRA &= ~BIT(TXC) ;               // clear flag bit  
       UCSRB |= BIT(RXCIE) ;              // enable RXB interrupt  
} 
void SendString(const uchar *AddressPointer) 
{ 
  UCSRB &= ~BIT(RXCIE);                       // unable RXB interrupt 
     while('\0' != *AddressPointer ) 
   { 
             UDR = *AddressPointer; 
             while((UCSRA & BIT(TXC))==0);       //  waiting  send finish              
             UCSRA |= BIT(TXC);                  // send finish flag  set 0 
    AddressPointer++; 
      } 
  UCSRB |= BIT(RXCIE);                      // enable RXB interrupt  
} 
void AnalysisCommand() 
{ 
   uchar i; 
    if((0==(strcmp( Receive_command.comm_infor ,"on"))) || (0==(strcmp( Receive_command.comm_infor ,"ON"))))  
     {  
      Led_ON; 
   Beep_ON; 
   SendString("Led ON"); 
   SendChar('\r'); 
  } 
    else if((0==(strcmp( Receive_command.comm_infor ,"off")))||(0==(strcmp( Receive_command.comm_infor ,"OFF"))))  
     {    
     Led_OFF; 
     Beep_OFF; 
     SendString("Led OFF"); 
     SendChar('\r'); 
     } 
    else 
    { 
   SendString(CommandPrompt); 
   for(i=0;i<Receive_command.index;i++) 
    Receive_command.comm_infor[i]='\0'; 
     Receive_command.index=0;  
   return ;  
  } 
  for(i=0;i<Receive_command.index;i++) 
      Receive_command.comm_infor[i]='\0'; 
     Receive_command.index=0;  
} 
void Receive(uchar rbuf ) 
{ 
   uchar i; 
   uchar r_flag=0; 
   if((13==rbuf)||(10==rbuf)) 
     { 
         if(13==rbuf) 
             Receive_command.r_flag_end1=1; 
          if(10==rbuf) 
             Receive_command.r_flag_end2=1; 
          r_flag= (1==Receive_command.r_flag_end1) && (1==Receive_command.r_flag_end2); 
          if(1==r_flag) 
            { 
                Receive_command.r_flag_end1=0; 
                Receive_command.r_flag_end2=0; 
                AnalysisCommand(); 
            }    
       } 
     else 
       { 
           if((1==Receive_command.r_flag_end1)||(1==Receive_command.r_flag_end2)) 
             { 
                 Receive_command.r_flag_end1=0; 
              Receive_command.r_flag_end2=0; 
              for(i=0;i<Receive_command.index;i++) 
            Receive_command.comm_infor[i]='\0'; 
              Receive_command.index=0;                                        // count set 0    
           }  
        Receive_command.comm_infor[Receive_command.index]=rbuf; 
        Receive_command.index++ ; 
        if(Receive_command.index>=Receive_command.index_end)      // avoid array overflow 
           { 
               for(i=0;i<Receive_command.index;i++) 
              Receive_command.comm_infor[i]=0; 
               Receive_command.index=0;   
           }  
    } 
} 
void DisposeValue(ulint temp_data) 
{ 
 uchar value[20]={0};   
    signed char i=0; 
 if(temp_data==0) 
  { 
      if(TestAllFlag) 
     SendString("Light is Weak , Please check! "); 
    else 
     SendString("Light is Weak , Please check! \r "); 
   count=0;  
   ConvertFlag=1; 
   return ; 
  }  
 temp_data=temp_data*50;                // time 20ms   100% output 
    while(temp_data!=0) 
     {  
       value[i]=temp_data % 10; 
   temp_data=temp_data / 10; 
   i++; 
  } 
    ShowValue(&value[0],i-1); 
} 
void ShowValue(uchar *p , signed char j) 
{ 
 while(j>=0) 
      { 
      SendChar(0x30+(*(p+j)));  
   if(j==3) 
    SendChar('.');  
   j=j-1; 
   } 
  if(TestAllFlag) 
   SendString("  KHz  "); 
  else 
   SendString("  KHz  \r"); 
  count=0;   
  ConvertFlag=1; 
} 
/************************ delayms *****************************************/ 
void delayms(uint z) 
{    
 uint i,j; 
   for(i=1;i<z;i++) 
   for(j=1;j<(uint)(7.3728*143-2);j++);     // 7.3728 Mhz 
} 
/************************ interrupt *************************************/ 
#pragma interrupt_handler TC2COMP: 4   
void TC2COMP(void) 
{  
 count = TCNT1 ; 
 TIMSK &= ~BIT(OCIE2);                                 // unable TC2 
 TCCR1B &=  ~BIT(CS12) + ~BIT(CS11) + ~BIT(CS10);      // unable TC1 
 ConvertFlag=1; 
} 
#pragma interrupt_handler UARTReceive: 12   
void UARTReceive(void) 
{  
   Receive(UDR); 
} |   
     
  
 |