第一篇:简单单片机数字频率计设计
课程设计报告
简易频率计的设计
电子科学XX学院
姓名:专业:通信工程学号:2013
2015年12月
摘要 本系统基于单片机来实现核心的频率计数功能,并能够实现测量中的量程自动切换。实现了对1Hz~1MHz的正弦波、方波以及脉宽不小于100s的脉冲信号频率测量,以及系统的自校功能。考虑到不同的测量方法对于不同频率测量带来的误差,对于频率为1Hz~1KHz的信号使用测频法,对于频率1KHz~1MHz的信号采用测周法,用单片机实现功能自动转换。放大整形电路使用了基本的晶体管放大模块,结合施密特触发器74HC132,使输出信号为TTL电平信号。此外本频率计实现了刷新时间1~10S连续可调,步进值为1S,最终单片机在7段数码管上显示测量的频率值。系统设计达到了各项目标要求。
关键词:频率测量;等精度测量;放大整形电路
目录
一、引言...................................................................................3
二、系统方案...........................................................................4
1.方案选择...........................................................................4 2.方案确定...........................................................................6
三、理论分析与设计...............................................................6
四、电路与程序设计...............................................................8
五、设计总结..............................................................................9
六、参考文献...........................................错误!未定义书签。
一、引言 频率的测量在电子测量技术中是一项重要的内容。数字频率计是一种用十进制数字显示被测信号频率的数字测量仪器,其基本功能是测量正弦波、方波、脉冲等周期信号的频率并将其显示出来,用途十分广泛。频率计的设计需要结合模拟电路、数字电路来综合搭建一个简单的电子系统,要求功能完全、测量准确。对于方案的选择、实际电路的调试提出了一定挑战。
二、系统方案
频率的测量方法可分为模拟测量法和数字测量法。
模拟测量法利用谐振特性进行测量,与标准频率信号比较形成的李萨如图形进行测量。但是其系统较为复杂,且谐振电路较为复杂,精度难以保证。
现在的频率测量方法都是基于数字测量,具有较高的精度。基本的频率测量方法有测频法和测周法。
1.方案选择
1)测频法
频率的定义为单位时间内周期信号发生的次数。依据这一定义,要测量频率,即可以通过对一段时间Ts内信号发生的次数N计数得到。测量时间基准可以用单片机来产生,计数也可以通过单片机的运算功能实现。测频法的原理电路如图1所示。被测信号经整形变换得到周期为Tx的被测脉冲串,电平转换为TTL电平,送入单片机中。利用标准时钟信号分频得到的时间基准信号控制门控电路,在闸门开启的有效时间Ts内允许被测脉冲串通过闸门电路进行计数,则被测信号频率fx可以表示为:
fxN/Ts
分析考虑误差公式:
fxNfs fxNfs4 UsOTxtUaOTt
图1测频法原理图
不考虑单片机产生的时间基准的精度对频率测量的影响。根据这一测量原理,闸门信号开启和关闭这一时间段Ts内N的计数可能会带来误差N,其最大值为1。当误差减小时,闸门时间即基准频率自身的准确度对测量结果的影响是不可忽略的。考虑频率较低的情形(如1Hz时),某一闸门开启的时间段内经变换后与信号等频率的脉冲串没有经过闸门,则计数值少1。若要减少N/N带来误差,就必须增大N,在被测信号频率较低的情况下,则要求闸门开放时间很长(即在fs不变的条件下,要求分频系数大)。若被测频率很低,为达到一定的测量精度,就要求闸门开放时间大得难以忍受,即一次测量过程的时间很长,失去了使用意义。
例如若被测频率为10Hz,精度要求为0.01%,则最短闸门开放时间为
NNfx/f1/0.000110000
TsN/fx1000s
像这样的测量周期是根本不可能接受的,可见频率测量法不适用于低频信号的测量,在同样精度下10MHz的测量仅需要1ms,即对于高频信号适宜用此方法测量。
2)测周法
测周法的基本结构与测频法是相同的,只是把晶体震荡产生的基准信号与被测信号的位置互换了一下。由此得
TN/MfNT/M
计数值N与被测信号的周期成正比,N反映了M个信号周期的平均值。利用周期测量的方法在一定信号频率范围内,通过调节分频系数M,可以较好地解决测量精度与实时性的矛盾。由上式可得 T/TN/NT/TN/TMfT/T
第二项误差取决于晶体稳定度,第一项为计数器的量化误差,故该项主要取决于N的大小。在平均周期测量法中,N值得大小与测量时间的长短成正比,可根据测量精度要求而定。假定N/N的允许误差为0.001%,则N105,在T选定测量时间为105T,若T2s,则测量时间为0.2s。对于不同范围的被测周期信号,可以通过调节分频系数M的大小,达到相近的测量精度,也就是有相近的测量时间,且不会太长。
当然,对于高频信号,周期法就需要很大分频系数M,增加了硬件及软件的复杂性,不宜采用。
2.方案确定
以上两种种方法中,测频法和测周法分别表现出在低频和高频情况下的明显不足。因此我们考虑将两种方法相结合,利用分段法分别进行测频和测周。这就要求我们找到一个合适的临界频率fM,使得fxfM时用测周法测量,fxfM用测频法测量。这里我们选定fM1KHz。
图2系统总体设计框图
三、理论分析与设计
根据题目要求,我们将简易频率要完成的设计目标分成以下几个功能模块:
1)输入信号的放大整形; 2)单片机对信号频率的测量; 3)单片机的自校功能; 4)测量方式的设定功能。下面分别对这些功能模块进行理论分析:
1)输入信号的放大整形: 要求我们对输入信号类型为正弦波、方波、脉冲波三种信号(幅度变化范 围:0.5V~5V,频率变化范围:1Hz~1MHz,脉冲信号的脉冲宽度:大
于100μs)进行放大整形,得到与原信号同频率的方波信号或脉冲信号。同时进行TTL电平转换,以备下一步输入单片机的I/O口进行频率的测量。常用的放大整形模块有多种。这里我们的输入信号其幅度已经较大了,所以不用考虑对微小信号的放大,一般的放大电路足以满足要求。另外输入信号的频率变化范围也不是很高,现在常用的放大元件(集成运放,三极管等)都能达到要求。
2)单片机对信号频率的测量;
由之前的分析,不论是测频法还是测周法,单片机核心的功能就是一个计数器的功能,在闸门时间内对所测信号上升沿进行计数,经过计算,得到频率测量值,同时进行输出显示。这一过程用软件语言来编写,思路上是比较容易的。51单片机提供的两个定时器计数器T0,T1即可完成设计。具体来说,可以用用定时器T1产生时间基准信号,用计数器T0作为被测信号的计数器。由于被测信号已经被整形为符合TTL电平要求的脉冲,所以我们可以用中断处理的方法,让T0工作在下边沿中断计数的模式下。用T1来产生25ms的定时,用软件计数的方法实现闸门信号的产生。
显示键盘单片机输入信号中断口T0计数T1定时计算频率 图3单片机工作框图
3)单片机的自校功能
自校是在时基单元提供的闸门时间内,对时标信号(频率较高的标准频率信号)进行计数的一种功能,用以检查频率计的整机逻辑功能是否正常。由于这时的闸门信号和时标信号由同一个晶振的标准信号经过分频得到,这时的计数结果是已知的。通过测量频率,如果显示出来的频率和这一时标信号的频率是一致的,那么说明整机的功能达到了要求,可以工作。
另外,在自校状态下,由于闸门信号与时标信号是同一晶振产生的,同步关系始终成立,所以频率计不存在量化误差(1误差)。
题目要求单片机用1MHz进行自校,但是这里由于我们采用了两个频率段的测量,也就是采用了两个闸门时间,因此要用两个时标信号来进行自校。实现的原理如图X。
自校功能选定产生时标信号测量频率频率与时标信号相等否显示自校结果为ERROR是显示自校结果为OK结束 图4自校功能原理框图
3)测量方式的设定功能
系统设计的要求之一是要满足显示方式为十进制数字显示,显示刷新时 间1~10秒连续可调。也就是说单片机输出显示的信号要满足显示功能可 以设定,刷新时间可以调控。这里我们在频率计系统设计中加入一个测量 方式的控制按键,按键后用键盘设置刷新时间值。这样的功能用单片机程 序来编写是比较容易实现的,在此不做过多讨论。
四、电路与程序设计
(1)放大整形电路设计
VDDXFG15V1.0uF0R42k¦¸2C20VDD5VVDDR120k¦¸C1624VDDXSC1Ext Trig+_A+_+B_03718U3U141AVCC1B4A1Y4B2A4Y2B3A2Y3BGND3Y11.0uFVEEVEER620k¦¸OP37AH3-5VR220k¦¸0074LS00D5 图5放大整形电路图 由于输入信号最低幅值为0.5V,所以要对其先进行放大,再整形。频率计的对输入阻抗的要求比较高。因此第一步信号输入要求输入阻抗很大以降低对信号源内阻的要求。故采用OP37运算放大器构成反向输入比例放大电路对信号进行放大。
后级采通过74LS00与非门对输入电平取非,进行放大信号的整形,得到一个可符合单片机测频要求电平的矩形波。(2)单片机程序流程设计
初始化功能设定测量频率自检测周法测量显示自检结果测定频率范围在1Hz~1KHz否测频法测量是显示输出 图6单片机流程图
五、设计结果
经过方案的不断调整,我们最终按照设计方案进行了硬件电路的焊接、单片机程序的编写,分别对放大整形电路的性能、单片机测频率的功能实现进行了调试,两部分均能满足题目要求之后,进行了系统联调。
在单片机功能实现的调试过程中,我们用实验室的DDS信号源产生满足TTL电平要求的方波,输入进单片机的P3.4口进行程序部分的验证。调整方波的幅值和频率,可以看出,从0.5V到1V,1Hz到1MHz,单片机均可以实现频率测量,测量精度在高频区略有下降,但能达到百分之一以内的精度,我们认为是可以接受的。
刷新时间可调和自校这一功能由于我们时间上不太充足,虽然有所尝试但最 终没有实现。我们对刷新时间的理解就是改变的是闸门信号。因为程序默认是定1S的闸门宽度,而刷新时间可调就可以使得闸门宽度变宽,使得低频测量不会产生正负1的误差。我们的思路是把定时器T1软件计数的值设为可以由按键控制的变量,通过按键改变这一变量,使得闸门宽度得到改变。
在对放大整形电路的测试过程中,我们发现在1MHz的情况下,OP37运算放大器由于增益带宽积不足,电压放大倍数锐减为3——4倍左右,当输入电压为0.5V放大倍数时不能越过四与非74LS00芯片的判定阈值,无法实现整形的效果。于是,我们组根据关永峰老师的建议,采用对直流电源分压的方式抬高电平,如图端点4处,将此处的电压抬升了2.5V左右,达到74LS00的阈值(约3.2V),从而实现了对信号的整形的作用。
我们组采用了比较易于获取的器件,受限于器件的参数,我们采用了电容的滤波、隔直来保证波形的稳定,尽量减少噪声的影响。图中电容C1起隔直作用,以滤除信号中不稳定的直流分量,也便于下一步设定抬升电压的大小。电容C2滤除电源噪声。
最终验收测试的数据如下: 0.5——5V的输入下,在正弦波输入的条件下,测频范围80Hz——1.1MHz。在方波输入的条件下,测频范围1Hz——1.5MHz。
系统在正弦波作为输入信号时的低频部分(1~80Hz)无法实现准确测频,测出频率均在1kHz以上。用示波器观察放大整形信号可以看出,在低频部分的输出信号含有较多的噪声,输出的矩形波前出现一撮高频、高幅度的噪声,该段噪声无法通过电容滤波滤除,当频率提高时,该段噪声的幅度明显减小,我们组认为该噪声是器件内部噪声,是器件本身的局限性造成的,因此要提高频率计的性能就要改用性能更好的放大器和整形器件。
六、设计总结
在本次实验的过程中,我们通过简单常见器件的匹配和调整,基本实现了题目要求的参数,较好的完成了实验指标。实验过程中存在的不足是由于时间和个人能力的限制,未能在软件部分完成自校功能,硬件方面也没有尝试先前设计报告中性能更好的高速运算放大器、高速施密特触发器,采用了比较简单易的常用器件。在此次实验的过程中,我们组分工明确,一人负责总体设计、一人软件编程、一人硬件焊接,因此在实验中效率很高,很快完成了设计、调试和验收过程。在最开始的方案设计中中,我们借鉴了一个庞大的整形放大电路,但在实现的过程遇到了较大的困难,一方面是对电路理解的欠缺,一方面是调试上存在极大的困难。在实验的过程中,我们深刻体会到了设计要基于题目要求和指标,不能好高骛远,要基于自己的理解,广泛查阅资料,进而不断改进完善。在本次实验中,我们组观察到了硬件和软件的相互匹配关系,即从放大整形电路到单片机编程计数测算频率,最后在数码管上观察到输出结果,在软硬件的相互配合中实现功能,让我们体会了软硬件协调配合的过程和通过电路实现具体功能的过程,同时,在电路调试过程中也学会很多调试方法,收获了很多电路方面的经验。
七、参考文献
[1]刘菊荣库锡树主编《电子技术实验教程教程》,电子工业出版社,198~200.[2]黄虎,奚大顺主编《电子系统设计——专题篇》,电子工业出版社,32~33.
第二篇:基于51单片机的数字频率计的设计概要
武汉理工大学《单片机原理与应用》课程设计说明书 前言
频率测量是电子学测量中最为基本的测量之一。由于频率信号抗干扰性强,易于传输,因此可以获得较高的测量精度。随着数字电子技术的发展,频率测量成为一项越来越普遍的工作,测频原理和测频方法的研究正受到越来越多的关注。
1.1频率计概述
数字频率计是计算机、通讯设备、音频视频等科研生产领域不可缺少的测量仪器。它是一种用十进制数字显示被测信号频率的数字测量仪器。它的基本功能是测量正弦信号、方波信号及其他各种单位时间内变化的物理量。在进行模拟、数字电路的设计、安装、调试过程中,由于其使用十进制数显示,测量迅速,精确度高,显示直观,经常要用到频率计。传统的频率计采用测频法测量频率,通常由组合电路和时序电路等大量的硬件电路组成,产品不但体积大,运行速度慢而且测量低频信号不准确。本次采用单片机技术设计一种数字显示的频率计,测量准确度高,响应速度快,体积小等优点。
1.2频率计发展与应用
在我国,单片机已不是一个陌生的名词,它的出现是近代计算机技术的里程碑事件。单片机作为最为典型的嵌入式系统,它的成功应用推动了嵌入式系统的发展。单片机已成为电子系统的中最普遍的应用。单片机作为微型计算机的一个重要分支,其应用范围很广,发展也很快,它已成为在现代电子技术、计算机应用、网络、通信、自动控制与计量测试、数据采集与信号处理等技术中日益普及的一项新兴技术,应用范围十分广泛。其中以AT89S52为内核的单片机系列目前在世界上生产量最大,派生产品最多,基本可以满足大多数用户的需要。
武汉理工大学《单片机原理与应用》课程设计说明书 系统总体设计
2.1测频的原理
测频的原理归结成一句话,就是“在单位时间内对被测信号进行计数”。被测信号,通过输入通道的放大器放大后,进入整形器加以整形变为矩形波,并送入主门的输入端。由晶体振荡器产生的基频,按十进制分频得出的分频脉冲,经过基选通门去触发主控电路,再通过主控电路以适当的编码逻辑便得到相应的控制指令,用以控制主门电路选通被测信号所产生的矩形波,至十进制计数电路进行直接计数和显示。若在一定的时间间隔T内累计周期性的重复变化次数N,则频率的表达式为式:
Nfx=
TN频率计数器严格地按照f=公式进行测频。由于数字测量的离散性,被测频率在计数
T器中所记进的脉冲数可有正一个或负一个脉冲的1量化误差,在不计其他误差影响的情况下,测量精度将为:
(fA)1N
应当指出,测量频率时所产生的误差是由N和T俩个参数所决定的,一方面是单位时间内计数脉冲个数越多时,精度越高,另一方面T越稳定时,精度越高。为了增加单位时间内计数脉冲的个数,一方面可在输入端将被测信号倍频,另一方面可增加T来满足,为了增加T的稳定度,只需提高晶体振荡器的稳定度和分频电路的可靠性就能达到。
上述表明,在频率测量时,被测信号频率越高,测量精度越高。
2.2总体思路
频率计是我们经常会用到的实验仪器之一,频率的测量实际上就是在单位时间内对信号进行计数,计数值就是信号频率。本文介绍了一种基于单片机AT89S52 制作的频率计的设计方法,所制作的频率计测量比较高的频率采用外部十分频,测量较低频率值时采用单片机直接计数,不进行外部分频。该频率计实现10HZ~2MHZ的频率测量,而且可以实现量程自动切换功能,四位共阳极动态显示测量结果,可以测量正弦波、三角波及方波等各种波形的频率值。
2.3具体模块
根据上述系统分析,频率计系统设计共包括五大模块:单片机控制模块、电源模块、放大整形模块、分频模块及显示模块。各模块作用如下:
1、单片机控制模块:以AT89C51单片机为控制核心,来完成它待测信号的计数,译
武汉理工大学《单片机原理与应用》课程设计说明书
码,和显示以及对分频比的控制。利用其内部的定时/计数器完成待测信号周期/频率的测量。
2、电源模块:为整个系统提供合适又稳定的电源,主要为单片机、信号调理电路以及分频电路提供电源,电压要求稳定、噪声小及性价高的电源。
3、放大整形模块:放大电路是对待测信号的放大,降低对待测信号幅度的要求。整形电路是对一些不是方波的待测信号转化成方波信号,便于测量。
4、分频模块:考虑单片机外部计数,使用12 MHz时钟时,最大计数速率为500 kHz,因此需要外部分频。分频电路用于扩展单片机频率测量范围,并实现单片机频率测量使用统一信号,可使单片机测频更易于实现,而且也降低了系统的测频误差。
5、显示模块:显示电路采用四位共阳极数码管动态显示,为了加大数码管的亮度,使用4个PNP三极管进行驱动,便于观测。
综合以上频率计系统设计有单片机控制模块、电源模块、放大整形模块、分频模块及显示模块等组成,频率计的总体设计框图如图2所示。
信号放大整形分频电路微控制器AT89S52数码管显示驱动电路5V电源
图2.1 频率计总体设计框图
武汉理工大学《单片机原理与应用》课程设计说明书 系统硬件设计
3.1 AT89C51主控制器模块
3.1.1 AT89C51的介绍
AT89C51是一种带4K字节FLASH存储器的低电压、高性能CMOS 8位微处理器,俗称单片机。由于将多功能8位CPU和闪烁存储器组合在单个芯片中,ATMEL的AT89C51是一种高效微控制器。AT89C51单片机为很多嵌入式控制系统提供了一种灵活性高且价廉的方案。
AT89C51引脚如下图所示。
图3.1 AT89C51引脚图
3.1.2 复位电路
复位电路是维持单片机最小系统运行的基本模块。复位电路如下图所示。
武汉理工大学《单片机原理与应用》课程设计说明书
图3.2 复位电路
高频率的时钟有利于程序更快的运行,也有可以实现更高的信号采样率,从而实现更多的功能。但是告诉对系统要求较高,而且功耗大,运行环境苛刻。考虑到单片机本身用在控制,并非高速信号采样处理,所以选取合适的频率即可。合适频率的晶振对于选频信号强度准确度都有好处,本次设计单片机实物具有11.0592M的晶振频率。AT89C51单片机最小系统如下图所示。
图3.3 单片机最小系统原理图
3.2 分频设计模块
分频电路用于扩展单片机频率测量范围,并实现单片机频率和周期测量使用统一信号,可使单片机测频更易于实现,而且也降低了系统的测频误差。
本频率计的设计以AT89C51单片机为核心,利用他内部的定时/计数器完成待测信号
武汉理工大学《单片机原理与应用》课程设计说明书
周期/频率的测量。单片机AT89C51内部具有2个16位定时计数器,定时/计数器的工作可以由编程来实现定时、计数和产生计数溢出时中断要求的功能。在定时器工作方式下,在被测时间间隔内,每来一个机器周期,计数器自动加1(使用12 MHz时钟时,每1μs加1),这样以机器周期为基准可以用来测量时间间隔。在计数器工作方式下,加至外部引脚的待测信号发生从1到0的跳变时计数器加1,这样在计数闸门的控制下可以用来测量待测信号的频率。外部输入在每个机器周期被采样一次,这样检测一次从1到0的跳变至少需要2个机器周期(24个振荡周期),所以最大计数速率为时钟频率的1/24(使用12 MHz时钟时,最大计数速率为500 kHz),因此采用74LS161进行外部十分频使测频范围达到2MHz。为了测量提高精度,当被测信号频率值较低时,直接使用单片机计数器计数测得频率值;当被测信号频率值较高时采用外部十分频后再计数测得频率值。这两种情况使用74LS151进行通道选择,由单片机先简单测得被测信号是高频信号还是低频信号,然后根据信号频率值的高低进行通道的相应导通,继而测得相应频率值。
3.3 显示模块
显示模块由频率值显示电路和量程转换指示电路组成。频率值显示电路采用四位共阳极数码管动态显示频率计被测数值,使用三极管8550进行驱动,使数码管亮度变亮,便于观察测量。量程转换指示电路由红、黄、绿三个LED分别指示Hz、KHz及MHz档,使读数简单可观。
3.3.1 数码管介绍
常见的数码管由七个条状和一个点状发光二极管管芯制成,叫七段数码管,根据其结构的不同,可分为共阳极数码管和共阴极数码管两种。根据管脚资料,可以判断使用的是何种接口类型。
LED数码管中各段发光二极管的伏安特性和普通二极管类似,只是正向压降较大,正向电阻也较大。在一定范围内,其正向电流与发光亮度成正比。由于常规的数码管起辉电流只有1~2 mA,最大极限电流也只有10~30 mA,所以它的输入端在5 V电源或高于TTL高电平(3.5 V)的电路信号相接时,一定要串加限流电阻,以免损坏器件。
3.3.2 频率值显示电路
数码管电路设计不加三极管驱动时,数码管显示数值看不清,不便于频率值的测量与调试。因此加入三极管8550进行驱动数码管。使用4位数码管进行频率值显示,如果选择共阴极数码管显示,则需要8个三极管进行驱动,而采用共阳极数码管则需要4个三极
武汉理工大学《单片机原理与应用》课程设计说明书
管驱动,为了节约成本,因此选用共阳极数码管进行动态显示,具体数码管设计电路如图所示。
图3.4 数码管显示电路
3.3.3 档位转换指示电路
根据设计要求,采用红、黄、绿三个LED分别指示Hz、KHz及MHz档,根据被测信号的频率值大小,可以自动切换量程单位,无需手动切换,便于测量和读数,简单方便。具体设计的档位转换LED指示电路如图所示。
图3.5 LED档位指示电路
武汉理工大学《单片机原理与应用》课程设计说明书 系统软件设计
系统软件设计主要采用模块化设计,叙述了各个模块的程序流程图,并介绍了软件Keil和Proteus的使用方法和调试仿真。
4.1 软件模块设计
系统软件设计采用模块化设计方法。整个系统由初始化模块,信号频率测量模块,自动量程转换和显示模块等模块组成。系统软件流程如图所示。
频率计开始工作或者完成一次频率测量,系统软件都进行测量初始化。测量初始化模块设置堆栈指针(SP)、工作寄存器、中断控制和定时/计数器的工作方式。定时/计数器的工作首先被设置为计数器方式,即用来测量信号频率。
开始系统初始化频率测量频率是否超过1KHzY硬件十分频N计数器计数测频率值测量数据显示
图4.1 系统软件流程总图
首先定时/计数器的计数寄存器清0,运行控制位TR置1,启动对待测信号的计数。计数闸门由软件延时程序实现,从计数闸门的最小值(即测量频率的高量程)开始测量,计数闸门结束时TR清0,停止计数。计数寄存器中的数值经过数制转换程序从十六进制数转换为十进制数。判断该数的最高位,若该位不为0,满足测量数据有效位数的要求,测量值和量程信息一起送到显示模块;若该位为0,将计数闸门的宽度扩大10倍,重新对待测信号的计数,直到满足测量数据有效位数的要求。定时/计数器的工作被设置为定时器方式,定时/计数器的计数寄存器清0,在判断待测信号的上跳沿到来后,运行控制位TR
武汉理工大学《单片机原理与应用》课程设计说明书
置为1,以单片机工作周期为单位进行计数,直至信号的下跳沿到来,运行控制位TR清0,停止计数。16位定时/计数器的最高计数值为65535,当待测信号的频率较低时,定时/计数器可以对被测信号直接计数,当被测信号的频率较高时,先由硬件十分频后再有定时/计数器对被测信号计数,加大测量的精度和范围。
4.2 应用软件简介
此设计需要在Keil软件平台上完成程序的调试,在Proteus软件平台上完成仿真显示。因此介绍如何使用Keil和Proteus进行软件的仿真。
4.2.1 Keil简介
Keil软件是目前最流行开发系列单片机的软件,Keil提供了包括C编译器、宏汇编、连接器、库管理和一个功能强大的仿真调试器等在内的完整开发方案,通过一个集成开发环境(uVision)将这些部份组合在一起。而Proteus与其它单片机仿真软件不同的是,它不仅能仿真单片机CPU的工作情况,也能仿真单片机外围电路或没有单片机参与的其它电路的工作情况。因此在仿真和程序调试时,关心的不再是某些语句执行时单片机寄存器和存储器内容的改变,而是从工程的角度直接看程序运行和电路工作的过程和结果。对于这样的仿真实验,从某种意义上讲,是弥补了实验和工程应用间脱节的矛盾和现象[16]。
4.2.2 protues简介
protues是Labcenter公司出品的电路分析、实物仿真系统,而KEIL是目前世界上最好的51单片机汇编和C语言的集成开发环境。他支持汇编和C的混合编程,同时具备强大的软件仿真和硬件仿真功能[17]。Protues能够很方便的和KEIL、Matlab IDE等编译模拟软件结合。Proteus提供了大量的元件库有RAM,ROM,键盘,马达,LED,LCD,AD/DA,部分SPI器件,部分IIC器件,它可以仿真单片机和周边设备,可以仿真51系列、AVR,PIC等常用的MCU,与keil和MPLAB不同的是它还提供了周边设备的仿真,只要给出电路图就可以仿真。
武汉理工大学《单片机原理与应用》课程设计说明书 系统仿真
5.1 系统总电路图
根据课程设计任务书的要求,本次课设设计的系统总电路图如下图所示。
图5.1 系统总电路图
5.2 系统仿真结果
系统仿真结果图如下图所示,由图中可以看出,LCD显示的值为900Hz,LED显示的值为886Hz,在误差允许的范围内,二者近似相等,符合课设任务书要求。
图5.2 系统仿真结果图
武汉理工大学《单片机原理与应用》课程设计说明书 系统硬件调试
6.1频率计的测试 如图6.1为频率计的测试实物拍摄图。其中函数信号发生器输出频率为1000Hz、幅值为5V的方波信号时,数字频率计测得的频率为996Hz,在误差允许的范围内,二者相等,符合课设任务书要求。
图6.1 频率计测试的实物拍摄图
6.2 低频方波信号发生器的测试
图6.2 低频信号发生器测试的实物拍摄图
武汉理工大学《单片机原理与应用》课程设计说明书
如图6.2为低频信号发生器测试的实物拍摄图。其中低频方波信号发生器输出频率的LED显示值为400Hz,经过示波器检测得到幅值为4.88V,频率为396.2Hz,在误差允许的范围内,二者相等,符合课设任务书要求。
6.3 低频方波信号发生器、数字频率计的综合测试
如图6.3为低频方波信号发生器检测频率计的实物拍摄图。其中低频方波信号发生器输出频率的LED显示值为300Hz,经过数字频率计检测得到频率的LCD显示值为297Hz,在误差允许的范围内,二者相等,符合课设任务书要求。
图6.3 低频方波信号发生器检测频率计的实物拍摄图
武汉理工大学《单片机原理与应用》课程设计说明书 心得体会
本次设计的过程和结果都给了我很多感触。初次拿到课程设计的题目时,只是对频率有一定的理解,至于怎么设计,几乎没有什么想法。在同学的指导和讲解下,对频率计的介绍有了一定的了解。后来通过不断的学习和查阅资料,终于清楚的知道了频率计的基本情况和设计的方案有了一定的理解。通过对各种性能的比较和所学知识能实现的状况,对本次课程设计进行了设计,最后进行的是课设报告的撰写。
通过本次设计,让我学会了从系统的高度来考虑设计的方方面面,对电路的设计和研究有了更深刻的体会;让我了解到软件的设计是建立在对硬件了解的基础上的,特别是对单片机的功能,引脚定义和内部结构要有较为详细的了解,此外对电路板中所用到的各个芯片的引脚和功能,也要进行了解;在编写程序时,进行模块化设计,以严谨的态度进行编程,避免出现低级错误,养成为程序添加注释和说明的好习惯,以便自己的修改和阅读者轻松的了解程序的各部分及整体的功能。
武汉理工大学《单片机原理与应用》课程设计说明书
参考文献
[1]李华.单片机实用接口技术[M].航空航天大学出版社.2006.[2]张鹏.王雪梅.单片机原理与应用实例教程[M].海军出版社.2007.[3]赫建国等.单片机在电子电路设计中的应用[M].清华大学出版社.2005.[4]康华光.电子技术基础(模拟部分)[M].高等教育出版社.1998. [5]吴清平.单片机原理与应用实例教程[M].海军出版社.2008.武汉理工大学《单片机原理与应用》课程设计说明书
#include
uchar code table[]=“made by Li Houmin”;uchar num;
void delay(int count){ int p;
//延时
while(count--)for(p=0;p<110;p++);}
void write_com(unsigned int n){
RS=0;P0=n;delay(5);
//写指令
E=1;delay(5);
武汉理工大学《单片机原理与应用》课程设计说明书
E=0;}
void write_data(unsigned char t){ RS=1;P0=t;delay(5);
//写数据
E=1;delay(5);E=0;}
void time1_int(void)interrupt 3 { TH1=TL1=0;TR1=1;x++;}
void time0_int(void)interrupt 1 { TH0=(65535-50000)/256;//装初值,定时50ms TL0=(65535-50000)%256;i++;
if(i==20){ i=0;//1s时间已到
武汉理工大学《单片机原理与应用》课程设计说明书
TR1=0;//关闭计数器1 count=65536*x+256*TH1+TL1;x=0;//重新装初值 //重新启动计数器器1 TH1=TL1=0;TR1=1;} }
void show(){
write_com(0x85);write_data(shu[count/100000]);delay(5);
//在第一行第五列显示十万位
write_com(0x86);write_data(shu[(count/10000)%10]);delay(5);write_com(0x87);write_data(shu[(count/1000)%10]);delay(5);write_com(0x88);write_data(shu[(count/100)%10]);delay(5);write_com(0x89);write_data(shu[(count/10)%10]);delay(5);write_com(0x8a);write_data(shu[count%10]);delay(5);
//显示万位 //显示千位 //显示百位
//显示十位
//显示个位
write_com(0x83);write_data(0x66);delay(5);//显示频率表示的字符f write_com(0x84);write_data(0x3d);delay(5);//显示字符= write_com(0x8b);write_data(0x48);delay(5);//显示字母H write_com(0x8c);write_data(0x7a);delay(5);//显示字母z write_com(0x80+0x40);
}
void main()
//第二行显示
for(num=0;num<17;num++){ write_data(table[num]);delay(5);}
武汉理工大学《单片机原理与应用》课程设计说明书
{ TMOD=0x51;
//T1计数、T2定时,且都工作在方式1 TH1=0x00;TL1=0x00;TH0=(65535-50000)/256;//装初值,定时50ms TL0=(65535-50000)%256;EA=1;
ET0=1;ET1=1;
TR0=1;TR1=1;
dula=0;wela=0;RW=0;E=0;write_com(0x01);write_com(0x38);write_com(0x0c);write_com(0x06);while(1){ show();
delay(5);} }
//开总中断
//中断允许
//启动定时器
//显示清零,数据指针清零
//设置16X2显示5X7点阵,8位数据口
//设置开显示,显示光标且闪烁
//写一个字符后地址指针加1
第三篇:单片机课程设计报告——智能数字频率计
单片机原理课程设计报告
题目:智能数字频率计设计
专业: 信息工程 班级:信息111 学号:*** 姓名:*** 指导教师:***
北京工商大学计算机与信息工程学院
1、设计目的
(1)了解和掌握一个完整的电子线路设计方法和概念;
(2)通过电子线路设计、仿真、安装和调试,了解和掌握电子系统研发产品的一个基本流程。
(3)了解和掌握一些常见的单元电路设计方法和在电子系统中的应用: 包括放大器、滤波器、比较器、计数和显示电路等。
(4)通过编写设计文档与报告,进一步提高学生撰写科技文档的能力。
2、设计要求
(1)基本要求
设计指标:
1.频率测量:0~250KHz; 2.周期测量:4mS~10S; 3.闸门时间:0.1S,1S;
4.测量分辨率:5位/0.1S,6位/1S; 5.用图形液晶显示状态、单位等。
充分利用单片机软、硬件资源,在其控制和管理下,完成数据的采集、处理和显示等工作,实现频率、周期的等精度测量方案。在方案设计中,要充分估计各种误差的影响,以获得较高的测量精度。
(2)扩展要求
用语音装置来实现频率、周期报数。
(3)误差测试
调试无误后,可用数字示波器与其进行比对,记录测量结果,进行误差分析。
(4)实际完成的要求及效果
1.测量范围:0.1Hz~4MHz,周期、频率测量可调; 2.闸门时间:0.05s~10s可调; 3.测量分辨率:5位/0.01S,6位/0.1S; 4.用图形液晶显示状态、单位(Hz/KHz/MHz)等。
3、硬件电路设计
(1)总体设计思路 本次设计的智能数字频率计可测量矩形波、锯齿波、三角波、方波等信号的频率。系统共设计包括五大模块: 主芯片控制模块、整形模块、分频模块、档位选择模块、和显示模块。设计的总的思想是以AT89S52单片机为核心,将被测信号送到以LM324N为核心的过零比较器,被测信号转化为方波信号,然后方波经过由74LS161构成的分频模块进行分频,再由74LS153构成的四选一选择电路控制档位,各部分的控制信号以及频率的测量主要由单片机计数及控制,最终将测得的信号频率经LCD1602显示。
各模块作用如下: 1.主芯片控制模块: 单片机AT89S52 内部具有2个16位定时/计数器T0、T1,定时/计数器的工作可以由编程来实现定时、计数和产生计数溢出时中断要求的功能。利用单片机的计数器和定时器的功能对被测信号进行计数。以AT89S52 单片机为控制核心,来完成对各种被测信号的精确计数、显示以及对分频比的控制。利用其内部的定时/计数器完成待测信号周期/频率的测量。
2.整形模块:整形电路是将一些不是方波的待测信号转化成方波信号,便于测量。本设计使用运放器LM324连接成过零比较器作为整形电路。
3.分频模块: 考虑单片机利用晶振计数,使用11.0592MHz 时钟时,最大计数速率将近500 kHz,因此需要外部分频。分频电路用于扩展单片机频率测量范围,并实现单片机频率测量使用统一信号,可使单片机测频更易于实现,而且也降低了系统的测频误差。本设计使用的分频芯片是74LS161实现4分频及16分频。
4.档位选择模块:控制74LS161不分频、4分频 或者 16分频,控制芯片是74LS153。5.显示模块:编写相应的程序可以使单片机自动调节测量的量程,并把测出的频率数据送到显示电路显示,本设计选用LCD1602。
(2)测频基本设计原理
所谓“频率”,就是周期性信号在单位时间(1s)内变化的次数。若在一定时间间隔T内测得这个周期性信号的重复变化次数N,则其频率可表示为f=N/T(右图3-1所示)。其中脉冲形成电路的作用是将被测信号变成脉冲信号,其重复频率等于被测频率fx。利用单片机的定时/计数T0、T1的定时、计数功能产生周期为1s的时间脉冲信号,则门控电路的输出信号持 图3-1 续时间亦准确地等于1s。闸门电路由标准的秒脉冲信号进行控制,当秒脉冲信号来到时,闸门开通,被测脉冲信号通过闸门送到计数译码显示电路。秒脉冲信号结束时闸门关闭,计数器停止计数。由于计数器计得的脉冲数N是在1秒时间内的累计数,所以被测频率fx=NHz。
(2)系统框图
本智能数字频率计系统框图如图3-2所示
图3-2智能数字频率计系统框图
(3)单片机部分
P0口经上拉后做LCD数据接口 P2.1~P2.3作为LCD控制端口 P2.4~P2.5作为分频选择端口 P3.5作为被测信号输入端口
P3.2~P3.4作为开关控制端口(对应电路图中K1,K2,SET)
图3-3 89D52单片机部分电路
(4)分频部分
74HC161与74ls161功能兼容,是常用的四位二进制可预置的同步加法计数器,他可以灵活的运用在各种数字电路,以及单片机系统中实现分频器等很多重要的功能。
其管脚图如图3-4所示:
图3-4 74HC161 图3-5 74HC153管脚图
74HC153是一个双4选1数据选择器,其管脚图如图3-5所示:
74LS161对整形后的防波信号进行分频,Q1为四分频输出,Q3为16分频输出。未经分频、经过四分频和经过16分频的三路信号作为74LS153的一个4选1数据选择器低三位输入,由单片机控制选择分频数,然后再送单片机内部计数器T1(如图3-6)。
图3-6 分频、选择分频档位电路图
(5)LCD显示部分
LCD显示,1602的八位数据I/O口与单片机的P0口相连,读写控制端接P2.0-P2.2口。三个按键中,设置键接P3.2单片机按外部中断0接口,当按键按下后,置P3.2口低电平,单片机中断。S1、S2为频率/周期、闸门时间加/减选择按键(如图3-7)。
图3-7 LCD显示部分电路图
4、软件设计
(1)主程序流程图设计
本次程序设计采用的是C语言程序设计,其设计流程图4-1所示:
图4-1主程序流程图
(2)子程序流程图设计
<1>显示程序:
LCD显示程序设计流程如图4-2所示:
图4-2显示程序流程图 <2>频率测量程序框图:
频率测量程序的整体架构如图4-3所示:
图4-3频率测量框架图
(3)中断服务流程图
INT0中断流程图如图4-4所示:
图4-4INT0中断流程图
(4)程序代码
#include
//频率 float p;
//周期 float sj;
//闸门时间 char idata buff[20];char flag=0;
//频率、周期选择标志位
char xs=0;//设置闸门时间结束后是否显示结果的标志位
unsigned char m=0,n=0,yichu=0,fenpin;
//m定时中断次数 n计数中断次数 yichu判断是定时
//器还是计数器溢出
#define Key_Set P3 #define K1 0xf7
//11110111
P33 #define K2 0xef
//11101111
P34 #define NO_Set 0xff #define Freq 0 #define Peri 1
sbit B153=P2^4;sbit A153=P2^3;sbit P17=P3^4;sbit P16=P3^3;sbit P35=P3^5;sbit Set=P3^2;unsigned char LCD_Wait(void);void LCD_Write(bit style, unsigned char input);void LCD_SetDisplay(unsigned char DisplayMode);void LCD_SetInput(unsigned char InputMode);void LCD_Initial();void GotoXY(unsigned char x, unsigned char y);void Print(unsigned char *str);void C52_Initial();void Delay(unsigned int t);void display(float f);void cepin();void panduan();void timedisplay(float sj);void Time_Set1();void Time_Set2();void t0();void t1();
/*****模块名称 LCD1602显示程序******/
/***********************端口定义 ***********************************/
sbit LcdRs= P2^0;sbit LcdRw= P2^1;sbit LcdEn= P2^2;sfr DBPort= 0x80;
//P0=0x80,P1=0x90,P2=0xA0,P3=0xB0.数据端口 /************************内部等待函数********************************/
unsigned char LCD_Wait(void){
LcdRs=0;
//寄存器选择输入端 1:数据 0:指令
LcdRw=1;
_nop_();//RW:为0:写状态;为1:读状态;
LcdEn=1;
_nop_();
//使能输入端,读状态,高电平有效;写状态,下降沿有效
LcdEn=0;
return DBPort;
} /**********************向LCD写入命令或数据***************************/
#define LCD_COMMAND 0
// Command #define LCD_DATA 1
// Data #define LCD_CLEAR_SCREEN
0x01
// 清屏 #define LCD_HOMING
0x02
// 光标返回原点 void LCD_Write(bit style, unsigned char input){
LcdEn=0;
LcdRs=style;
LcdRw=0;
_nop_();
DBPort=input;
_nop_();//注意顺序
LcdEn=1;
_nop_();//注意顺序
LcdEn=0;
_nop_();
LCD_Wait();} /********************设置显示模式*********************************/
#define LCD_SHOW
0x04
//显示开 #define LCD_HIDE
0x00
//显示关
#define LCD_CURSOR
0x02
//显示光标
#define LCD_NO_CURSOR
0x00
//无光标
#define LCD_FLASH
0x01
//光标闪动 #define LCD_NO_FLASH
0x00
//光标不闪动 void LCD_SetDisplay(unsigned char DisplayMode){
LCD_Write(LCD_COMMAND, 0x08|DisplayMode);
} /*********************设置输入模式***********************************/ #define LCD_AC_UP 0x02 #define LCD_AC_DOWN 0x00
// default #define LCD_MOVE 0x01
// 画面可平移 #define LCD_NO_MOVE 0x00
//default void LCD_SetInput(unsigned char InputMode){
LCD_Write(LCD_COMMAND, 0x04|InputMode);} /******************初始化LCD**************************************/
void LCD_Initial(){
LcdEn=0;
LCD_Write(LCD_COMMAND,0x38);
//8位数据端口,2行显示,5*7点阵
LCD_Write(LCD_COMMAND,0x38);
LCD_SetDisplay(LCD_SHOW|LCD_NO_CURSOR);
//开启显示, 无光标
LCD_Write(LCD_COMMAND,LCD_CLEAR_SCREEN);
//清屏
LCD_SetInput(LCD_AC_UP|LCD_NO_MOVE);
//AC递增, 画面不动 }
/************************************************************************/ void GotoXY(unsigned char x, unsigned char y){ if(y==0)
LCD_Write(LCD_COMMAND,0x80|x);if(y==1)
LCD_Write(LCD_COMMAND,0x80|(x-0x40));} void Print(unsigned char *str){
while(*str!=' ')
{
LCD_Write(LCD_DATA,*str);
str++;
} }
/*************************************************************************** *
模块名称:
频率测量程序
* *
测量范围:0.1Hz~4MHz,闸门时间:0.05s~10s可调。
* ***************************************************************************/ /***************************89c52初始化************************************/ void C52_Initial(){ sj=1000000.00;Key_Set=0xff;TMOD=0x51;
// 01010001 T1为计数器,T0为定时器
EA=1;ET0=1;ET1=1;EX0=1;
PX0=1;
//外部中断0设置为高优先级
IT0=0;
//电平触发方式 } /**************************延时子程序**************************************/ void Delay(unsigned int t)
//t随着数值越大,误差趋于平衡.{
unsigned char i;
while(t--)
{
for(i=0;i<123;i++){;}
} } /*************************计数中*********************************/ void t1(void)interrupt 3
//计数器1溢出,yichu=1 { n++;yichu=1;TH1=0;TL1=0;} /***********************定时中断****************************/ void t0(void)interrupt 1
{ m++;yichu=2;
//定时器0溢出,yichu=2 TH0=0x3c;
//定时50ms TL0=0xb0;} /***********************频率显示*****************************/ void Fdisplay(float f){
if(f>999400.00)
{
if(f<4000400.00)
{sprintf(buff,“ F=%2.4fmHz ”,(f/1000000.00));}
}
else
{
if(f>1040.00)
{sprintf(buff,“ F=%4.2fkHz ”,(f/1000.00));}
else
{
if(f>0.06)
{sprintf(buff,“ F=%3.2fHz
”,f);}
}
}
GotoXY(0,1);
Print(buff);} /***********************周期显示**********************************/ void Pdisplay(float p){
if(p>999400.00)
{
if(p<10004000.00)
{sprintf(buff,“ Cycle:%2.4fs ”,(p/1000000.00));}
else
{sprintf(buff,“error(Time or F)”,p);}
}
else
{
if(p>9950.00)
{sprintf(buff,“ Cycle:%4.2fms ”,(p/1000.00));}
else
{
if(p>0.248)
{sprintf(buff,“ Cycle:%3.3fus ”,p);}
else
{sprintf(buff,“error(Time or F)”,p);}
}
}
GotoXY(0,1);
Print(buff);}
/*********************测试频率**************************/ void cepin(){ unsigned char a;unsigned long js;m=0;n=0;TMOD=0x51;TH0=0x3c;
//定时50ms TL0=0xb0;TH1=0;TL1=0;a=sj/50000.00;TCON=0x50;
//启动定时器和计数器 while(m!=a);TCON=0;js=TH1*256+n*65536+TL1;f=(js/(sj/1000000.00))*fenpin;p=sj/(js*fenpin);if(xs==0)
//设置结束后第一次不显示结果 { if(flag==Freq)Fdisplay(f);else Pdisplay(p);} }
/*********************判断频率******************************/ void panduan(){ xs=0;
//设置结束后第二次循环显示结果 B153=1;
//选择16分频 A153=0;yichu=0;TMOD=0x51;
TH0=0xff;
TL0=0x38;TH1=0xff;
TL1=0x9c;TR0=1;
TR1=1;while(yichu==0);
TR0=0;
TR1=0;
if(yichu==1)
(f>500khz)
{fenpin=16;
cepin();} else
频数
{
yichu=0;
B153=0;
A153=1;
TH0=0xfc;
TL0=0x18;
TH1=0xff;
TL1=0x9c;
TR0=1;
TR1=1;
while(yichu==0);
TR0=0;
TR1=0;
if(yichu==1)
(1khz {fenpin=4; //定时器0 200us //计数器1 100脉冲 //启动定时器0和计数器1 //如果没有溢出一直循环 //已经溢出关闭定时器0和计数器1 //计数器先溢出:在200ms内测得的脉冲过多,说明频率较高 //转为测16分频后的频率 //定时器先溢出:100个脉冲的时间比较短,即频率较低,可以减少分 //定时器0 1ms //计数器1 100个脉冲 //启动定时器0和计数器1 //如果没溢出一直循环 //已经溢出关闭定时器0和计数器1 //计数器先溢出:在1ms内测得的脉冲过多,说明频率较高 //转为测4分频后测频率 cepin();} else //定时器先溢出:100个脉冲的时间比较短,即频率较低 { fenpin=1; B153=0; A153=0; cepin();} } } /*************************显示闸门时间***********************************/ void timedisplay(float GTime){ sprintf(buff,“GTime=%7.0fus ”,GTime);GotoXY(0,1);Print(buff);Delay(50);} /***************************减按键*******************************/ void Time_Set2(){ Delay(1000);if(P17==1) { sj=sj-50000.00; if(sj>50000.00)timedisplay(sj); else {sj=50000.00; timedisplay(sj);} } else {while(P17==0) { Delay(500); sj=sj-500000.00; if(sj>50000.00)timedisplay(sj); else {sj=50000.00; timedisplay(sj);} } } } /***************************加按键**********************************/ void Time_Set1(){ Delay(1000)if(P16==1) { sj=sj+50000.00; if(sj<10000000.00)timedisplay(sj); else {sj=10000000.00; timedisplay(sj);} } else {while(P16==0) { Delay(500); sj=sj+500000.00; if(sj<10000000.00)timedisplay(sj); else {sj=10000000.00; timedisplay(sj);} //按住1s快加0.5s } } } /************************闸门时间设置***********************************/ void Time_Set()interrupt 0 { EA=0; //防止无限中断 Delay(100);if(Set==0) { Delay(1000); //判断处于哪种设置状态 if(Set==1) { GotoXY(0,1); Print(“ Press Button ”); GotoXY(0,0); Print(“ T Settings ”); while(Set==1) { switch(Key_Set) { case K1: Time_Set1();break; case K2: Time_Set2();break; default: break; } } } else //选择测试频率或周期 { GotoXY(0,1); Print(“ 1.Freq 2.Cycle”); GotoXY(0,0); Print(“ Select ”); while(Set==0); //等待设置按键松开 while(Set==1) { switch(Key_Set) { case K1: flag=Freq;GotoXY(0,1);Print(“ ---Freq--- case K2: flag=Peri;GotoXY(0,1);Print(” ---Cycle--- default: break; } } } } GotoXY(0,0);Print(“---Cymometer---”); GotoXY(0,1);Print(“ Waiting...”);while(Set==0); //防止再次进入中断 EA=1;xs=1; //不显示此次结果.} /**************************主程序****************************/ void main(){ LCD_Initial(); //LCD初始化 GotoXY(0,0);Print(“---Cymometer---”);GotoXY(0,1);Print(“ Huixi && Xia”);Delay(1000);GotoXY(0,1);Print(“ Waiting...”); “);break;”);break; C52_Initial(); //89c52初始化 while(1) { panduan(); } } 5、调试过程 程序的设计及调试过程中离不开89C52的开发系统板电路图,起初忽视了开发板上的K3键用到的P35引脚也是定时器T1的信号输入引脚。后来在其他管脚的分配也曾出现错误,不过通过调试、修改都一一改正。仿真的时候默认晶振是12MHz,故程序编写的时候按12MHz设计的定时,以至于在实体时候测量不是很准确,后通过重新计算、修改程序达到了较高的准确率。但最终在实体系统演示中犯了一个极其幼稚的错误,未拿掉短接帽,以至于起初LCD未任何显示,浪费了不少时间去找程序的问题,还是自己不够认真细心。 6、实验结果 (1)最终实物图 最终实体电路系统如图6-1。 图6-1最终实物图 该课程设计验收时结果符合设计要求,可测量矩形波,方波,三角波,锯齿波等信号的频率;测量范围为0.1Hz~4MHz;闸门时间为0.05s~10s可调。 (2)电路仿真分析 由于实物演示不方便,这里用仿真图进行说明: 如下图,开关K1、K2、SET分别代表实物单片机最小系统上的开关K5、K4、K6。SET为确认键,K1可以选择频率输出,K2可以选择周期输出。K1、K2配合还可以调节阀门时间。 下图为开关仿真图和结果显示图: 开关K1,K2选择测周、测频及闸门时间的增减,SET键用于功能切换及确认 初始显示 选择测频率或测周期 频率显示 周期显示 改变阀门时间 7、总结与感悟 本设计通过运用单片机AT89S52,Proteus 仿真软件以及Kell 仿真软件的相关知识,成功地实现了数字频率计的设计。综合调试结果表明,本文提出的设计与传统测频系统相比,具有体积小、成本低、低功耗、精度高等优点,适用于各种测量电路。 本次设计的低频测量部分及高频测量部分分别采用测频、测周的测量方法,并通过计算精确计数,故测量误差很小,再加上智能分频使单片机的测量带宽提高了一千倍以上,仅用几个芯片搭成的低成本简单电路,使该频率计拥有了不错的性价比,且完全可以满足一般的测量需求。本次课程设计由前期自己查资料、想设计思路、写代码及画电路图,然后在实验室多半天基本完成。总体来说还算顺利,所以前期做足准备工作很重要。通过本次课设,我们复习了老师所讲的C51知识,通过将所学的课本知识用于实践,即体会到了知识运用所得成果的快乐,又加深了我对知识的理解,印象更加深刻。通过参加竞赛及此次课设,我深刻体会到无论设计什么,首先要分析需求,根据所学设计构思,只要思路出来了编程的大致方向确定,问题就解决一半。另外,很多东西都是有前人经验的,并不是要我们只会盲目埋头自己苦干,要学会搜集资料,总结前人经验教训用于自己的设计,达到事半功倍的效果。在电路设计及编程、仿真以及最后的搭建实体电路系统中,任何一个环节中细节都不容忽视,比如焊接前外围电路板的排版布局,拿到新的洞洞板要先看构造,综合考虑电路需要,想好布局再焊,尽量避免错误焊接,吸掉重焊。这样既影响美观,又可能损坏电路板。另外,仿真只是初步的检验设计构思是否满足设计需要,仿真效果完美在实体系统调试运行中还是会遇到各种各样的问题亟待解决。总的来说,做任何设计要有清楚的头脑,做好准备工作,还要有耐心、细心,以及团队合作意识。每次的动手设计都能让我学到很多,有知识有心态,实践中的学习总会印象深刻! 数字频率计设计 1.设计任务 设计一简易数字频率计,其基本要求是: 1)测量频率范围1Hz~10Hz,量程分为4档,即×1,×10,×100,×1000。2)频率测量准确度fx2103.fx3)被测信号可以是下弦波、三角波和方波。4)显示方式为4位十进制数显示。5)使用EWB进行仿真。2.设计原理及方案 频率的定义是单位时间(1s)内周期信号的变化次数。若在一定时间间隔T内测得周期信号的重复变化次数为N,则其频率为 f=N/T 据此,设计方案框图如图1所示。 图1 数字频率计组成框图 其基本原理是,被测信号ux首先经整形电路变成计数器所要求的脉冲信号,频率与被测信号的频率fx相同。时钟电路产生时间基准信号,分频后控制计数与保持状态。当其高电平时,计数器计数;低电平时,计数器处于保持状态,数据送入锁存器进行锁存显示。然后对计数器清零,准备下一次计数。其波形逻辑关系图如图2所示。3.基本电路设计 1)整形电路 整形电路是将待测信号整形变成计数器所要求的脉冲信号。电路形式采用由555定时器所构成的施密特触发器,电路如图XXX所示。若待测信号为三角波,输入整形电路,设置分析为瞬态分析,启动电路,其输入、输出波形如图XXX所示。可见输出为方波,二者频率相同。 2)时钟产生电路 时钟信号是控制计数器计数的标准时间信号,其精度很大程度上决定了频率计的频率测量精度。当要求频率测量精度较高时,应使用晶体振荡器通过分频获得。在此频率计中,时钟信号采用555定时器构成的多谐振荡器电路,产生频率为1Kz的信号,然后再进行分频。多谐振荡器电路如图XXX所示。由555定时器构成多谐振荡器的周期计算公式为 XXXXXXXXXX 取XXXXXXXXXXXXXX,则得到振荡频率为1Kz的负脉冲,其振荡波形如图XXX所示。3)分频器电路 采用计数器构成分频电路,对1Kz的时钟脉冲进行分频,取得不同量程所需要的时间基准信号,实现量程控制。1Kz的时钟脉冲,对其进行3次10分频,每个10分频器的输出信号频率分别为100Hz,10Hz,1Hz三种时间基准信号。对应于以1Kz,100Hz,10Hz,1Hz的信号作为时间基准信号时,相应的量程为×1000,×100,×10,×1。 构成10分频带电路是采用十进制计数器74LS160实现的。具体电路及其输入、输出波形如图XXX所示。 (1)T触发器 T触发器电路是用来将分频带器输出阻抗的窄脉冲整形为方波,因为计数器需要用方波来控制其计数/保持状态的切换。整形后方波的频率为频器输出信号频率的一半,则对应于1Kz,100Kz,10Kz,1Hz的信号,T触发器输出信号的高电平持续时间分别为0.001s,0.01s,0.1s,1s。T触发器采用JK触发器7473为实现,其电路连接图及其输入、输出波形如图XXX所示。 (2)单稳触发器 单稳触发器用于产生一窄脉冲,以触发锁存器,使计数器在计数完毕后更新锁存器数值。单稳触发器电路采用555定时器实现,为了保证系统正常工作,单稳电路产生的脉冲宽度不能大于该量程分频带器输出信号的周期。例如,计数器的最大量程是×1000,对应分频带器输出的时间基准信号频率为1000Hz,周期是1ms。取单稳电路输出脉冲宽度TW=0.1ms。根据TW=1.1RC,取C=0.01Uf,则R=9.8KΩ,取标称什为10KΩ。单稳触发器输入信号是T触发器输出信号经Rd、Cd组成的微分器将方波变成尖脉冲后加到555定时器的触发器。电路图及输入、输出波形如图XXX所示。 (3)延迟反相器 延时反相器的功能是为了得到一个对计数器清零的信号。由于计数器清零是低电平有效,而且计数器清零必须在单稳触发信号之后,故延迟反相器是在上述单稳电路之后,再加一级单稳触发电路,且在其输出端加反相器输出。其输入、输出波形如图XXX所示。(4)计数器 计数器在T触发器输出信号的控制下,对经过整形的待测信号进行脉冲计数,所得结果乘以量程即为待测信号频率。 根据精度要求,采用4个十进制计数器级联,构成N=1000计数器。十进制计数器仍采用74LS160实现。其电路图如图XXX所示。其中计数器的清零信号由延迟反相器提供,控制信号由T触发器提供,计数器输出结果送入锁存器。 (5)锁存器和显示 计数器的结果进入锁存器锁存,4个七段数码管显示测试信号的频率。锁存器使用了两片8D集成触发器实现,其控制信号来自于延迟反相器,具体电路如图XXX所示。 (6)数字频率计的总体电路 图XXX是数字频率计的总体电路图。 4.测试 搭建好以上电路以后,进行调试,首先分模块进行调试,待每一个模块调试正确后,不规则进行联调。因为整个电路的分析是瞬态分析,故总体电路的分析需要较长时间。以上仅仅是学生所做综合电路分析与设计的例子,由于EWB5.12教学版本库元件的限制,有些电路与系统无法进行全部电路的仿真(例如收发信通信系统等),但有些局部电路也可以进行仿真,从而节省对这部分电路设计化费的时间。 //********************************************************************* //* 标题: 简易数字频率计 //* 文件: topdesign.v //* 作者: SJ&QJY //* 日期: 2009.06.10 //* 修改: 2009.12.20 //* 软件: Xilinx ISE 7.1 SP4 //* 芯片: Xilinx Spartan2 FPGA(XC2S200-pq208) //* 说明: 测频率并用LCD显示,从信号源接入一个信号(正弦波,三角波或者方波),经过AD1转换后,送入FPGA中。 //在FPGA中,使用双值法整形,得到标准的方波,然后测出频率,并送入1602中显示。经测试,其测频误差小于0.5%,其测频范围为10Hz-10MHz。 //********************************************************************* //* 注意: 输入信号电压峰峰值不要超过AD输入范围,即4V。 //********************************************************************* //---------------module topdesign(clk, rst, lcd_rs, lcd_rw, lcd_en, lcd_d, ad1_clk, ad1_d); input clk; //时钟信号40MHz input rst; //全局复位信号 output lcd_rs;//LCD数据/命令选择信号,'1'表示数据输入,'0'表示命令输入 output lcd_rw; //LCD读/写信号,'1'表示读,'0'表示写 output reg lcd_en; //LCD使能信号,'1'有效 output[7:0] lcd_d; //LCD数据总线(8位) output ad1_clk; //AD时钟信号 input[11:0] ad1_d; //AD9224,12位AD输入 //LCD时序常量信号 parameter[10:0] IDLE = 11'b00000000000; //初始化 parameter[10:0] CLEAR = 11'b00000000001; //清屏 parameter[10:0] RETURNCURSOR = 11'b00000000010;//归位 parameter[10:0] SETMODE = 11'b00000000100; //设置输入模式。此状态为完成一个字符码传送后,AC自动减1,显示不发生移位 parameter[10:0] SWITCHMODE = 11'b00000001000;//显示开关控制 parameter[10:0] SHIFT = 11'b00000010000;//光标或显示移位 parameter[10:0] SETFUNCTION = 11'b00000100000;//功能设置:数据总线选8位还是4位 parameter[10:0] SETCGRAM = 11'b00001000000;//CGRAM的地址设置 parameter[10:0] SETDDRAM = 11'b00010000000; //DDRAM地址设置 parameter[10:0] READFLAG = 11'b00100000000;//读忙标志BF和AC parameter[10:0] WRITERAM = 11'b01000000000; //写数据到CGRAM或DDRAM parameter[10:0] READRAM = 11'b10000000000; parameter cur_inc = 1'b1; parameter cur_dec = 1'b0; parameter cur_shift = 1'b1; parameter cur_noshift = 1'b0; parameter open_display = 1'b1; parameter open_cur = 1'b0; parameter blank_cur = 1'b0; parameter shift_display = 1'b1; parameter shift_cur = 1'b0; parameter right_shift = 1'b1; parameter left_shift = 1'b0; parameter datawidth8 = 1'b1; parameter datawidth4 = 1'b0; parameter twoline = 1'b1; parameter oneline = 1'b0; parameter font5x10 = 1'b1; parameter font5x7 = 1'b0; reg[10:0] state; //时序信号 reg[5:0] counter; reg[3:0] div_counter; reg flag; //辅助时序信号 parameter DIVSS = 4'd15; reg[5:0] char_addr; reg[7:0] data_in; //延迟参量信号 reg clk_int; reg[19:0] clkcnt; parameter[19:0] divcnt = 20'b***00000; reg clkdiv; wire tc_clkcnt; //测频部分 parameter[15:0] ad_d_chankao1 = 16'b***1; parameter[15:0] ad_d_chankao2 = 16'b***1; reg[15:0] ad1_d_r; //计数部分 reg[25:0] yimiao; //用来计数 reg rukou; //整形方波 reg[3:0] odata7; //记录数据 reg[3:0] odata6; reg[3:0] odata5; reg[3:0] odata4; reg[3:0] odata3; reg[3:0] odata2; //将近-25mV //将近25mV reg[3:0] odata1; reg[3:0] odata0; reg[7:0] data7; reg[7:0] data6; reg[7:0] data5; reg[7:0] data4; reg[7:0] data3; reg[7:0] data2; reg[7:0] data1; reg[7:0] data0; reg yimiao_rst; //将记录的数据转换成ASCII码,以便显示 //数据清零信号 //主程序 assign ad1_clk = clk; always @(posedge clk) begin yimiao_rst =(yimiao == 26'b***00111111111)? 1'b0 : 1'b1;//一秒时清零信号有效 end //测频部分 always @(posedge clk) begin ad1_d_r <= {ad1_d, 4'b0000}; if(ad1_d_r > ad_d_chankao2) rukou <= 1'b1; if(ad1_d_r < ad_d_chankao1) rukou <= 1'b0; end //1秒钟测频 always @(posedge clk) //每1秒钟循环一次 begin if(yimiao == 26'b***01000000000) yimiao <= 26'b***00000000000; else yimiao <= yimiao + 1; end //计数部分 always @(posedge rukou or negedge yimiao_rst) if(~yimiao_rst) begin odata0 <= 4'b0000; odata1 <= 4'b0000; odata2 <= 4'b0000; odata3 <= 4'b0000; odata4 <= 4'b0000; odata5 <= 4'b0000; odata6 <= 4'b0000; odata7 <= 4'b0000; end else if(yimiao < 26'b***00111111111) begin begin if(odata0 == 4'b1001) begin odata0 <= 4'b0000; if(odata1 == 4'b1001) begin odata1 <= 4'b0000; if(odata2 == 4'b1001) begin odata2 <= 4'b0000; if(odata3 == 4'b1001) begin odata3 <= 4'b0000; if(odata4 == 4'b1001) begin odata4 <= 4'b0000; if(odata5 == 4'b1001) begin odata5 <= 4'b0000; if(odata6 == 4'b1001) begin odata6 <= 4'b0000; if(odata7 == 4'b1001) begin odata7 <= 4'b0000; end else begin odata7 <= odata7 + 1; end end else begin odata6 <= odata6 + 1; end end else begin odata5 <= odata5 + 1; end end else begin odata4 <= odata4 + 1; end end else begin odata3 <= odata3 + 1; end end else begin odata2 <= odata2 + 1; end end else begin odata1 <= odata1 + 1; end end else begin odata0 <= odata0 + 1; end end end //码制转换 always @(posedge clk) begin if(yimiao == 26'b***00111110110) begin data7 <= {4'b0011, odata7}; //将二进制BCD码转换成ASCII码,即1602可以显示的码值 data6 <= {4'b0011, odata6}; data5 <= {4'b0011, odata5}; data4 <= {4'b0011, odata4}; data3 <= {4'b0011, odata3}; data2 <= {4'b0011, odata2}; data1 <= {4'b0011, odata1}; data0 <= {4'b0011, odata0}; end end //时钟分频 always @(posedge clk) begin if(clkcnt == divcnt) begin clkcnt <= 20'b***00000; end else begin clkcnt <= clkcnt + 1; end end assign tc_clkcnt =(clkcnt == divcnt)? 1'b1 : 1'b0;//tc_clkcnt 0.016s产生一次脉冲 always @(posedge tc_clkcnt) begin clkdiv <= ~clkdiv; 0.032s end always @(posedge clkdiv) begin clk_int <= ~clk_int; end //显示界面设置 always @(negedge clkdiv) begin lcd_en <= ~lcd_en; end always @(char_addr) begin case(char_addr) 6'b000000 : //I //clkdiv 0.016s翻转一次,周期为 //clk_int 0.032s翻转一次,周期为0.064s begin data_in <= 8'b01001001; end 6'b000001 ://n begin data_in <= 8'b01101110; end 6'b000010 : //p begin data_in <= 8'b01110000; end 6'b000011 : //u begin data_in <= 8'b01110101; end 6'b000100 : //t begin data_in <= 8'b01110100; end 6'b000101 : //空格 begin data_in <= 8'b00100000; end 6'b000110 : //F begin data_in <= 8'b01100110; end 6'b000111 : //r begin data_in <= 8'b01110010; end 6'b001000 : //e begin data_in <= 8'b01100101; end 6'b001001 : //q begin data_in <= 8'b01110001; end 6'b001010 : //u begin data_in <= 8'b01110101; end 6'b001011 : //e begin data_in <= 8'b01100101; end 6'b001100 : //n begin data_in <= 8'b01101110; end 6'b001101 : //c begin data_in <= 8'b01100011; end 6'b001110 : //y begin data_in <= 8'b01111001; end 6'b001111 : //空格 begin data_in <= 8'b00100000; end 6'b101000 : //“=” begin data_in <= 8'b00111101; end 6'b101001 : //若为零则显示空格 begin if(data7 == 8'b00110000) begin data_in <= 8'b00100000; end else begin data_in <= data7; end end 6'b101010 : //若为零则显示空格 begin data_in <= data6; if(data6 == 8'b00110000 & data7 == 8'b00110000) begin data_in <= 8'b00100000; end else begin data_in <= data6; end end 6'b101011 : //若为零则显示空格 begin data_in <= data5; if(data5 == 8'b00110000 & data6 == 8'b00110000 & data7 == 8'b00110000) begin data_in <= 8'b00100000; end else begin data_in <= data5; end end 6'b101100 : //若为零则显示空格 begin data_in <= data4; if(data4 == 8'b00110000 & data5 == 8'b00110000 & data6 == 8'b00110000 & data7 == 8'b00110000) begin data_in <= 8'b00100000; end else begin data_in <= data4; end end 6'b101101 : //若为零则显示空格 begin data_in <= data3; if(data3 == 8'b00110000 & data4 == 8'b00110000 & data5 == 8'b00110000 & data6 == 8'b00110000 & data7 == 8'b00110000) begin data_in <= 8'b00100000; end else begin data_in <= data3; end end 6'b101110 : //若为零则显示空格 begin data_in <= data2; if(data2 == 8'b00110000 & data3 == 8'b00110000 & data4 == 8'b00110000 & data5 == 8'b00110000 & data6 == 8'b00110000 & data7 == 8'b00110000) begin data_in <= 8'b00100000; end else begin data_in <= data2; end end 6'b101111 : //若为零则显示空格 begin data_in <= data1; if(data1 == 8'b00110000 & data2 == 8'b00110000 & data3 == 8'b00110000 & data4 == 8'b00110000 & data5 == 8'b00110000 & data6 == 8'b00110000 & data7 == 8'b00110000) begin data_in <= 8'b00100000; end else begin data_in <= data1; end end 6'b110000 : begin data_in <= data0; end 6'b110110 : //H begin data_in <= 8'b01001000; end 6'b110111 : //z begin data_in <= 8'b01111010; end default : begin data_in <= 8'b00100000; end endcase end assign lcd_rs =(state == WRITERAM | state == READRAM)? 1'b1 : 1'b0; assign lcd_rw =(state == CLEAR | state == RETURNCURSOR | state == SETMODE | state == SWITCHMODE | state == SHIFT | state == SETFUNCTION | state == SETCGRAM | state == SETDDRAM | state == WRITERAM)? 1'b0 : 1'b1; assign lcd_d =(state == CLEAR)? 8'b00000001 :(state == RETURNCURSOR)? 8'b00000010 :(state == SETMODE)? {6'b000001, cur_inc, cur_noshift} :(state == SWITCHMODE)? {5'b00001, open_display, open_cur, blank_cur} :(state == SHIFT)? {4'b0001, shift_display, left_shift, 2'b00} :(state == SETFUNCTION)? {3'b001, datawidth8, twoline, font5x10, 2'b00} :(state == SETCGRAM)? 8'b01000000 :(state == SETDDRAM & counter == 0)? 8'b10000000 :(state == SETDDRAM & counter!= 0)? 8'b11000000 :(state == WRITERAM)? data_in : 8'bZZZZZZZZ; //时序进程 always @(posedge clk_int or posedge rst) begin if(rst) begin state <= IDLE; counter <= 0; div_counter <= 0; flag <= 1'b0; char_addr <= 6'b000000; end else case(state) IDLE : begin if(flag == 1'b0) begin state <= SETFUNCTION; flag <= 1'b1; counter <= 0; div_counter <= 0; end else begin if(div_counter < DIVSS) begin div_counter <= div_counter + 1; state <= IDLE; end else begin div_counter <= 0; state <= IDLE; end end end CLEAR : begin state <= SETMODE; end SETMODE : begin state <= WRITERAM; end RETURNCURSOR : begin state <= WRITERAM; end SWITCHMODE : begin state <= CLEAR; end SHIFT : begin state <= IDLE; end SETFUNCTION : begin state <= SWITCHMODE; end SETCGRAM : begin state <= IDLE; end SETDDRAM : begin state <= WRITERAM; end READFLAG : begin state <= IDLE; end WRITERAM : //可用来修改,实现1602的输出显示 begin if((counter >= 6'd0 & counter <= 6'd14)|(counter >= 6'd40 & counter <= 6'd54)) begin state <= WRITERAM; //一行同时只能显示16个字符,第二行的首地址为40 char_addr <= char_addr + 1; counter <= counter + 1; end else if(counter > 6'd14) //换到第二行显示 begin state <= SETDDRAM; counter <= 6'd40; char_addr <= 6'b101000; end else begin state <= SHIFT; state <= READRAM; end end READRAM : begin state <= IDLE; end default : begin state <= IDLE; end endcase end endmodule第四篇:数字频率计设计
第五篇:数字频率计