数字频率计是能实现对周期性变化信号频率测量的仪器。传统的频率计通常是用很多的逻辑电路和时序电路来实现的,这种电路一般运行较慢,而且测量频率的范围较小。这篇文章介绍以单片机STC89C52为核心,通过对输入的脉冲进行计数,运用单片机的运算和控制功能并采用数码管将所测频率显示出来。软件方面采用C语言编程,运用定时计数器测量频率,再调显示函数,将测得的结果显示在数码管上。系统简单可靠、操作简易,能基本满足一般情况下的需要。既保证了系统的测频精度,又使系统具有较好的实时性。
本次设计主要分成两大方面:硬件电路的设计和软件程序的设计。硬件电路方面,采用STC89C52单片机最小系统,便可实现要求。程序的设计方面,采用C语言编写程序。其整体框图如图1所示:
此数字频率计是利用单片机的P3.4(T0)引脚作为被测矩形波信号输入端,且单片机晶振FOSC=12MHZ,当外部脉冲信号,即被测矩形波信号从P3.4进入单片机,同时启动定时器T0和计数器T1,T0是工作在计数状态下,对输入的频率信号进行计数,工作在计数状态下的T0的最大计数值为65535则:T0的最大计数频率为65535Hz,T1是工作在定时状态下,每定时1秒,就停止T1的计数,而从T1的计数单元中读取的计数值在进行数据处理后,送到数码显示管显示出来,因为T1工作在定时状态下的最大定时时间为65ms,达不到1秒的定时,所以采用50ms,共定时20次,即可完成1秒的定时功能。
如图所示,是在proteus软件数字频率计的仿真。
将要测量的脉冲输入单片机的P3.4引脚。
#include "reg52.h"
sbit L1 = P1^0;
sbit S1 = P3^2;
unsigned char code SMG_duanma[18]=
{0xc0,0xf9,0xa4,0xb0,0x99,0x92,0x82,0xf8,
0x80,0x90,0x88,0x80,0xc6,0xc0,0x86,0x8e,
0xbf,0x7f};
unsigned char count = 0;
unsigned int frequency = 0;
unsigned char start=1;
unsigned char flag = 0;
void InitTimer()
{
TMOD = 0x15; //T1定时,T0计数,
TH1 = (65535 - 50000) / 256;
TL1 = (65535 - 50000) % 256;
TH0 = 0x00;
TL0 = 0x00;
ET1 = 1;
ET0 = 1;
EA = 1;
TR1 = 1;
TR0 = 1;
}
unsigned int i = 0;
void ServiceTimer1() interrupt 3
{
TH1 = (65535 - 50000) / 256;
TL1 = (65535 - 50000) % 256;
i++;
if(i==20)
{
i = 0;
TR0=0; //停止计数
TR1=0; //停止定时
frequency=(TH0*256+TL0); //求出频率值 就是1秒内脉冲次数
TH0=0x00; //计数值清零
TL0=0x00;
TH1 = (65535 - 50000) / 256;
TL1 = (65535 - 50000) % 256;
start=1; //启动定时器开启变量
}
}
void Init_INT0()
{
IT0 = 1;
EX0 = 1;
EA = 1;
}
void ServiceINT0() interrupt 0
{
if(flag == 0)
{
frequency = 0;
}
if(flag!=0)
frequency++;
flag = 1;
}
void DisplaySMG_Bit(unsigned char value, unsigned char pos)
{
P0 = 0xff;
P2 = 0x01 << pos;
P0 = value;
}
void DelaySMG(unsigned int t)
{
while(t--);
}
void Display_Dynamic()
{
DisplaySMG_Bit(SMG_duanma[frequency/100000],0);
DelaySMG(500);
DisplaySMG_Bit(SMG_duanma[frequency%100000/10000],1);
DelaySMG(500);
DisplaySMG_Bit(SMG_duanma[frequency%10000/1000],2);
DelaySMG(500);
DisplaySMG_Bit(SMG_duanma[frequency%1000/100],3);
DelaySMG(500);
DisplaySMG_Bit(SMG_duanma[frequency%100/10],4);
DelaySMG(500);
DisplaySMG_Bit(SMG_duanma[frequency%100%10],5);
DelaySMG(500);
}
void Delay(unsigned char t)
{
while(t--)
{
Display_Dynamic();
}
}
void DelayK(unsigned char t)
{
while(t--);
}
void ScanKeys_Alone()
{
if(S1 == 0)
{
DelayK(100);
if(S1 == 0)
{
TR0=0; //停止计数
TR1=0; //停止定时
if(flag == 0)
{
frequency = 0;
}
if(flag!=0)
frequency++;
flag = 1;
while(!S1);
}
}
}
void main()
{
InitTimer();
Init_INT0();
while(1)
{
ScanKeys_Alone();
if(start==1)
{
TR0=1; //启动定时器
TR1=1; //启动计数器
start=0; //关闭启动变量位 保证1秒时间
}
Display_Dynamic();
Delay(200);
if(flag == 1)
{
start = 0;
}
}
}
双击器件DCLOCK对外部输入矩形脉冲的频率进行设置:
50hz:
100hz:
当测频时,启动定时计数器时,若从T0(P3.4)输入矩形波刚好为高电平,而当1s定时到时刚好为高电平时,此时测得的频率值最准确。若启动定时计数器时,输入的矩形波刚好处于低电平,而当定时1s到时矩形波刚好要发生负跳变时,此时测得的频率误差最大。定时计数器的工作方式选择与初值的赋予不一定精准,容易引起误差。定时计数器的工作方式选择不同,最后的结果也会有所差异。工作方式2相比于工作方式0和工作方式1误差更小。其次,采用中断或查询的方式也会影响实验结果。采用查询方式的误差比采用中断误差更小。
电子计数器测频法主要是将被测频率信号加到计数器的计数输入端,然后让计数器在标准时间 Ts1 内进行计数,所得的计数值 N1。与被测信号的频率 fx1 的关系如下:
主要误差源是由于计数器只能进行整数计数而引起的±1 误差:
工作在计数状态下的16位计数器T0的最大计数值为65535,理论上可以测的频率范围是0-65535hz,实际仿真测试最大为65.5KHz,测量显示值为65530hz,误差为0.04%
经过测试在一定误差允许和测量范围内,数字频率计可以正常工作。下图是基于上述方案的数字频率计原理图设计参考。可实现下面功能:
(1)将外部矩形脉冲输入T0引脚,即将外部输入脉冲用导线连接到P3.4引脚,可以做外部脉冲输入数字频率计。
(2)扩展功能:当按下按键,停止对外部矩形脉冲计数,改为单脉冲计数。当按下一次按键,计数值加1,并显示到数码管上。(PS:LED可作为其它功能扩展使用)。
频率的测量可以采用数字逻辑电路来实现,也可以采用单片机进行控制。前者不仅实现的电路复杂,而且测量频率的范围较小,而利用单片机的定时器可以很方便的进行信号频率的测量,只需要在电脑上编写程序,然后在相应的显示电路进行显示就可以了,可以使用STC89C51单片机的定时器、计数器的定时和计数功能,外部扩展6位LED数码管,累计每秒进入单片机的外部脉冲个数,用LED数码管显示出来,实现基于单片机数字频率计的制作。