目录

基于51单片机的频率计

基于51单片机的频率计

频率计

基于51单片机的频率计

简介

1.频率计数器是计算机、通讯设备、音频视频等科研生产领域不可缺少的测量仪器。它是一种用十进制数字显示被测信号频率的数字测量仪器。它的基本功能是测量正弦信号,方波信号及其他各种单位时间内变化的物理量。在进行模拟、数字电路的设计、安装、调试过程中,由于其使用十进制数显示,测量迅速,精确度高,显示直观,经常要用到频率计。

本文的频率计系统是以单片机(AT89C51)为核心,利用AT89C51单片机的T0和T1的定时计数功能来完成对输入的信号进行频率计数,由时基集成电路NE555P、四位共阴极数码管等元器件以及C语言程序组成。

2.本设计拟实现的性能指标如下:

本文利用AT89C51单片机的T0、T1的定时计数器功能,来完成对输入的信号进行频率计数,计数的频率结果通过4位动态数码管显示出来。能够对0-9999HZ的信号频率进行准确计数,计数误差不超过±1HZ。

数码管显示

数码管是一种半导体发光器件,其基本单元是发光二极管。数码管按段数分为七段数码管和八段数码管,八段数码管比七段数码管多一个发光二极管单元(多一个小数点显示);按能显示多少个“8”可分为1位、2位、4位等等数码管:按发光二极管单元连接方式分为共阳极数码管和共阴极数码管。

共阳数码管是指将所有发光二极管的阳极接到一起形成公共阳极(COM)的数码管,共阳数码管在应用时应将公共极COM接到+5V,当某一字段发光二极管的阴极为低电平时,相应字段就点亮,当某一字段的阴极为高电平时,相应字段就不亮。

共阴数码管是指将所有发光二极管的阴极接到一起形成公共阴极(COM)的数码管,共阴数码管在应用时应将公共极COM接到地线GND上,当某一字段发光二极管的阳极为高电平时,相应字段就点亮,当某一字段的阳极为低电平时,相应字段就不亮。

https://i-blog.csdnimg.cn/blog_migrate/978423ab6e940844cabf1de901d6d63c.png#pic_center

定时电路NE555

1、NE555是属于555系列的计时IC的其中的一种型号,555系列IC的接脚功能及运用都是相容的,只是型号不同的因其价格不同其稳定度、省电、可产生的振荡频率也不大相同;而555是一个用途很广且相当普遍的计时IC,只需少数的电阻和电容,便可产生数位电路所需的各种不同频率之脉波讯号。

NE555的特点有:

(1)只需简单的电阻器、电容器,即可完成特定的振荡延时作用。其延时范围极广,可由几微秒至几小时之久。

(2)它的操作电源范围极大,可与TTL,CMOS等逻辑闸配合,也就是它的输出准位及输入触发准位,均能与这些逻辑系列的高、低态组合。

(3)其输出端的供给电流大,可直接推动多种自动控制的负载。

(4)它的计时精确度高、温度稳定度佳,且价格便宜。

2、NE555引脚位配置说明下:

https://i-blog.csdnimg.cn/blog_migrate/e8bb18452584d9682d232379aa2ec2b6.png#pic_center

Pin 1 (接地) -地线(或共同接地) ,通常被连接到电路共同接地。

Pin 2 (触发点) -这个脚位是触发NE555使其启动它的时间周期。触发信号上缘电压须大于2/3 VCC,下缘须低于1/3 VCC 。

Pin 3 (输出) -当时间周期开始555的输出输出脚位,移至比电源电压少1.7伏的高电位。周期的结束输出回到O伏左右的低电位。于高电位时的最大输出电流大约200 mA 。

Pin 4 (重置) -一个低逻辑电位送至这个脚位时会重置定时器和使输出回到一个低电位。它通常被接到正电源或忽略不用。

Pin 5 (控制) -这个接脚准许由外部电压改变触发和闸限电压。当计时器经营在稳定或振荡的运作方式下,这输入能用来改变或调整输出频率。

Pin 6 (重置锁定) - Pin 6重置锁定并使输出呈低态。当这个接脚的电压从1/3 VCC电压以下移至2/3 VCC以上时启动这个动作。

Pin 7 (放电) -这个接脚和主要的输出接脚有相同的电流输出能力,当输出为ON时为LOW,对地为低阻抗,当输出为OFF时为HIGH,对地为高阻抗。

Pin 8 (V +) -这是555个计时器IC的正电源电压端。供应电压的范围是+4.5伏特(最小值)至+16伏特(最大值)。

3、参数功能特性:

•供应电压4.5-18V

•供应电流3-6 mA

•输出电流225mA (max)

•上升/下降时间100 ns

4、NE555内部结构图

https://i-blog.csdnimg.cn/blog_migrate/d77a204e113e9b8681438cbd99baf7b0.png#pic_center

硬件电路设计

1、NE555方波产生信号电路图

所产生方波公式:T1=0.693(RA+RB) *C

T2=0.693RB* C

F=1.433/(RA+2RB)*C https://i-blog.csdnimg.cn/blog_migrate/0e75a63a79e847ad351bb4af3f613c6c.png#pic_center

源文件下载

链接:

仿真图 频率计仿真电路图

代码

//包含头文件
#include <reg52.h> 
#include <math.h>
unsigned char code dispbit[]={0x01,0x02,0x04,0x08,0x10,0x20,0x40,0x80}; //反扫 (高位接高位)
//unsigned char code dispbit[]={0x80,0x40,0x20,0x10,0x08,0x04,0x02,0x01}; //正扫 (高位接低位)
unsigned char code dispcode[]={0xc0,0xf9,0xa4,0xb0,0x99,0x92,0x82,0xf8,0x80,0x90};//数码管显示码0-9 (a b c d e f g dp)
unsigned char dispbuf[6]={0,0,0,0,0,0};   //显示数据暂存数组
unsigned char temp[6]; 					  //频率值暂存数组
unsigned char T0count; 					  //计数器计满次数,计满一次对应的脉冲数为65536个
unsigned int timecount; 				  //定时器定时1秒的变量,每次对应为50ms,计20次对应就是1秒,然后计算一秒内的计数器脉冲个数
bit flag; 								  //计时到1秒时该标志位置1,进行脉冲数的运算,得出结果送显示,然后该位清零,重新开始脉冲计数
unsigned long x; 						  //计算脉冲的数据范围一般比较大,所以用无符号长整形变量定义该变量

sbit dian=P0^7; //位定义小数点,用于 kHz 显示

void display() //显示函数
{
unsigned int j; //定义变量用于显示延时 
if(dispbuf[5]!=0) //如果十万位不为 0
{
P2=dispbit[5];
P0=dispcode[dispbuf[5]]; //十万位正常显示数字
for(j=50;j>0;j--);
P0=0xff;
}
if(dispbuf[5]!=0||dispbuf[4]!=0) //如果十万位和万位都不等于零
{
P2=dispbit[4];
P0=dispcode[dispbuf[4]]; //万位正常显示
for(j=50;j>0;j--);
P0=0xff;
}

    P2=dispbit[3];						  //同上
    P0=dispcode[dispbuf[3]];
    dian=0;								  //该位显示小数点
    for(j=50;j>0;j--);
    P0=0xff;

    P2=dispbit[2];
    P0=dispcode[dispbuf[2]];
    for(j=50;j>0;j--);
    P0=0xff;

    P2=dispbit[1];
    P0=dispcode[dispbuf[1]];
    for(j=50;j>0;j--);
    P0=0xff;

    P2=dispbit[0];
    P0=dispcode[dispbuf[0]];
    for(j=50;j>0;j--);
    P0=0xff;

}
void main(void) //主函数
{
unsigned char i;
TMOD=0x15; //定义 T1 为定时模式,T0 位计数模式
TH0=0;
TL0=0; //计数器清零
TH1=0x3c;
TL1=0xb0; //定时器赋值(定时 50ms)
TR1=1; //打开定时器 T1
TR0=1; //打开计数器 T0
ET0=1; //打开中断允许
ET1=1; //打开中断允许
EA=1; //打开中断总开关

    while(1) 							  //进入循环,因为括号内为常数1,不会变化,所以该表达式一直成立,又称死循环
    {
    	display();						  //调用显示函数
    	if(flag) 						  //判断1秒时间是否到
    	{
    		flag=0; 					  //标志位清零,计算完脉冲数后重新开始计时计数
    		x=T0count*65536+TH0*256+TL0;  //读取1秒时间内的计数个数(T0count为每次计数超过65536时进入计数中断加1)
    		for(i=0;i<6;i++) 			  //for循环将暂存数组内数据清零
    		{
    			temp[i]=0;
    		}
    		i=0; 						  //i清零
    		while(x/10) 				  //将x拆分为6个一位数
    		{
    			temp[i]=x%10; 			  //如果x/10不为0,将x除以10的余数赋值temp【i】
    			x=x/10; 				  //然后将x/10的商赋值给x
    			i++; 					  //i++
    		}
    		temp[i]=x; 					  //最高位直接赋值给temp【i】
    		for(i=0;i<6;i++) 			  //for循环用于将数据送入显示暂存数组
    		{
    			dispbuf[i]=temp[i]; 	  //赋值语句
    		}
    		T0count=0; 					  //计数器中断次数清零
    		TH0=0;
    		TL0=0; 						  //计数器清零
    		TR0=1;
    		TR1=1;						  //重新打开定时计数器
    	}
    }

}

void t0() interrupt 1 //计数器中断函数
{
T0count++; //计数超过 65536,就产生一次中断
}

void t1() interrupt 3 //定时器中断函数
{
TH1=0x3c;
TL1=0xb0; //50ms 进入一次中断,进入中断后要重新赋初值
timecount++; //每进一次中断就是 50ms,该变量加一
if(timecount==20) //该变量加到 20 次时,代表 1 秒到了
{
TR0=0; //关闭计数器
TR1=0; //关闭定时器
timecount=0; //计时变量清零,准备下次定时
flag=1; //一秒时间到,该标志位置 1,主函数中执行脉冲数运算与显示函数
}
}
/**************************这里是函数的结尾 END***************************/