单片机原理与应用数字频率计数器.docx
《单片机原理与应用数字频率计数器.docx》由会员分享,可在线阅读,更多相关《单片机原理与应用数字频率计数器.docx(23页珍藏版)》请在冰豆网上搜索。
![单片机原理与应用数字频率计数器.docx](https://file1.bdocx.com/fileroot1/2023-4/28/41cee406-0e70-4876-be54-8b8563a0bba8/41cee406-0e70-4876-be54-8b8563a0bba81.gif)
单片机原理与应用数字频率计数器
第1章数字频率计概述
1.1数字频率计概述
数字频率计又称为数字频率计数器,是一种专门对被测信号频率进行测量的电子测量仪器,是计算机、通讯设备、音频视频等科研生产领域不可缺少的测量仪器。
它是一种用十进制数字显示被测信号频率的数字测量仪器。
它的基本功能是测量方波信号及其他各种单位时间内变化的物理量。
本数字频率计将采用定时、计数的方法测量频率,采用6个数码管显示6位十进制数。
测量范围从10Hz—5.5kHz,精度为1%,用单片机实现自动测量功能。
基本设计原理是直接用十进制数字显示被测信号频率的一种测量装置。
它以测量频率的方法对方波的频率进行自动的测量。
1.2数字频率计的基本原理
数字频率计最基本的工作原理为:
当被测信号在特定时间段T内的周期个数为N时,则被测信号的频率f=N/T(如图1.1所示)。
图1.1频率测量原理
频率的测量实际上就是在1s时间内对信号进行计数,计数值就是信号频率。
用单片机设计频率计通常采用的办法是使用单片机自带的计数器对输入脉冲进行计数;好处是设计出的频率计系统结构和程序编写简单,成本低廉,不需要外部计数器,直接利用所给的单片机最小系统就可以实现。
缺陷是受限于单片机计数的晶振频率,输入的时钟频率通常是单片机晶振频率的几分之一甚至是几十分之一,在本次设计使用的AT89C51单片机,由于检测一个由“1”到“0”的跳变需要两个机器周期,前一个机器周期测出“1”,后一个周期测出“0”。
故输入时钟信号的最高频率不得超过单片机晶振频率的二十四分之一。
根据频率检测的原理,很容易想到利用51单片机的T0、T1两个定时/计数器,一个用来定时,另一个用来计数,两者均应该工作在中断方式,一个中断用于1s时间的中断处理,一个中断用于对频率脉冲的计数溢出处理。
1.3单脉冲测量原理
首先设置定时器T0为方式1,在被测脉冲信号INT0的下降沿进入外部中断函数,在中断函数中启动T0计数码,被测脉冲信号下降沿停止T0计数,
脉宽测量过程见下图:
定时器T0以方式1对内部脉冲计数,16位计数值存放在40H(高字节)和41H单元
第2章课程设计方案设计
2.1系统方案的总体论述
数字频率计是用于测量信号(方波,脉冲信号)的频率,并用十进制数字显示,它具有精度高,测量迅速,读数方便等优点。
脉冲信号的频率就是在单位时间内所产生的脉冲个数,其表达式为f=N/T,其中,f为被测信号的频率,N为计数器所累计的脉冲个数。
T为产生N个脉冲所需的时间。
计数器所记录的结果,就是被测信号的频率。
如在1S内记录1000个脉冲,则被测信号的频率为1000Hz。
本实验课题仅讨论一种简单易制的数字频率计。
2.2系统硬件的总体设计
本频率计的数据采集系统主要元器件是单片机AT89C51,由它完成对待测信号频率的计数和结果显示等功能,可分为以下几个两个模块电路:
单片机系统、数码管及显示电路。
各模块关系图如图2.1所示:
图2.1数字频率计系统框图
2.3处理方法
本频率计的设计以AT89C51单片机为核心,利用它内部的定时/计数器完成待测信号周期/频率的测量。
单片机AT89C51内部具有2个16位定时/计数器,定时/计数器的工作可以由编程来实现定时、计数和产生计数溢出中断要求的功能。
在构成为定时器时,每个机器周期加1(使用12MHz时钟时,每1us加1),这样以机器周期为基准可以用来测量时间间隔。
在构成为计数器时,在相应的外部引脚发生从1到0的跳变时计数器加1,这样在计数闸门的控制下可以用来测量待测信号的频率。
外部输入每个机器周期被采样一次,这样检测一次从1到0的跳变至少需要2个机器周期(24个振荡周期),所以最大计数速率为时钟频率的1/24(使用12MHz时钟时,最大计数速率为500KHz)。
定时/计数器的工作由相应的运行控制位TR控制,当TR置1,定时/计数器开始计数;当TR清0,停止计数。
第3章硬件设计
3.1单片机最小系统
AT89C51是一种高性能低功耗的采用CMOS工艺制造的8位微控制器,它提供下列标准特征:
4KB的程序存储器,128B的RAM,32条I/O线,2个16位定时器/计数器,2个外部中断源和1个串行口。
图3.1单片机最小系统
其引脚功能如下:
⒈电源:
⑴VCC-电源引脚,接+5V;
⑵GND-接地端;
⒉时钟:
XTAL1、XTAL2-晶体振荡电路反相输入端和输出端。
⒊控制线:
控制线共有4根,
⑴
:
地址锁存允许/片内EPROM编程脉冲
①ALE功能:
用来锁存P0口送出的低8位地址
②
功能:
片内有EPROM的芯片,在EPROM编程期间,此引脚输入编程脉冲。
⑵PSEN:
外ROM读选通信号。
⑶RESET:
复位信号。
⑷
:
内外ROM选择/片内EPROM编程电源。
①
功能:
内外ROM选择端。
②Vpp功能:
片内有EPROM的芯片,在EPROM编程期间,施加编程电源Vpp。
⒋I/O线
89C51共有4个8位并行I/O端口:
P0、P1、P2、P3口,共32个引脚。
P3口还具有第二功能,用于特殊信号输入输出和控制信号(属控制总线)。
5.P3口第二功能
P3.0RXD串行输入口
P3.1TXD串行输出口
P3.2
外部中断0申请输入端
P3.3
外部中断1申请输入端
P3.4T0定时计数器0计数输入端
P3.5T1定时计数器1计数输入端
P3.6
外部数据存储器写选通
P3.7
外部数据存储器读选通
第4章软件设计
4.1系统的软件流程图
系统软件设计采用模块化设计方法。
整个系统由初始化模块、显示模块和信号频率测量模块和脉冲测量模块组成(见图4.1)。
上电后,进入系统初始化模块,系统软件开始运行。
在执行过程中,根据外界开关选择是频率测量模式还是脉冲宽度测量模式。
其中当闭合开关,蓝色指示灯亮时,表示是在单脉冲测量模式,打开开关,蓝色指示灯灭,表示是在频率测量模式。
若模式选择错误,将会导致不能得到正确的测量结果。
具体程序流程见下图:
图4.1主函数流程图
图4.2频率测量流程图
图4.3脉冲宽度测量流程图
4.2程序清单
程序详见附录Ⅱ。
第5章课程设计总结
通过本次对数字频率计的设计使我对书本上的知识有了更进一步的了解,同时也使我感觉到,在实际运用中仅仅凭借书本上的的知识是远远不够的。
在设计中我遇到了一些困难,比如测量方法的选择上曾一度陷入困境,终于攻克了难题。
本次课程设计使我的分析能力和动手能力都有了很大的进步,激起了我对课程的更大兴趣。
在电子技术中,频率是最基本的参数之一,并且与许多电参量的测量方案、测量结果都有十分密切的关系,因此频率的测量就显得更为重要。
频率计的基本原理是用一个频率稳定度高的频率源作为基准时钟,对比测量其他信号的频率。
通常情况下计算每秒内待测信号的脉冲个数,此时我们称闸门时间为1秒。
闸门时间也可以大于或小于一秒。
闸门时间越长,得到的频率值就越准确,但闸门时间越长则没测一次频率的间隔就越长。
闸门时间越短,测的频率值刷新就越快,但测得的频率精度就受影响。
本设计还有很多地方需要改进,其中包括对数据的处理,因为取模运算耗时过大,导致数码管在测量高频信号时出现闪烁。
所以应该优化算法,获得更好的显示效果。
参考文献
[1]《单片机原理及应用》陈为,中国石油大学出版社
附录Ⅰ仿真截图
开关打开,指示灯灭,表示此时为测量频率模式,调整方波频率,在数码管上得到测量值为520Hz
开关打开,指示灯灭,表示此时为测量频率模式,调整方波频率,在数码管上得到测量值为21Hz
经过放着可见,对频率的测量还是比较准确的
以下是对脉冲宽度测量的仿真截图
双击脉冲发生器
,会出现如下对话框
设置脉冲格式,单脉冲,正脉冲,起始时间为1s后(即开始仿真一秒后,脉冲自动产生),脉冲宽度设置为520us,点击OK
保持开关闭合,模式指示灯亮,表示此时在脉冲测量方式下,点击仿真开始按钮,开始仿真,1s后,单片机接收到脉冲信号,并把结果显示到数码管上
其默认单位为us,此时显示结果为576us
修改脉冲宽度为0.1s(要求测量范围的上限),仿真结果如下,此时数码管显示为100000us,即0.1s
附录Ⅱ程序清单
/*****************************************************************
课题名称:
单片机测输入方波脉冲频率和单脉冲宽度
测量范围:
外界输入频率在10KHz以内可以稳定显示,六位数码管默认单位为Hz
当测量范围过大时,因取模运算耗时大数码管会闪烁,但显示基本正确
单正脉冲测量范围可达100us--0.1s,六位数码管默认单位为us
*****************************************************************/
#include//包含51单片机寄存器定义的头文件
#defineucharunsignedchar
#defineuintunsignedint
longn,num;//全局变量,n用来记录T1的中断次数,4000次后正好是一秒:
num用来存放测脉冲宽度时T0的计数值
sbitu=P3^2;//将u位定义为P3.2
sbitL=P2^7;//将L位定义为P2.7
sbitled=P2^6;//led亮时表示测量脉冲宽度状态
uchara,b,c,d,e,f;//六位数码管
ucharcodet[]={0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7f,0x6f};//段码
/**************************************************************
函数功能:
延时子函数
*************************************************************/
voiddelay(uintz)
{
uinti,j;
for(i=0;ifor(j=0;j<50;j++);
}
/**************************************************************
函数功能:
测频率时的定时器初始化
*************************************************************/
voidinit()//测频率时的定时器初始化
{
TMOD=0x25;//00100101=>T1,定时方式二,8位自动重装;T0,计数,方式1
TH0=0;//计数初值为零
TL0=0;
TH1=6;//定时250us
TL1=6;
TR1=1;//开T1定时
TR0=1;//开T0计数
ET0=1;//允许TO中断
ET1=1;//允许T1中断
EA=1;//开总中断
}
/**************************************************************
函数功能:
显示子函数
*************************************************************/
voiddisplay()//显示
{
P2=0xfe;//最右端一位数码管
P0=t[f];//送段码
delay
(1);//延时
P0=0;//熄灭
P2=0xfd;//右端数第二位
P0=t[e];//送段码
delay
(1);//延时
P0=0;//熄灭
P2=0xfb;//右端数第三位
P0=t[d];//送段码
delay
(1);//延时
P0=0;//熄灭
P2=0xf7;//右端数第三位
P0=t[c];//送段码
delay
(1);//延时
P0=0;//熄灭
P2=0xef;//右端数第三位
P0=t[b];//送段码
delay
(1);//延时
P0=0;//熄灭
P2=0xdf;//右端数第三位
P0=t[a];//送段码
delay
(1);//延时
P0=0;//熄灭
}
/**************************************************************
函数功能:
定时器T0中断,定时1s
*************************************************************/
voidt1(void)interrupt3//定时器T1中断,
{
n++;//记录中断次数,4000次正好1s
if(n==4000)//一秒时间到,读计数器的T0的值
{
n=0;//清零
EA=0;//关中断
TR1=0;//关T1定时
TR0=0;//关T0计数
num=(long)TH0*256+TL0;//取计数值
TL0=0;//计数清零
TH0=0;//计数清零
a=num/100000;//对计数值取模,显示用
b=num/10000%10;
c=num/1000%10;
d=num/100%10;
e=num/10%10;
f=num%10;
TR1=1;//开T1定时
TR0=1;//开T0计数
EA=1;//重开
}
}
/**************************************************************
函数功能:
测脉冲宽度的子函数
*************************************************************/
voidmaikuan(void)
{
TMOD=0x01;//TMOD=0001H,使用计数器T0的模式1
EA=1;//开放总中断
EX0=1;//允许使用外中断
IT0=0;//选择负跳变来触发外中断
TH0=0;//定时器T0赋初值0
TL0=0;//定时器T0赋初值0
while(L==0)
display();
//无限循环,不停调用显示子函数
}
/**************************************************************
函数功能:
外中断0的中断服务程序
*************************************************************/
voidint0(void)interrupt0//外中断0的中断编号为0
{
TR0=1;//外中断一到来,即启动T0计时
while(u==0);//P3^2为低电平时T0一直计数
TR0=0;//P3^2为高电平时关闭T0
num=((long)TH0*256+TL0)+31;//取计数值
TL0=0;//计数清零
TH0=0;//计数清零
if(TF0==1)//如果计数器有溢出,需要加上溢出前的计数值65535
{
TF0=0;
num=num+65536;
}//计数器没有溢出,直接对计数值处理
a=num/100000;
b=num%100000/10000;
c=num%100000%10000/1000;
d=num%100000%10000%1000/100;
e=num%100000%10000%1000%100/10;
f=num%100000%10000%1000%100%10;
}
/**************************************************************
函数功能:
测频率的子函数
*************************************************************/
voidpinlv()
{
init();//初始化
while(L==1)
display();
}
/**************************************************************
函数功能:
主函数
*************************************************************/
voidmain(void)
{
while
(1)//主循环
{
if(L==1)//判断是计频率还是测脉冲宽度
pinlv();
else
maikuan();
}
}