标题:各位大侠,AVR 单片机测量频率的问题,求教一下,麻烦啦。
只看楼主
sol2010
Rank: 1
等 级:新手上路
帖 子:3
专家分:0
注 册:2012-2-27
 问题点数:0 回复次数:1 
各位大侠,AVR 单片机测量频率的问题,求教一下,麻烦啦。
各位大侠好:
   小弟编写了一个测量频率的程序,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_ ,"on"))) || (0==(strcmp( Receive_ ,"ON"))))
           {   
            Led_ON;
            Beep_ON;
            SendString("Led ON");
            SendChar('\r');
        }
       else if((0==(strcmp( Receive_ ,"off")))||(0==(strcmp( Receive_ ,"OFF"))))
           {   
           Led_OFF;
           Beep_OFF;
           SendString("Led OFF");
           SendChar('\r');
        }
       else
          {
            SendString(CommandPrompt);
            for(i=0;i<Receive_command.index;i++)
                Receive_[i]='\0';
              Receive_command.index=0;
            return ;   
        }
     for(i=0;i<Receive_command.index;i++)
         Receive_[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_[i]='\0';
                 Receive_command.index=0;                                        // count set 0            
              }   
           Receive_[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_[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);
}
搜索更多相关主题的帖子: 测量 主程序 
2012-07-16 19:46
鸥翔鱼游
Rank: 5Rank: 5
等 级:职业侠客
帖 子:182
专家分:323
注 册:2014-4-19
得分:0 
学习学习~~~偷师本学徒来偷偷~~~
2014-04-26 14:20



参与讨论请移步原网站贴子:https://bbs.bccn.net/thread-373529-1-1.html




关于我们 | 广告合作 | 编程中国 | 清除Cookies | TOP | 手机版

编程中国 版权所有,并保留所有权利。
Powered by Discuz, Processed in 0.547152 second(s), 7 queries.
Copyright©2004-2024, BCCN.NET, All Rights Reserved