打印
[AVR单片机]

各位大侠,AVR 单片机测量频率,求教一下,麻烦啦。

[复制链接]
1352|0
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主
sdcxy|  楼主 | 2012-7-16 19:40 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
各位大侠好:
   小弟编写了一个测量频率的程序,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);
}

相关帖子

发新帖 我要提问
您需要登录后才可以回帖 登录 | 注册

本版积分规则

2

主题

9

帖子

1

粉丝