📄 liulei.c
字号:
/*本程序显示的结果和实验室里信号发生器的显示一致,
根据频率的不同分别显示到小数点后一位,两位,或三位。*/
#include <reg51.h>
#define uchar unsigned char
#define uint unsigned int
#define ulong unsigned long
sbit P24=P2^4;
uchar time=80;//测频时定时时间4S(80*0.05)
uchar j=0;//显示位数
uint count=0;//计数值的高位
uchar putout[8];//显示缓存
uchar FLAG;//测量方式标志
float temp;//数据处理时的中间结果
void out(void);
void mea_freq(void) interrupt 0 using 0 //外中断0服务子程序
{FLAG=1;//测频方式置标志FLAG为1
P0=0;//灭数码管
IE1=0;IT1=1;IE0=0;IT0=1;//关TRO,TR1,置外中断请求触发方式为脉冲后沿负跳有效
TMOD=0X51;//定时器T0工作方式1,计数器T1工作方式1
TH0=0X3C; TL0=0XB0;
TH1=0; TL1=0;
//TCON=0X55;//开TR0,TR1
TR0=1;TR1=1;
return;
}
void mea_cycle(void) interrupt 2 using 0 //外中断1服务子程序
{FLAG=0;//测周方式置标志FLAG为0
P0=0;//灭数码管
// TCON=0X05;//关TRO,TR1,置外中断请求触发方式为脉冲后沿负跳有效
IE1=0;IT1=1;IE0=0;IT0=1;
TMOD=0X61;//计时器T0工作方式1,计数器T1工作方式2
TH0=0; TL0=0;
TH1=251; TL1=251;
TR1=1;//开计数器T1
while(252-TL1) ;//等待一个负跳变到来
TR0=1;//来了一个负跳变,开始计时。计4个脉冲的时间
return;
}
void t0_service(void) interrupt 1 using 1 //定时器0中断服务子程序
{
P0=0;//灭数码管
if(FLAG) //测频方式,定时器0溢出,判断是否定时时间到
{time--; TH0=0X3C; TL0=0XC8;
if(!time)//tiem=0则定时时间到
{//TCON=0X05;//关TR0,TR1
TR0=0;TR1=0;
out();//数据处理
//下一次测量初始化
TH0=0X3C; TL0=0XB0;
TH1=0; TL1=0;
count=0; time=80;
//TCON=0X55;//开TR0,TR1,开始定时,计数
TR0=1;TR1=1;
}
}
else //测周方式,计时器0溢出,计时高位加1
count++;
return;
}
void t1_service(void) interrupt 3 using 2 //计数器1中断服务子程序
{P0=0;//灭数码管
if(FLAG) //测频方式,计数器1溢出,计数高位加1
count++;
else //测周方式,计4个脉冲到后溢出
{//TCON=0X05;//关TR0,TR1
TR0=0;TR1=0;
out();//数据处理
//下一次测量初始化
TH0=0; TL0=0;
TH1=251; TL1=251;
TR1=1; count=0;
while(252-TL1) ;
TR0=1;
}
return;
}
void delay_ms(uchar i) //延时子程序
{uchar k;
while(i--)
{for(k=0;k<125;k++) ; }
return;
}
void out(void) using 3
{ulong result;
uchar i;
if(FLAG)//测频方式的数据处理,计算1S的脉冲数
{temp=(float)(count*65536+TH1*256+TL1)/4;
//频率<10,则扩大1000倍后取整,即显示三位小数
if(temp<10) result=(ulong)(temp*1000);
//10<=频率<100,则扩大100倍后取整,即显示两位小数
else if(temp<100) result=(ulong)(temp*100);
//100<=频率<1000,则扩大10倍后取整,即显示一位小数
else if(temp<1000) result=(ulong)(temp*10);
//频率>=1000,则直接取整,只显示整数
else result=(ulong)temp;
}
else //测周方式的数据处理,计算1个脉冲的时间后取倒数
{temp=4e+6/(count*65536+TH0*256+TL0);
if(temp<10) result=(ulong)(temp*1000);//一般在频率<10时用测周方式,则总显示三位小数
else if(temp<100) result=(ulong)(temp*100);
else if(temp<1000) result=(ulong)(temp*10);
else result=(ulong)temp;
}
i=0; j=0;
while(result)//数据输出到显示缓冲区
{putout[i]=result%10;
result=result/10;
i++; j++;
}
while(j<4)
putout[j++]=0;//所得结果只有小数位时补置显示缓冲区低位至putout[3]位为0
return;
}
void display(void)
{uchar n;
uint bit_secl[8]={0x08,0x04,0x02,0x01,0x80,0x40,0x20,0x10};
for(n=0;n<j;n++) //显示数字
{
P0=bit_secl[n];
P2=putout[n];
delay_ms(1);
}
//显示小数点,P2口P24选中数码管的小数点
if(temp<10) {P0=0X01; P24=1;} //位选选中D3位的数码管
else if(temp<100) {P0=0X02; P24=1;} //位选选中D2位的数码管
else if(temp<1000) {P0=0X04; P24=1;} //位选选中D1位的数码管
delay_ms(1);
return;
}
void main(void)
{
FLAG=1;//默认测量方式为测频
//TCON=0X05;//关TRO,TR1,置外中断请求触发方式为脉冲后沿负跳有效
TR0=0;TR1=0;
TMOD=0X51;//定时器0方式1,计数器1方式1
count=0;//计数值的高位初始化
TH0=0X3C; TL0=0XB0;
TH1=0; TL1=0;
EA=1;ET1=1;ET0=1; EX1=1;EX0=1;//允许中断
TR0=1;TR1=1; IT1=1;IT0=1; //开始定时记数
for(;;)
{display();}
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -