//**********头文件区************
#include<reg52.h>
#include<math.h>
#include<absacc.h>
#include<intrins.h>
//*********宏定义方便使用*******
#define uchar unsigned char
#define uint unsigned int
//*********定义变量区***********
//sbit dula=P2^6; //数码管段选
//sbit wela=P2^7; //数码管位选
sbit lcden=P2^2; //LCD使能信号
sbit lcdrs=P2^0; //LCD数据/命令选择信号
sbit k5=P3^7; //按键
sbit sign=P3^4; //T0外部时钟信号输入脚 脉宽
//当外部输入脉冲产生由1至0的负跳变时计数器值加1
unsigned long int f,p,w; //Frequency,Period,Pulse Width(频率、周期、脉冲宽度)
uchar k,count,key=0;
uint zk; //占空比
uchar tab_freq[6]={0,0,0,0,0,0};
uchar tab_per[6]={0,0,0,0,0,0};
uchar tab_puw[6]={0,0,0,0,0,0};
uchar tab_duty[]={0,0,0};
uchar code tab_sf[]="Signal Frequency"; //第一行显示
uchar code tab_num[]="0123456789";
uchar code tab_f[]="Freq:"; //Frequency
uchar code tab_pe[]="Period:"; //Period
uchar code tab_pw[]="Pulse:"; //Width
uchar code tab_du[]="dutyfactor:"; //dutyfactor
uchar code tab_nop[]=" "; //blank
uchar code tab_point[]="."; //point
uchar code tab_hz[]="Hz"; //Hz
uchar code tab_us[]="us"; //us
uchar code tab_bf[]="%"; //%
//===========================================================
//*********函数声明区***********
//------LCD显示-----
void lcd_dis(); //lcd显示函数
void lcd_init(); //LCD初始化函数
void write_com(uchar); //写命令函数
void write_data(uchar); //写数据函数
void delay(uint); //延时函数
//------频率计-------
void int_count0(); //T0计数中断函数
void int_time1(); //T1定时中断函数
void trans_count(); //数据转换函数
void freq_key(); //测试启动及频率周期切换
//=========================================================
//*********主函数开始************
void main()
{
//dula=0;
//wela=0;
lcd_init(); //LCD初始化
write_com(1); //显示清屏,所有现有显示清除,指针清零
TMOD=0x15; //设置模式 T1作定时器--13位计数器
//T0作计数器--16位计数器
EA=1;
ET0=1;
ET1=1;
while(1)
{
freq_key(); //按键函数
trans_count(); //数据转换函数
lcd_dis(); //显示函数
}
}
//==========================================================
//*********T0计数中断函数开始*****
void int_count0() interrupt 1
{
k++; // 外部计数中断
if(key==2) //测周期
{
TR1=0;
TR0=0;
}
}
//*********T1计时中断函数开始**********
void int_time1() interrupt 3
{
count++;
if(key==1) //测频率
{
TH1=0x4c;
TL1=0x00; //50ms初值
if(count>=20) //计算1S内的频率
{
TR0=0;
TR1=0;
count=0;
}
}
}
//============================================================================
//*********数据转换函数开始*******
void trans_count()
{
if(key==1) //测频率
{
f=k*65536+TH0*256+TL0; //由定时器定时1S,在1S内看计数器0产生了(K)次中段,再加上
//TH0和TL0的值即可求出1S钟里面得脉冲数量,即频率
if(f>=999999) //超过最大量程显示999999
{f=999999;}
tab_freq[0]=f/100000; //十万位
tab_freq[1]=(f%100000)/10000; //万位
tab_freq[2]=(f%10000)/1000; //千位
tab_freq[3]=(f%1000)/100; //百位
tab_freq[4]=(f%100)/10; //十位
tab_freq[5]=f%10; //个位
}
//-------------------------
if(key==2) //测周期
{
p=((count*65536+TH1*256+TL1)*12000)/110592; //11.0592每个机器周期时间为:12/11.0592 us
if(p>=999999)
{p=999999;}
tab_per[0]=p/100000; //十万位
tab_per[1]=(p%100000)/10000; //万位
tab_per[2]=(p%10000)/1000; //千位
tab_per[3]=(p%1000)/100; //百位
tab_per[4]=(p%100)/10; //十位
tab_per[5]=p%10; //个位
}
//----------------------------
if(key==3)
{
w=((count*65536+TH1*256+TL1)*120000)/110592; //测脉冲宽度
if(w>=999999)
{w=999999;}
tab_puw[0]=w/100000; //十万位
tab_puw[1]=(w%100000)/10000; //万位
tab_puw[2]=(w%10000)/1000; //千位
tab_puw[3]=(w%1000)/100; //百位
tab_puw[4]=(w%100)/10; //十位
tab_puw[5]=w%10; //个位
}
//------------------------------
if(key==4) //测占空比
{
zk=(w*1000)/p; //脉宽/周期
tab_duty[0]=zk/100; //十位
tab_duty[1]=(zk%100)/10; //个位
tab_duty[2]=zk%10; //小数点后一位
}
}
//===============================================================
//*********延时函数开始************
void delay(uint a)
{
uint i,n;
for(i=a;i>0;i--)
for(n=110;n>0;n--);
}
//*********按键函数开始*************
void freq_key()
{
if(k5==0)
{
delay(10); //延时消抖
if(k5==0)
{
key++;
while(k5==0); //松手检测
if(key==1) //首次按键测频率
{
k=0;
count=0;
TH0=0x00;
TL0=0X00; //T0计数初值
TH1=0x4c;
TL1=0X00; //50ms定时初值 */
TR0=1;
TR1=1;
}
if(key==2) //二次按键测试周期
{
k=0;
count=0; //变量清0
TH0=0xff;
TL0=0Xf5; //T0计数初值,检测10个周期时间
TH1=0x00;
TL1=0X00; //T1计时初值
TR0=1;
while(TL0==0xf5); //确保当外部时钟信号来下降沿时,T1开始计数
TR1=1; //T1开始计数
}
if(key==3) //三次按键测脉冲宽度
{
k=0;
count=0;
TH0=0xff;
TL0=0Xf5; //T0
TH1=0x00;
TL1=0X00; //T1
TR0=1;
while(TL0==0xf5); //当外部时钟信号下降沿来临
while(sign==0); //当外部时钟信号为高电平时
TR1=1; //T1开始计数
while(sign==1); //当外部时钟信号为低电平时
TR1=0; //T1,T0停止计数
TR0=0;
}
if(key>=5) //五次按键显示0
{
f=0;
p=0;
w=0;
key=0;
}
}
}
}
//=====================================================================
//*********lcd显示函数开始******
void lcd_dis()
{
uchar i;
write_com(0x80);
for(i=0;i<16;i++)
{
write_data(tab_sf[i]); //显示"Signal Frequency"
}
//----------------------------------
if(key==0) //显示频率
{
write_com(0x80+0x40);
for(i=0;i<5;i++)
{
write_data(tab_f[i]); //显示"Freq:";
}
write_com(0x80+0x40+5);
for(i=0;i<6;i++)
{
write_data(tab_num[0]); //显示频率值
}
write_com(0x80+0x40+5+6);
for(i=0;i<2;i++)
{
write_data(tab_hz[i]); //显示"Hz";
}
write_data(tab_nop[0]);
write_data(tab_nop[0]);
write_data(tab_nop[0]);
}
write_com(0x80+0x40);
//------------------------------------
if(key==1) //显示频率
{
write_com(0x80+0x40);
for(i=0;i<5;i++)
{
write_data(tab_f[i]); //显示"Freq:";
}
write_com(0x80+0x40+5);
for(i=0;i<6;i++)
{
write_data(tab_num[tab_freq[i]]); //显示频率值
}
write_com(0x80+0x40+5+6);
for(i=0;i<2;i++)
{
write_data(tab_hz[i]); //显示"Hz";
}
write_data(tab_nop[0]);
write_data(tab_nop[0]);
write_data(tab_nop[0]);
}
write_com(0x80+0x40);
//-----------------------------------
if(key==2) //显示周期
{
write_com(0x80+0x40);
for(i=0;i<7;i++)
{
write_data(tab_pe[i]); //显示"Period:"
}
write_com(0x80+0x40+7);
for(i=0;i<6;i++)
{
write_data(tab_num[tab_per[i]]); //显示周期值
}
write_com(0x80+0x40+7+6);
for(i=0;i<2;i++)
{
write_data(tab_us[i]); //显示"us";
}
write_data(tab_nop[0]);
}
write_com(0x80+0x40);
//---------------------------------------
if(key==3) //显示脉宽
{
write_com(0x80+0x40);
for(i=0;i<6;i++)
{
write_data(tab_pw[i]); //显示"Pulse:"
}