我想做一个51mcu 4位频率计,测1~9999hz方波,程序写好了,可以正常运行,显示正常。但是有个问题就是:当待测频率较小的时候,100hz左右时候没有误差,待测频率在1000hz左右时,测出来的相对误差大概1.6%,2000hz时候误差3.2%,3000hz时候5.3%,8000hz时候误差15%。频率越大,误差越大。但是误差是跟频率成正比的,所以我想给num乘以一个关于频率的函数,频率越高,此函数值越大,刚好就弥补了待测频率越高误差越大的缺陷。
但是void display()里面num一乘以double型变量就显示出错了,强制转换(uint)(num*x)类型也没用,还是显示不对。请问该怎么改?
//四位方波频率计
#include<reg52.h>
sbit dula=P2^6;
sbit wela=P2^7;
#define uint unsigned int
#define uchar unsigned char
uint num,a,b,c,d,k;//num作为一个全局变量//a b c d是千位到个位
//double num;
uchar code table[]={
0x3f,0x06,0x5b,0x4f,
0x66,0x6d,0x7d,0x07,
0x7f,0x6f,0x77,0x7c,
0x39,0x5e,0x79,0x71};
/*函数声明*/
void delay(uint);
void display();
uint read1();
/*主函数*/
void main()
{
TMOD=0x15; //0001 0101 定时器1,计数器0
TH1=(65536-45872)/256; //11.0592MHZ下装入45872才是50ms
TL1=(65536-45872)%256;
TH0=0;
TL0=0; //要用1个计数器,1个定时器
ET1=1;
EA=1;
TR0=1;
TR1=1;
while(1);
}
/*定时1s函数*/
void
timer0() interrupt 3
{
TR1=0;
TH1=(65536-45872)/256;
TL1=(65536-45872)%256;
k++;
if(k==20)
{
num=read1(); //num是计数个数
display();
k=0;
TH0=0;
TL0=0;
}
TR1=1;
}
/*前4位数码管显示函数*/
void display()
{
uint i;
for(i=100;i>0;i--)
{
num=(num*1); //在此处num乘以修正系数,不修正时NUM乘1
a=(num/1000);
b=((num%1000)/100);
c=(((num%1000)%100)/10);
d=(((num%1000)%100)%10);
dula=1; //千位
P0=table[a];
dula=0;
P0=0xff;
wela=1;
P0=0xfe;//1111 10
wela=0;
delay(5);
dula=1; //百位
P0=table[b];
dula=0;
P0=0xff;
wela=1;
P0=0xfd;//1111 01
wela=0;
delay(5);
dula=1; //十位
P0=table[c];
dula=0;
P0=0xff;
wela=1;
P0=0xfb;//1110 11
wela=0;
delay(5);
dula=1; //个位
P0=table[d];
dula=0;
P0=0xff;
wela=1;
P0=0xf7;//1101 11
wela=0;
delay(5);
wela=1;
P0=0xff;//1101 11
wela=0;
delay(5);
}
}
uint read1() //读计数器1的值
{
uint t1_1,th1_1,th2_1;
uint val_1;
while(1)
{
th1_1=TH0;
t1_1=TL0;
th2_1=TH0;
if(th1_1==th2_1)
break;
}
val_1=th1_1*256+t1_1;
return val_1;
}
/*延时函数*/
void delay(uint z)
{
uint x,y;
for(x=z;x>0;x--)
for(y=110;y>0;y--);
}
我是用一个单片机发出方波,从P2.0口输入到频率计P3.4口,这个口是单片机内部已经定义好做计数器外部输入的,所以程序里面没有写出来,直接连一根杜邦线就可以了。我现在就想把num乘以一个浮点数后再拿去数码管显示,不然误差太大,但是一乘之后最后显示出来的数就不断地在变,不知道怎么改
谢谢,现在这个错误已经改过来了
//由于是拿郭天祥C51单片机做的,段选P2.6位选,P2.7,6位数码管,选前四位显示频率。外部方波输入是P3.4口
//由于51单片机机器周期比较长,所以在测频率的时候会产生误差,而且待测频率越大,误差越大。测1000HZ以内时误差可稳定在1%100以内。测很高频率时候请自行乘以修正函数。我下面程序里面没有写,乘完之后显示的频率误差会小很多。
#include<reg52.h>
sbit dula=P2^6;
sbit wela=P2^7;
#define uint unsigned int
#define uchar unsigned char
double num,a,b,c,d,k;//num作为一个全局变量//a b c d是千位到个位
uchar code table[]={
0x3f,0x06,0x5b,0x4f,
0x66,0x6d,0x7d,0x07,
0x7f,0x6f,0x77,0x7c,
0x39,0x5e,0x79,0x71};
/*函数声明*/
void delay(uint);
void display();
uint read1();
/*主函数*/
void main()
{
TMOD=0x15; //0001 0101 定时器1,计数器0
TH1=(65536-45872)/256; //11.0592MHZ下装入45872才是50ms
TL1=(65536-45872)%256;
TH0=0;
TL0=0; //要用1个计数器,1个定时器
ET1=1;
EA=1;
TR0=1;
TR1=1;
while(1);
}
/*定时1s函数*/
void timer0() interrupt 3
{
TR1=0;
TH1=(65536-45872)/256;
TL1=(65536-45872)%256;
k++;
if(k==20)
{
num=read1(); //num是计数个数
display();
k=0;
TH0=0;
TL0=0;
}
TR1=1;
}
/*前4位数码管显示函数*/
void display()
{
uint i;
if(num<=200) num=num*1+num*(0.001);
if(num>200&&num<=500) num=num*1+num*(0.003); //在此处num乘以修正系数
if(num>500&&num<=1000) num=num*1+num*(0.008);
for(i=100;i>0;i--)
{
a=((uint)num/1000);
b=((uint)((uint)((uint)num%1000))/100);
c=((uint)((uint)((uint)num%1000)%100)/10);
d=((uint)((uint)((uint)num%1000)%100)%10);
dula=1; //千位
P0=table[(uint)a];
dula=0;
P0=0xff;
wela=1;
P0=0xfe;//1111 10
wela=0;
delay(5);
dula=1; //百位
P0=table[(uint)b];
dula=0;
P0=0xff;
wela=1;
P0=0xfd;//1111 01
wela=0;
delay(5);
dula=1; //十位
P0=table[(uint)c];
dula=0;
P0=0xff;
wela=1;
P0=0xfb;//1110 11
wela=0;
delay(5);
dula=1; //个位
P0=table[(uint)d];
dula=0;
P0=0xff;
wela=1;
P0=0xf7;//1101 11
wela=0;
delay(5);
wela=1;
P0=0xff;//1101 11
wela=0;
delay(5);
}
}
uint read1() //读计数器1的值
{
uint t1_1,th1_1,th2_1;
uint val_1;
while(1)
{
th1_1=TH0;
t1_1=TL0;
th2_1=TH0;
if(th1_1==th2_1)
break;
}
val_1=th1_1*256+t1_1;
return val_1;
}
/*延时函数*/
void delay(uint z)
{
uint x,y;
for(x=z;x>0;x--)
for(y=110;y>0;y--);
}
一周热门 更多>