目录 一、需求分析 二、方案设计 1设计基本原理·······························································4 1.1测量频率的原理·······················································4 1.2系统设计框图·························································4 三、软件设计··································································5 1资源分配表·································································5 2程序流程框图·······························································6 四、系统硬件线路设计图·····················································7 1 单片机最小系统设计·······················································7 2 液晶LCD1602显示 电路····················································8 3 频率测量电路······························································11 五.系统 仿真、测试结果及性能分析·······································12 1系统仿真、测试结果························································12 2性能分析·····································································13 六、心得与体会·································································14 七、参考文献·····································································14 摘 要 本设计提出了一种基于AT89C51单片机开发的数字频率测量仪的设计。系统以单片机AT89C51为核心,构成完备的测量系统。可以对信号进行频率的精确测量,测频在1Hz至10kHZ。采用液晶LCD1602显示被测信号的频率。与传统的电路系统相比,其有处理速度快、稳定性高、性价比高、硬件结构简单的优点。
关键词:单片机;低频;绝对误差 一、需求分析 频率测量在科技研究和实际应用中的作用日益重要。传统的频率计通采用组合电路和时序电路等大量的硬件电路构成,产品不但体积较大,运行速度慢,而且测量低频信号时不宜直接使用。频率信号抗干扰性强、易于传输,可以获得较高的测量精度。同时,频率测量方法的优化也越来越受到重视.并采用AT89C51 单片机和相关硬软件实现。MCS—51系列单片机具有体积小,功能强,性能价格比较高等特点,因此被广泛应用于工业控制和智能化仪器,仪表等领域。我们研制的频率计以89c51单片机为核心,具有性能优良,精度高,可靠性好等特点。 二、设计方案 此次课程设计采用间接测量法来测量。要用到GATE信号,GATE=1时,TR0=1,INTO=1才能启动计数器,而计数器0是通过外部中断INTO的下降沿开始触发的,计时器从0开始计时,计数器只能测高电平,因此测得的时间为半个周期。当计数器0计时溢出,执行m加1的操作。则测量时间为:t1=TH0*256+TL0+m*65536 ,所求频率F=1000000/(2*t1) 1设计基本原理 1.1测量频率的原理 定时/计数器工作在方式1,每产生一次定时器0中断,计数65536个脉冲,此时的脉冲来自振荡器的12分频后的脉冲,其周期为1uS。根据产生外部中断0时,定时器0中断的次数u,以及此时定时/计数器0计数寄存器的数值X,即可求得待测方波的周期为:T=(65536*u+X)us ,取其倒数即可求得待测方波的频率,小数点后保留两位,即可使得频率精度为0.1HZ。 1.2系统设计框图 经过方案论证和比较后,最终确定的系统框图如图1所示,主要由 AT89C51单片机、异或器件、 LCD1602、电源等组成。 图2 系统设计框图 三、软件设计 1资源分配表 表5 资源分配表 2程序流程框图 频率程序流程图如图9所示: 图10 程序流程图 四、系统硬件线路设计图 1 单片机最小系统设计 单片机最小系统是能补足单片机工作的最简单电路,它由单片机、电源、晶体振荡器、复位电路等构成。它是本系统的处理单元也是控制单元,负责处理信号、外设的接口与控制,同时它也是所有软件的载体。 本系统采用AT89C51是美国Atmel公司生产的低电压、高性能CMOS 8位单片机,片内含4KB的可反复檫写的程序存储器和12B的随机存取数据存储器(RAM),器件采用Atmel公司的高密度、非易失性存储技术生产,片内配置通用8位中央处理器(CPU)和Flash存储单元,功能强大的AT89C51单片机可灵活应用于各种控制领域。与Intel公司的80C51在引脚排列、硬件组成、工作特点和指令系统等方面兼容。 主要管脚有: XTAL1(19 脚)和XTAL2(18 脚)为振荡器输入输出端口,外接12MHz 晶振。 RST/Vpd(9 脚)为复位输入端口,外接电阻电容组成的复位电路。 VCC(40 脚)和VSS(20 脚)为供电端口,分别接+5V电源的正负端。 P0~P3 为可编程通用I/O 脚,其功能用途由软件定义。 其管脚如下图所示: 图3 AT89C51单片机管脚图 本设计中,P0 端口(32~39 脚)被定义为N1 功能控制端口,分别与N1的相应功能管脚相连接。单片机正常工作时,都需要有一个时钟电路和一个复位电路。本设计 中选择了内部时钟方式和按键电平复位电路,来构成单片机的最小电路。如图3所示。 图4 单片机最小系统 2液晶LCD1602显示电路 字符型液晶显示模块是一种专门用于显示字母、数字、符号等点阵式LCD,目前常用16*1,16*2,20*2和40*2行等的模块。LCD1602分为带背光和不带背光两种,基控制器大部分为HD44780,带背光的比不带背光的厚,是否带背光在应用中并无差别。LCD1602采用标准的14脚(无背光)或16脚(带背光)接口,各引脚接口说明如下表1所示: 表 1 LCD1602引脚接口说明 1602液晶模块的读写操作、屏幕和光标的操作都是通过指令编程来实现的。1602液晶模块内部的控制器共有11条控制指令,如下表2所示,其中1为高电平、0为低电平。 表 2 LCD1602控制指令 指令1:清显示,指令码01H,光标复位到地址00H位置。 指令2:光标复位,光标返回到地址00H。 指令3:光标和显示模式设置 I/D:光标移动方向,高电平右移,低电平左移 S:屏幕上所有文字是否左移或者右移。高电平表示有效,低电平则无效。 指令4:显示开关控制。 D:控制整体显示的开与关,高电平表示开显示,低电平表示关显示 C:控制光标的开与关,高电平表示有光标,低电平表示无光标 B:控制光标是否闪烁,高电平闪烁,低电平不闪烁。 指令5:光标或显示移位 S/C:高电平时移动显示的文字,低电平时移动光标。 指令6:功能设置命令 DL:高电平时为4位总线,低电平时为8位总线 N:低电平时为单行显示,高电平时双行显示 F: 低电平时显示5x7的点阵字符,高电平时显示5x10的点阵字符。 指令7:字符发生器RAM地址设置。 指令8:DDRAM地址设置。 指令9:读忙信号和光标地址 BF:为忙标志位,高电平表示忙,此时模块不能接收命令或者数据,如果为低电平表示不忙。 指令10:写数据。 与HD44780相兼容的芯片时序如下表3所示: 表 3 基本操作时序表 | | | | | | | RS=L,R/W=L, D0—D7=指令码,E=高脉冲 | | | | | | | | | | RS=H,R/W=L, D0—D7=数据,E=高脉冲 | | |
其操作时序图如下所示: 图5 读操作时序图 图6 写操作时序图 本设计中采用液晶LCD1602显示输入方波A的频率,其D0~D7与单片机的P0端口连接,使能端E、RS、RW分别与单片机P2.4、P1.7、P1.6连接,此电路原理简单,电路连接方便,如图7所示。 图7 液晶LCD1602显示电路 3频率测量电路 本设计中将方波A输入,采用定时中断测量其频率。如图7所示。 图8 频率测量电路 综上所述,频率的总体电路图如图9所示: 图9 频率计的总体电路图 五.系统仿真、测试结果及性能分析 1系统仿真、测试结果 在仿真软件PROTUES中按照电路图连接好电路。输入待测方波信号波形,当测试频率时,先依次设置好方波A的频率,进行仿真测得数据;测试波形和结果如图11所示: 图11 仿真波形 表6 仿真频率测试结果 2性能分析 根据表6测试所得结果可以看出:,频率范围为1Hz~3000HZ;频率误差少于1Hz.当输入频率大于4000HZ时,频率误差小于6HZ,并且随着输入频率增大,频率误差逐渐增大。由此可得如下结论:本次所设计的频率适合测试低频信号,最佳频率范围为1-3000HZ,输入方波任意均可。 六、心得与体会 刚刚拿到做频率计这个题目时,我们的感觉可以说是比较轻松的,在一开始的时候也不算太着急。过了几天后,我和几个组员开始打算动手去做了,这时才感觉到频率计不是那么容易做的。虽然心中有个大概的想法,但要实施起来时才觉得不知从哪里入手。 可是我们还是硬着头皮做了,我和组长曾潜,组员孙凯开始上网了解频率计的具体做法。通过几个小时的讨论,终于大概定出了本次设计的思路、流程与分工。在本次的设计中,我主要负责做 PCB版和协助组长曾潜设计详细的程序。通过好几天的努力,我们终于做出了最初的设计,但是程序在仿真图片中的显示不正常,误差也很大。我们三人通过不断的修改,调试,终于,做出了基本符合要求的51单片机频率计。 这次的频率计设计,虽然在过程中也走了不少的弯路,但终究是学到许多知识,学到课堂上没有的知识,除了实践上的,理论上的知识也有。除此之外,我还认识到了与人合作的重要性,这次设计如果只是我一个人做是很有可能做不出来的,在设计中往往会遇到一些个人弄很长时间都弄不明白的地方,但几个人一起讨论后就往往会害然开朗。 由于本次设计时间的安排还是不够合理,设计中还有很多不够完美的地方,系统中还有许多有待改进的地方。 最后,要感谢老师,给我们一个把理论应用到实践的机会,也感谢同学们在我困难的时候能伸出援手,谢谢。 七、参考文献 【1】周美娟、肖来胜编著。《单片机技术及系统设计》,清华大学出版社 【2】谭浩强编著。《C程序设计》,清华大学出版社 附录一:仿真图 附录二:原理图 附录三:PCB图 附录四:源程序 #include #include #define uint unsigned int #define uchar unsigned char uchar m=0; uchar u; uint i; uint x; uint c; //相位数据结果保存 float t0,f; uint a[]={70,61,48,48,48,48,48,46,48,48,72,90}; //频率数据结果保存 //F,=,0,0,0,0,0,.,0,0,H,Z ***it lcdrw=P1^6; ***it lcdrs=P1^7; ***it lcden=P2^4; /////////////////LCD1602的设置////////////////////////////////// void delay(uint s)//延时1MS { uint r,g; for(r=s;r>0;r--) for(g=110;g>0;g--); } void write_com(uchar com) // 写指令 { lcdrs=0; P0=com; delay(5); lcden=1; delay(5); lcden=0; } void write_data(uchar date) // 写数据 { lcdrs=1; P0=date; delay(5); lcden=1; delay(5); lcden=0; } void initlcd()//初始化 { lcdrw=0; lcden=0; //write_com(0x01);//显示清屏 write_com(0x38);//显示模式设置 write_com(0x0c); //显示开,开游标,不闪烁 write_com(0x06); // 字符时整体不移动 } ////////////LCD1602设置/////////////// ///////////定时器的设置////////////// void CT_init() //定时计数器初始化 { TMOD=0x99; //GATE=1,T1、T0工作在方式1,定时方式 TH0=0; //定时计数器初值清零 TL0=0; // TH1=0; // TL1=0; TR0=1; //TR0,TR1置位,此时定时计数器的启动有INT0,INT1引脚电平决定 // TR1=1; ET0=1; //开中断 // ET1=1; } void ITC0() interrupt 0 //外部中断0服务程序 { u=m; //读定时计数器0溢出次数 m=0; //溢出次数清零 x=TH0*256+TL0; //读定时计数器0当前值 TH0=0; //定时计数器0清零 TL0=0; } void tiME0() interrupt 1 //定时计数器0溢出中断 { m++; //溢出次数加1 } ////////////定时器的设置////////////// void main() { initlcd(); //液晶显示初始化 CT_init(); //定时计数器初始化 EA=1; //开总中断 EX0=1; //允许外部中断 // EX1=1; IT0=1; //设置外部中断方式为下降沿触发 // IT1=1; P3=0xff; while(1) { t0=u*65536+x; //计算脉冲时间宽度 f=1000000/(2*t0); //计算频率 c=f*100; //计算结果逐位保存 a[9]=c%10+48; a[8]=(c/10)%10+48; c=f; a[6]=c%10+48; a[5]=(c/10)%10+48; a[4]=(c/100)%10+48; a[3]=(c/1000)%10+48; a[2]=(c/10000)%10+48; write_com(0x80); for(i=0;i<=11;i++) { write_data(a); delay(10); } } }
|