各位大侠,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);
}