用STC89C52的定时器及计数器做频率计无法测准400Khz以上频率?
昨天用51写了个测量频率的程序,晶振12M。测量500Hz到400KHz范围内的频率都达到了所需要的精度。例如测量400K时误差在0.5K以内。在测量500K时误差也不大。但是测量420K至500K之间的频段时误差就很大了。可以达到20K。这是为什么? 显示用的是12864,处理完数据才慢悠悠地显示,因而显示环节应该没有问题。 附源程序:#include <reg52.h>
#include "LCD_Dis.h"
char i=0;
float frq=0;
unsigned char timeflag=0;
void err()//显示err
{
FontSet(1,1);
SetBackLight(50);
PutChar(0,0,0x45);
PutChar(X_Witch,0,0x52);
PutChar(2*X_Witch,0,0x52);
}
void dis(float r)//在LCD上显示浮点数
{
int i=0;
int disx=122,disy=3;
long int s;
// r=r*100.0;
// ClrScreen();
s=r*1000000;
while(i<6)
{ i++;
PutChar(disx,disy,0x30+(s%10));
s=s/10;
disx=disx-X_Witch;
}
//以下为显示小数点指令
SPI_SSSet(0); //SS置低电平
SPI_Send(1); //传送指令0x07
SPI_Send(disx+X_Witch/2); //要显示字符的左上角的X轴位置
SPI_Send(disy+Y_Witch-3); //要显示字符的左上角的Y轴位置
disx=disx-X_Witch;
SPI_SSSet(1); //完成操作置SS高电平
s=r;
while((s/10)!=0)
{
PutChar(disx,disy,0x30+(s%10));
s=s/10;
disx=disx-X_Witch;
}
PutChar(disx,disy,0x30+s);
disx=disx-X_Witch;
}
void time() interrupt 1 //低频信号将进入此中断
{
TR1=0;
timeflag+=1;
if(timeflag>=200)
{ frq=(i+1.0)*1024.0*1000000.0/(timeflag*65536.0+4); //估计修正值4us
dis(frq);
while(1);
}
else
{
TR0=1;
TR1=1;
}
}
float calcfrq()//calculate frequency
{
float frequency;
frequency=((i+1.0)*1024.0*1000000.0/(TH0*256.0+TL0+timeflag*65536.0)*1.01626-1626);
return frequency;
}
void count() interrupt 3//高频信号进入此中断
{
TR0=0;
if(TH0<40)
{
TH1=TH1-0x04*(i+1);//测量时间太短时延长测量时间
i++;
TL1=0x00;
TH0=0x00;
TL0=0x00;
TR1=1;
TR0=1;
}
else
{
frq=calcfrq();
dis(frq);
while(1);
}
}
void main()
{
int i=0;
EA=1;
ET0=1;
ET1=1;
TMOD=0x51;
LCD_Init();
ClrScreen();
SetBackLight(60);
FontSet(1,1);
TH0=0x00;
TL0=0;
TH1=0xfc;
TL1=0x00;
TR1=1;
TR0=1;
while(1)
{
for(i=255;i<0;i--)
;
}
} 计数器最高输入频率只能到晶振的1/24,换24M晶振吧,要不先用分频器分频 我12M 40K都做不上去 先用74HC4040做分频后再送到外中断,在程序中乘以原分频值,得到原来的频率,想是这样啊,没玩过。 mark 回复【3楼】chess01=CHESS
-----------------------------------------------------------------------
试了一下果然是。。。换了个手头有的22.1184就达到700k了。、
谢谢~~ 回复【6楼】lcmdw
-----------------------------------------------------------------------
这个有什么好Mark。。。 3楼,然后就6楼了。。。 今天也写了这个程序~~ STC89C52
设成6T的,不是相当于24MHz,能测500KHz以上吗? it can easily measure frequencies in excess of 1Mhz.
you just need to know how to code correctly. { frq=(i+1.0)*1024.0*1000000.0/(timeflag*65536.0+4); //估计修正值4us ???
在中断程序中跑浮点运算?这不扯淡嘛!
还有在中断3里出现了如下的代码:
else
{
frq=calcfrq();
dis(frq);
while(1);
}
别把什么显示、计算的功能放在中断里,中断里的程序越简洁越好。
使用单片机的定时器2之16位自动重载方式来定时,保证计时精确。T1和T2用来记录脉冲,在12MHz时测量500KHz以下绝对精确。
页:
[1]