標題:
我做的單片機頻率計 MB506+BF998
[打印本頁]
作者:
banqiao
時間:
2023-5-25 14:55
標題:
我做的單片機頻率計 MB506+BF998
電路原理圖.gif
(166.42 KB, 下載次數(shù): 57)
下載附件
2023-5-25 15:24 上傳
/********************************************************
項 目:51單片機頻率計
單片機:STC89c52RC
元 件:24MHZ晶振、1602液晶、MB506超高頻分頻器、
74HC393二進制脈沖計數(shù)器、BF998雙刪極場效應管、
74HC14施密特觸發(fā)器。
設計思路:參考網(wǎng)上“diy頻率計”帖子重新整理編程。利
用T0做定時器、T2做計數(shù)器,在一秒內(nèi)T2計數(shù)脈沖
數(shù)計算頻率
測試信號頻率32MHZ到2.4GHZ時,開關(guān)撥到高頻位置,
信號經(jīng)MB506放大分頻再輸入到BF998放大——74HC14整
形——74HC393計數(shù)后由Q1Q2Q3Q4送到單片機的P14 P15
P16 P17腳,其中Q4也送到單片機的P1.0腳,從
而記錄Q4的脈沖個數(shù),計算出信號頻率。
測試信號頻率低于32MHZ時,開關(guān)撥到低頻位置,
被測試信號不經(jīng)過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表示本次測試結(jié)束,可進行下次測試
/****************以下延時函數(shù)******************/
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) //寫數(shù)據(jù)
{
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位數(shù)據(jù)接口
yanshi500us(10);
lcdrw_com(0x38);
yanshi500us(10);
lcdrw_com(0x38);
yanshi500us(10);
lcdrw_com(0x08); //關(guān)閉顯示
lcdrw_com(0x01); //清屏
lcdrw_com(0x06); //讀寫一個字符后指針加一光標加一
lcdrw_com(0x0c); //開顯示,顯示光標,光標閃爍
for(i=0;i<17;i++)
{
lcdrw_dat(table[i]); //寫第一行數(shù)據(jù)f= M K HZ
}
lcdrw_com(0x80+0x40); //第二行起始位
for(i=0;i<16;i++)
{
lcdrw_dat(table1[i]); //寫第二行數(shù)據(jù)T= u n ps
}
}
/*******************定時器0中斷服務函數(shù)**********************/
void tim0_isr (void) interrupt 1 using 1//定時器0中斷服務函數(shù)
{
unsigned int fl;
float ff; //用于計算帶小數(shù)點的頻率
irtime++; //用于計數(shù)2個下降沿之間的時間
if(k200Hz==0)
{
if(jishu==2)
{
TR0=0;
TR2=0;
ff=4000000.00/((irtime)*25); //精確到小數(shù)點后兩位
f=ff*100; //使000.00類型的小數(shù)變?yōu)?0000整數(shù),
//從而容易分解個十百整數(shù)及小數(shù)點后兩位小數(shù)
// 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個脈沖的脈沖數(shù)
TR2=0; //關(guān)計數(shù)器2
TR0=0; //關(guān)定時器0
irtime=0;
fl=P1>>4; //少于16個脈沖的脈沖數(shù)
f=((jishu*65536+(TH2*256+TL2))*16+fl)/2;//2秒內(nèi)總脈沖數(shù)即頻率
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; //開計數(shù)器2
TR0=0; //關(guān)定時器0
}
else
{
TH0=0x38;//初始值
TL0=0x38;//自動重裝值,定時100um
TR2=1; //開計數(shù)器2
TR0=1; //開定時器0
}
}
/*******************T2計數(shù)器初始化***********************/
void t2Init(void) //t2初始化
{
TR2=0; //停止計數(shù)器2
T2CON=0x2; //計數(shù)器
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計數(shù)器***************************/
void timer2() interrupt 5
{
TF2=0; //!!!注意!!! 定時器2必須由軟件對溢出標志位清零,硬件不能清零,這里與定時器0和定時器1不同!!!
jishu++;//T2中斷次數(shù),如果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();
}
}
}
復制代碼
作者:
fsj5098
時間:
2023-5-25 20:06
為何不做成等精度頻率計呢
歡迎光臨 (http://www.torrancerestoration.com/bbs/)
Powered by Discuz! X3.1