- /********************************************************
- 项 目:51单片机频率计
- 单片机:STC89c52RC
- 元 件:24MHZ晶振、1602液晶、MB506超高频分频器、
- 74HC393二进制脉冲计数器、BF998双删极场效应管、
- 74HC14施密特触发器。
- 设计思路:参考网上“diy频率计”帖子重新整理编程。利
- 用T0做定时器、T2做计数器,在一秒内T2计数脉冲
- 数计算频率
- 测试信号频率32MHZ到2.4GHZ时,开关拨到高频位置,
- 信号经MB506放大分频再输入到BF998放大——74HC14整
- 形——74HC393计数后由Q1Q2Q3Q4送到单片机的P14 P15
- P16 P17脚,其中Q4也送到单片机的P1.0脚,从
- 而记录Q4的脉冲个数,计算出信号频率。
- 测试信号频率低于32MHZ时,开关拨到低频位置,
- 被测试信号不经过MB506直接到BF998放大,后面同上
- 编 程:
- ********************************************************/
- #include<at89x52.h>
- #define uchar unsigned char
- #define uint unsigned int
- unsigned char code table[]="f= M K Hz"; //兆hz 千hz
- unsigned char code table1[]="T= m u ns";//微妙 纳秒 皮秒
- unsigned char code table2[]="0123456789";
- sbit lcdrs=P2^7;
- sbit lcdrw=P2^6;
- sbit lcden=P2^5;
- sbit LS393_MR=P1^3;
- sbit k200Hz=P2^0;
- sbit GP=P2^1;
- sbit k=P1^2;
- unsigned int jishu,i;
- unsigned long f=0,T,irtime;
- bit a=0; //标志位,为1表示本次测试结束,可进行下次测试
- /****************以下延时函数******************/
- void yanshi500us(uint x)
- {
- uint y;
-
- for(x;x>0;x--)
- for(y=122;y>0;y--);
- }
- void delay1s(void) //误差 0us
- {
- unsigned char a,b,c,n;
- for(c=167;c>0;c--)
- for(b=39;b>0;b--)
- for(a=152;a>0;a--);
- for(n=1;n>0;n--);
- }
- //================以下是LCD操作=========================
- void read_busy() /*LCD1602 忙等待*/
- {
- lcdrs = 0;
- lcdrw = 1;
- lcden = 1;
- P0 = 0xff;
- while (P0&0x80);
- lcden = 0;
- }
-
- void lcdrw_com(unsigned char com) //写命令
- {
- read_busy();
- lcdrw=0;
- lcdrs=0;
- P0=com;
- yanshi500us(1);
- lcden=1;
- yanshi500us(1);
- lcden=0;
- // lcdrs=1;
- yanshi500us(10);
- }
-
- void lcdrw_dat(unsigned char dat) //写数据
- {
- read_busy();
- lcdrw=0;
- lcdrs=1;
- P0=dat;
- yanshi500us(1);
- lcden=1;
- yanshi500us(2);
- lcden=0;
- // lcdrs=1;
- yanshi500us(10);
- }
- void write_lcd(uchar COM,uchar dat)//向LCD写一个字
- {
- lcdrw_com(COM);
- lcdrw_dat(dat);
-
- }
-
- void lcdinit()
- {
- yanshi500us(30);
- lcdrw_com(0x38); //设置16*2屏显,5*7点阵,8位数据接口
- yanshi500us(10);
- lcdrw_com(0x38);
- yanshi500us(10);
- lcdrw_com(0x38);
- yanshi500us(10);
- lcdrw_com(0x08); //关闭显示
- lcdrw_com(0x01); //清屏
- lcdrw_com(0x06); //读写一个字符后指针加一光标加一
- lcdrw_com(0x0c); //开显示,显示光标,光标闪烁
-
- for(i=0;i<17;i++)
- {
- lcdrw_dat(table[i]); //写第一行数据f= M K HZ
- }
-
- lcdrw_com(0x80+0x40); //第二行起始位
- for(i=0;i<16;i++)
- {
- lcdrw_dat(table1[i]); //写第二行数据T= u n ps
- }
-
- }
- /*******************定时器0中断服务函数**********************/
- void tim0_isr (void) interrupt 1 using 1//定时器0中断服务函数
- {
- unsigned int fl;
- float ff; //用于计算带小数点的频率
- irtime++; //用于计数2个下降沿之间的时间
- if(k200Hz==0)
- {
- if(jishu==2)
- {
- TR0=0;
- TR2=0;
- ff=4000000.00/((irtime)*25); //精确到小数点后两位
- f=ff*100; //使000.00类型的小数变为00000整数,
- //从而容易分解个十百整数及小数点后两位小数
- // f=4*f;
-
- if(irtime==0)
- {
- f=0;T=0;
- }
- else
- T=(1000000000/ff); //周期ns
- a=1;
- delay1s();
- }
- }
- else
- {
- if(irtime==20000) //计时够2秒
- {
- fl=P1>>4; //少于16个脉冲的脉冲数
- TR2=0; //关计数器2
- TR0=0; //关定时器0
- irtime=0;
-
- fl=P1>>4; //少于16个脉冲的脉冲数
- f=((jishu*65536+(TH2*256+TL2))*16+fl)/2;//2秒内总脉冲数即频率
- if(GP==0)
- {
- f=2*f*64;
- }
- else
- f=2*f;
- if(f==0)
- T=0;
- else //下载时使用6T模式
- T=1000000000/f; //周期ns
- a=1;
- }
- }
- }
- void TIM0init(void)//定时器0初始化
- {
- TMOD=0x02;//定时器0工作方式2,8位初值自动重装,TH0是重装值,TL0是初值
- ET0=1; //开中断
-
- if(k200Hz==0)
- {
- TH0=0xce;//初始值
- TL0=0xce;//自动重装值,定时25um
- TR2=1; //开计数器2
- TR0=0; //关定时器0
- }
- else
- {
- TH0=0x38;//初始值
- TL0=0x38;//自动重装值,定时100um
- TR2=1; //开计数器2
- TR0=1; //开定时器0
- }
- }
-
- /*******************T2计数器初始化***********************/
- void t2Init(void) //t2初始化
- {
- TR2=0; //停止计数器2
- T2CON=0x2; //计数器
- T2MOD=0x00;
-
- if(k200Hz==0)
- {
- RCAP2H=0xff;
- RCAP2L=0xfe; // 自动重装,接收1个脉冲中断
- }
- else
- {
- RCAP2H=0x0;
- RCAP2L=0x0; // 自动重装,接收65536个脉冲中断
- }
- TH2=RCAP2H;
- TL2=RCAP2L; //定时器2赋初值
- EA=1; //开总中断
- ET2=1; // 开外定时器2中断
- }
- /*********************T2计数器***************************/
- void timer2() interrupt 5
- {
- TF2=0; //!!!注意!!! 定时器2必须由软件对溢出标志位清零,硬件不能清零,这里与定时器0和定时器1不同!!!
- jishu++;//T2中断次数,如果k200Hz=0,来一个脉冲中断一次,否则65536个脉冲中断一次
- if(k200Hz==0)
- {
- if(jishu==1) //收到第一个脉冲时开启计时器
- {
- TR0=1;
- }
- }
- }
- /*****************74LS393 复位*******************/
- void LS393_rest()
- {
- LS393_MR=0;
- LS393_MR=1;
- LS393_MR=0;
- }
- void main()
- {
- yanshi500us(100);
- lcdinit();
- t2Init();
- TIM0init();
-
- yanshi500us(100);
- LS393_rest();
- while(1)
- {
- if(k200Hz==0)
- {
- write_lcd(0x80+9,'z');
- write_lcd(0x80+8,'H');
- write_lcd(0x80+5,'.');
- write_lcd(0x80+10,' ');
- write_lcd(0x80+14,' ');
- write_lcd(0x80+15,' ');
-
- write_lcd(0x80+2,table2[f%100000/10000]);
- write_lcd(0x80+3,table2[f%10000/1000]);
- write_lcd(0x80+4,table2[f%1000/100]);
- write_lcd(0x80+6,table2[f%100/10]);
- write_lcd(0x80+7,table2[f%10]);
- delay1s();
-
- }
- /********************以下显示频率*********************/
- else
- {
- write_lcd(0x80+2,table2[f/1000000000]);
- write_lcd(0x80+3,table2[f%1000000000/100000000]);
- write_lcd(0x80+4,table2[f%100000000/10000000]);
- write_lcd(0x80+5,table2[f%10000000/1000000]);
- write_lcd(0x80+7,table2[f%1000000/100000]);
- write_lcd(0x80+8,table2[f%100000/10000]);
- write_lcd(0x80+9,table2[f%10000/1000]);
- write_lcd(0x80+11,table2[f%1000/100]);
- write_lcd(0x80+12,table2[f%100/10]);
- write_lcd(0x80+13,table2[f%10]);
- }
- /**********************以下显示周期***************************/
- write_lcd(0x80+0x40+2,table2[T/1000000000]);
- write_lcd(0x80+0x40+3,table2[T%1000000000/100000000]);
- write_lcd(0x80+0x40+4,table2[T%100000000/10000000]);
- write_lcd(0x80+0x40+5,table2[T%10000000/1000000]);
- write_lcd(0x80+0x40+7,table2[T%1000000/100000]);
- write_lcd(0x80+0x40+8,table2[T%100000/10000]);
- write_lcd(0x80+0x40+9,table2[T%10000/1000]);
- write_lcd(0x80+0x40+11,table2[T%1000/100]);
- write_lcd(0x80+0x40+12,table2[T%100/10]);
- write_lcd(0x80+0x40+13,table2[T%10]);
- if(a==1)
- {
- a=0;
- jishu=0;
- irtime=0;
- t2Init();
- LS393_rest();
- TIM0init();
- }
- }
- }
复制代码
|