基于51单片机制作频率计-测脉冲数法

本文为LED-执棋困局,csdn原创首发。 > 发布人:LED-执棋困局 > 欢迎大家与LED-执棋困局相互点赞+关注+收藏+评论,也祝大家顺顺利利,平平安安。 > 我的格言是:“尽最大努力,做最好的自己! 版权声明:本文为CSDN博主「LCD-执棋困局」的原创文章。

目录

一、频率计简介

1.1频率计概述

1.2频率计组成

1.3频率计原理

1.4测量原理

二、仿真设计

2.1频率计仿真

2.2仿真展示

三、软件程序设计

3.1主程序程序设计

3.2定时器初始化程序设计

3.3中断程序设计

3.4计数程序设计

3.5数码管程序设计

四、提高测量精度

4.1结果展现

4.2测量误差

4.3提高精度

一、频率计简介

1.1频率计概述

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

1.2频率计组成

本文频率计为简易基础版,由定时器1中断服务模块、计数器0计数模块、数码管显示模块和主程序模块四个部分组成。

1.3频率计原理

本文频率计时钟频率为12MHZ,测量的脉冲频率可以自调。频率计以at89c51为核心,利用内部自带的定时器和计数器。每个at89c51内部自带2个定时器/计数器,可以通过编程方法来完成定时器和计数器的工作,让定时器每1ms中断一次,时间累加到1s时,暂停计数,TR0=0,每次定时器进入中断时,暂时关闭定时器1,能有效防止中断还没结束,下一个中断就来执行的情况,提高测量的精度,同时计数器T0计数,利用高8位TH0和低8位TL0计算出1s内的脉冲数/频率。

1.4测量原理

测量频率有两种方法,一个叫计数测量法(测量1s内脉冲数),另一种叫测量周期法(利用定时器测量周期,再利用f=1/T求出频率)。

前者适用于高频测量,后者适用于低频测量。

本文采用计数测量法。

计数测量法如何计算频率?

频率f定义:单位时间内的脉冲数。

在t时间内测量到N个脉冲,则频率f=N/t,特殊情况下(t=1s),f=N。

如下图(定时器T0定时累加1s),f=50hz,则频率f=脉冲数N=1s/0.02s=50。

二、仿真设计

2.1频率计仿真

如图所示,是在proteus软件频率计的仿真。由于要测量1s内的脉冲数,所以要接计数器T0的引脚INT0。

2.2仿真展示

数码管线码a、b、c、d、e、f、g、DP接P0,由于P0口电流过小,驱动能力不足,所以一定要接排阻respack-8提高驱动能力,至于74HC245芯片也是提高驱动能力的,可以不用。而段码接到P2低4位。频率计接到计数器T0引脚INT0。

以上是我自己接的,大家也可以接其他引脚。

三、软件程序设计

3.1主程序程序设计

主程序调用定时器T1和计数器T0初始化,在while(1)调用数码管显示服务模块。

/******************************************************************

功能:1s内脉冲数及频率的测量

******************************************************************/

#include

#include "display.h"

void Timer0_Init();

void Timer1_Init();

void dis_service();

unsigned int cnd=0;//控制测量脉冲数时间变量

unsigned int num;//脉冲数变量

void main()

{

Timer0_Init();

Timer1_Init();

EA=1;

while(1)

{

dis_service();

}

}

3.2定时器初始化程序设计

void Timer1_Init(void) //1毫秒@12.000MHz

{

TMOD &= 0x0F; //设置定时器模式

TMOD |= 0x10; //设置定时器模式

TL1 = 0x18; //设置定时初始值

TH1 = 0xFC; //设置定时初始值

ET1=1; //定时器1中断打开

TF1 = 0; //清除TF1标志

TR1 = 1; //定时器1开始计时

}

3.3中断程序设计

1ms中断一次,要求测量时间为1s,所以定义变量cnd,让其累加到1000(中断1000次)后,开始计算脉冲数。计算脉冲数后,要将cnd、TH0、TL0清0,确保下次计算的正确性。

void T1_timer() interrupt 3 //1s测量脉冲数及频率

{

TR1=0;

cnd++;

if(cnd>=1000)//1s

{

TR0=0;

cnd=0;

num=TH0*256+TL0;//脉冲数

TH0=TL0=0;//重新赋予计数初值

TR0=1;

}

display();

TL1 = 0x18; //设置定时初始值

TH1 = 0xFC; //设置定时初始值

TR1=1;

}

