簡易數字頻率計的設計
頻率測量的方法常用的有測頻法和測周法兩種。
測頻法的基本思想是讓計數器在閘門信號的控制下計數1秒時間,計數結果是1秒內被測信號的周期數,即被測信號的頻率。若被測信號不是矩形脈沖,則應先變換成同頻率的矩形脈沖。測頻法的原理框圖如圖所示。
圖中,秒脈沖作為閘門信號,當其為高電平時,計數器計數;低電平時,計數器停止計數。顯然,在同樣的閘門信號作用下,被測信號的頻率越高,測量誤差越小。當被測頻率壹定時,閘門信號高電平的時間越長,測量誤差越小。但是閘門信號周期越長,測量的響應時間也越長。
2、當被測信號頻率較低時,為保證測量精度,常采用測周法。即先測出被測信號的周期,再換算成頻率。測周法的實質是把被測信號作為閘門信號。
在它的高電平的時間內,用壹個標準頻率的信號源作為計數器的時鐘脈沖。若計數結果為N,標準信號頻率為f1,則被測信號的周期為:T = T1·N。被測信號的頻率為:f = 1/T1·N = f1/N。
利用測周法所產生的最大絕對誤差,顯然也等於±1個標準信號周期。如果被測信號周期的真值為T真= T1·N,則T測= T1·(N±1)σmax= (f測-f真)/ f真= T真/T測 – 1=±1/(N±1)由上式可知,對於壹定的被測信號,標準信號的頻率越高,則N的值越大,因而相對誤差越小。
3、低頻段的測量,鑒於上述困難,對於低頻信號,為了達到規定的精度,要采取壹些比較特殊的方法。例如,可考慮將被測信號倍頻後再用測頻法測量。
或將閘門信號展寬。由於倍頻電路比較復雜,所以壹般采用後壹種方法,實際上閘門信號展寬與被測信號倍頻在效果上是相同的。
閘門信號展寬比較容易做到,例如采用分頻電路就可以實現。若閘門信號高電平時間從1秒展寬到10秒,則相對誤差可以按比例下降,但響應時間也增大相同的比例。
4、顯示方式:***用右邊四個數碼管,左三個顯示數據,最右端壹個顯示單位,為0時單位為Hz,為1時單位為Khz
5、代碼:
//#include<c8051F330.h>
#include<ZLG7289.h>
#include<init.h>
#define uint unsigned int
uint a,b,c,d;
unsigned long? x;
unsigned long? count;
unsigned char flag=0;
void Timer0_Init()interrupt 1
{
TH0=(65535-10000)/256;
TL0=(65535-10000)%256;
if(++count==40)
{
count=0; ?
TR1=0;
x=TH1*256+TL1; ?
TH1=0;
TL1=0;
TR1=1;
flag=1;
}
}
void show(void)
{if(x>=10&&x<100)
{
a=0;
b=x*10%100;
c=x/10;
d=x%10;
ZLG7289_Download(1,7,0,a);
ZLG7289_Download(1,6,0,b);
ZLG7289_Download(1,5,1,d);
ZLG7289_Download(1,4,0,c);
}
else if(x>=100&&x<1000)
{
a=0;
b=x/100;
c=x%100/10;
d=x%10;
ZLG7289_Download(1,7,0,a);
ZLG7289_Download(1,6,1,d);
ZLG7289_Download(1,5,0,c);
ZLG7289_Download(1,4,0,b);
}
else if(x>=1000&&x<10000)
{
a=x/1000;
b=x%1000/100;
c=x%100/10;
d=1;
ZLG7289_Download(1,7,0,d);
ZLG7289_Download(1,6,0,c);
ZLG7289_Download(1,5,0,b);
ZLG7289_Download(1,4,1,a);
}
}
main(void)
{
system_init();
systemclk_init();
port_init();
ZLG7289_Init(40);
ZLG7289_Reset();
timer_init();
while(1)
{
if(flag==1)
{
show();
flag = 0;
}
}}
#include <C8051F330.h>
#include <port.h>
void system_init()
{
PCA0MD&=~0x40;
}
void systemclk_init()
{
OSCICL=OSCICL+42; //設置內部振蕩器為24MHZ
OSCICN|=0x01;? //內部振蕩器4分頻
}
void port_init()
{?
P0SKIP=0x00;? //跳過P0.0做INT0.P0.1做INT1(P0.6,P0.7模擬輸出不跳)
P1SKIP=0x00;? //跳過P1.2,P1.3,P1.4
XBR0=0x00; //交叉開關使能UART0
XBR1=0x60; //打開交叉開關
//IT01CF=0x10; //INT0配置在P0.0,INT1配置在P0.1
P0MDIN=0xFF; //數字輸入
P1MDIN=0xFF;
P0MDOUT=0xFF; //推挽
P1MDOUT=0xFF;
}
void timer_init()
{
TMOD=0X51;
TH0=(65535-2500)/256;
TL0=(65535-2500)%256;
EA=1;
ET0=1;
TR1=1;
TR0=1;
}
#ifndef __port_H_
#define __port_H_
void system_init(void);
void systemclk_init(void);
void port_init(void);
void timer_init(void);
#endif