本文为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中断服务模块、计数器0计数模块、数码管显示模块和主程序模块四个部分组成。
本文频率计时钟频率为12MHZ,测量的脉冲频率可以自调。频率计以at89c51为核心,利用内部自带的定时器和计数器。每个at89c51内部自带2个定时器/计数器,可以通过编程方法来完成定时器和计数器的工作,让定时器每1ms中断一次,时间累加到1s时,暂停计数,TR0=0,每次定时器进入中断时,暂时关闭定时器1,能有效防止中断还没结束,下一个中断就来执行的情况,提高测量的精度,同时计数器T0计数,利用高8位TH0和低8位TL0计算出1s内的脉冲数/频率。
测量频率有两种方法,一个叫计数测量法(测量1s内脉冲数),另一种叫测量周期法(利用定时器测量周期,再利用f=1/T求出频率)。
前者适用于高频测量,后者适用于低频测量。
本文采用计数测量法。
计数测量法如何计算频率?
频率f定义:单位时间内的脉冲数。
在t时间内测量到N个脉冲,则频率f=N/t,特殊情况下(t=1s),f=N。
如下图(定时器T0定时累加1s),f=50hz,则频率f=脉冲数N=1s/0.02s=50。
如图所示,是在proteus软件频率计的仿真。由于要测量1s内的脉冲数,所以要接计数器T0的引脚INT0。
数码管线码a、b、c、d、e、f、g、DP接P0,由于P0口电流过小,驱动能力不足,所以一定要接排阻respack-8提高驱动能力,至于74HC245芯片也是提高驱动能力的,可以不用。而段码接到P2低4位。频率计接到计数器T0引脚INT0。
以上是我自己接的,大家也可以接其他引脚。
主程序调用定时器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();
}
}
void Timer1_Init(void) //1毫秒@12.000MHz
{
TMOD &= 0x0F; //设置定时器模式
TMOD |= 0x10; //设置定时器模式
TL1 = 0x18; //设置定时初始值
TH1 = 0xFC; //设置定时初始值
ET1=1; //定时器1中断打开
TF1 = 0; //清除TF1标志
TR1 = 1; //定时器1开始计时
}
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;
}
脉冲数从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开始计时
}
用于显示数码管的每一位。
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
50hz:
100hz:
500hz:
1000hz:
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%
随着测量频率提高,误差有所降低。
1.选择更加稳定的信号,例如使用石英晶体振荡器产生的信号。
2.本文测量时间为1s,可以提高测量时间,在较长的时间,能测量更多的信号周期,从而减小误差。
3.在软件编程,在执行中断时,可以暂时关闭定时器T1,即TR1=0,在本次中断结束时再打开定时器T1,即TR1=1。
五、总结
本文讲述了关于频率计的测量方法之一的计数测量法,就是利用频率的定义(单位时间内的脉冲数)。还学会了频率计的相关原理,利用at89c51内部的定时器T0定时累加到1s,同时利用内部的计数器T1的高8位和低8位测量脉冲数,从而借助数码管模块来显示到数码管屏幕上。此外,我们还学会了如何计算误差和提高测量精度的方法。
hello!我是博主LED-执棋困局,下一文章—基于51单片机制作门铃,我们下期再见!你们的关注支持就是我的动力!