3.4计数程序设计

脉冲数从0开始测量,所以TL0、TH0初值为0。

void Timer0_Init(void) //计数器T0

{

TMOD &= 0xf0; //设置计数器模式 0000 0101

TMOD |= 0x05; //设置计数器模式

TL0 = 0; //设置计数初始值

TH0 = 0; //设置计数初始值

TF0 = 0; //清除TF1标志

ET0=1; //计数器0中断打开

TR0 = 1; //计数器1开始计时

}

3.5数码管程序设计

用于显示数码管的每一位。

void dis_service()

{

LEDBuf[0]=num/1000;

LEDBuf[1]=num/100%10;

LEDBuf[2]=num/10%10;

LEDBuf[3]=num%10;

}

display.c

#include "display.h"

unsigned char code leddata[]={

0x3F, //0

0x06, //1

0x5B, //2

0x4F, //3

0x66, //4

0x6D, //5

0x7D, //6

0x07, //7

0x7F, //8

0x6F, //9

0x77, //A

0x7C, //B

0x39, //C

0x5E, //D

0x79, //E

0x71, //F

0x76, //H

0x38, //L

0x37, //n

0x3E, //u

0x73, //P

0x5C, //o

0x40, //-

0x00 //熄灭

};//数码管段码表

unsigned char LEDBuf[]={0,0,0,0};//缓冲区

unsigned char code PLACE_COOE[]={0xfe,0xfd,0xfb,0xf7};//位码

/******************************************************************************************

函数名:display

功能:数码管显示函数

参数:无

返回值:无

******************************************************************************************/

void display()

{

static unsigned char i=0;

switch(i)

{

case 0:

IO_DIG=0x00;//消隐

IO_DIG=leddata[LEDBuf[0]];//段码

IO_PLACE=PLACE_COOE[0];//位码

i++;

break;

case 1:

IO_DIG=0x00;//消隐

IO_DIG=leddata[LEDBuf[1]];//段码

IO_PLACE=PLACE_COOE[1];//位码

i++;

break;

case 2:

IO_DIG=0x00;//消隐

IO_DIG=leddata[LEDBuf[2]];//段码

IO_PLACE=PLACE_COOE[2];//位码

i++;

break;

case 3:

IO_DIG=0x00;//消隐

IO_DIG=leddata[LEDBuf[3]];//段码

IO_PLACE=PLACE_COOE[3];//位码

i=0;

break;

}

}

display.h

#ifndef __DISPLAY_H__

#define __DISPLAY_H__

#include

#define IO_DIG P0 //段码IO

#define IO_PLACE P2 //位码IO

#define N 4 //数码管个数

unsigned char code leddata[];//变量声明

extern unsigned char LEDBuf[];

void display();//数码管显示函数声明

#endif

四、提高测量精度

4.1结果展现

50hz:

100hz:

500hz:

1000hz:

4.2测量误差

4.2.1误差公式

本文测的是1s内的脉冲数,即为频率。

那频率计误差怎么求呢?其实很简单,就是先计算出实际值与理论值的差的绝对值,然后除于理论值,最后乘于100%。

误差=( |实际值-理论值| /实际值)×100%

4.2.2误差计算&结果

频率计测量50hz:

[(54-50)/54 ]×100%≈7.4%

频率计测量100hz:

[(108-100)/108]×100%≈7.4%

频率计测量500hz:

[(539-500)/539]×100%≈7.24%

频率计测量1000hz:

[(1077-1000)/1077]×100%≈7.15%

随着测量频率提高,误差有所降低。

4.3提高精度

1.选择更加稳定的信号,例如使用石英晶体振荡器产生的信号。

2.本文测量时间为1s,可以提高测量时间,在较长的时间,能测量更多的信号周期,从而减小误差。

3.在软件编程,在执行中断时,可以暂时关闭定时器T1,即TR1=0,在本次中断结束时再打开定时器T1,即TR1=1。

五、总结

本文讲述了关于频率计的测量方法之一的计数测量法,就是利用频率的定义(单位时间内的脉冲数)。还学会了频率计的相关原理,利用at89c51内部的定时器T0定时累加到1s,同时利用内部的计数器T1的高8位和低8位测量脉冲数,从而借助数码管模块来显示到数码管屏幕上。此外,我们还学会了如何计算误差和提高测量精度的方法。

hello!我是博主LED-执棋困局,下一文章—基于51单片机制作门铃,我们下期再见!你们的关注支持就是我的动力!