仿真图及报告.zip
(374.05 KB, 下载次数: 164)
一、设计题目:简易频率计 二、设计目的: 1、掌握89C52单片机产生脉冲及定时的简单程序编写。 2、理解频率计的测量原理。 三、设计任务及主要技术指标 3.1. 课程设计的任务 设计并仿真测量频率和相位差的数字频率计。 四、方案设计及论证 4.1测量方案 测量频率的方法有很多种,主要分为模拟法和数字法两大类,因为本次设计的要求和环境,现在主要讨论数字法中的电子计数式的几种测频方法。 电子计数式的测频方法主要有以下几种:脉冲数定时测频法(M法),脉冲周期测频法(T法),脉冲数倍频测频法(AM法),脉冲数分频测频法(AT法),脉冲平均周期测频法(M/T法),多周期同步测频法。下面是几种方案的具体方法介绍。 脉冲数定时测频法(M法):此法是记录在确定时间Tc内待测信号的脉冲个数Mx,则待测频率为: Fx=Mx/Tc (2-1) 脉冲周期测频法(T法):此法是在待测信号的一个周期Tx内,记录标准频率信号变化次数Mo。这种方法测出的频率是: Fx=Mo/Tx (2-2) 脉冲数倍频测频法(AM法):此法是为克服M法在低频测量时精度不高的缺陷发展起来的。通过A倍频,把待测信号频率放大A倍,以提高测量精度。其待测频率为: Fx=Mx/ATo (2-3) 脉冲数分频测频法(AT法):此法是为了提高T法高频测量时的精度形成的。由于T法测量时要求待测信号的周期不能太短,所以可通过A分频使待测信号的周期扩大A倍,所测频率为: Fx=AMo/Tx (2-4) 脉冲平均周期测频法(M/T法):此法是在闸门时间Tc内,同时用两个计数器分别记录待测信号的脉冲数Mx和标准信号的脉冲数Mo。若标准信号的频率为Fo,则待测信号频率为: Fx=FoMx/Mo (2-5) 4.2方案论证 多周期同步测频法:是由闸门时间Tc与同步门控时间Td共同控制计数器计数的一种测量方法,待测信号频率与M/T法相同。 以上几种方法各有其优缺点: 脉冲数定时测频法,时间Tc为准确值,测量的精度主要取决于计数Mx的误差。其特点在于:测量方法简单,测量精度与待测信号频率和门控时间有关,当待测信号频率较低时,误差较大。 脉冲周期测频法,此法的特点是低频检测时精度高,但当高频检测时误差较大。 脉冲数倍频测频法,其特点是待测信号脉冲间隔减小,间隔误差降低;精度比M法高A倍,但控制电路较复杂。 脉冲数分频测频法,其特点是高频测量精度比T法高A倍,但控制电路也较复杂。 脉冲平均周期测频法,此法在测高频时精度较高,但在测低频信号时精度较低。 多周期同步测频法,此法的优点是,闸门时间与被测信号同步,消除了对被测信号计数产生的±1个字误差,测量精度大大提高,且测量精度与待测信号的频率无关,达到了在整个测量频段等精度测量。 此次课程设计采用间接测量法来测量。此次设计涉及到相位差,即两列波形异或得到的波形只需要测高电平,要用到GATE信号,GATE=1时,TR0=1,INTO=1才能启动计数器,而计数器0是通过外部中断INTO的下降沿开始触发的,计时器从0开始计时,计数器只能测高电平,因此测得的时间为半个周期。当计数器0计时溢出,执行m加1的操作。则测量时间为:t1=TH0*256+TL0+m*65536 ,所求频率F=1000000/(2*t1) 。 测量两方波的相位差时,先将两方波信号异或,得到的新波形输入外部中断1的入口,在信号的第n个下跳沿时,进入外部中断的程序,开启计数器1。第n+1个下跳沿到来时,则关闭计数器1,当GATE=1时,只有在INT1=1 时,TR1=1时,计数器T1才开始计数,当计数器0计时溢出,执行m加1的操作,所以读的的时间只为高电平的持续时间,即为两方波的相隔时间t2,相位差可计算如下:t2=TH1*256+TLI+N*65536 ;则相位差P=t2/(2*t1)*360
关键词:单片机;低频;绝对误差 4.3系统设计框图 经过方案论证和比较后,最终确定的系统框图如图1所示,主要由AT89C52单片机、异或器件、LCD1602、电源等组成。
图1 系统设计框图 五、设计基本原理 5.1测量频率的原理 定时/计数器工作在方式1,每产生一次定时器0中断,计数65536个脉冲,此时的脉冲来自振荡器的12分频后的脉冲,其周期为1uS。根据产生外部中断0时,定时器0中断的次数u,以及此时定时/计数器0计数寄存器的数值X,即可求得待测方波的周期为:T=(65536*u+X)us ,取其倒数即可求得待测方波的频率,小数点后保留两位,即可使得频率精度为0.1HZ。 5.2相位差的测量原理 将两路同频不同相的方波信号进过鉴相器(即异或)后得到的脉冲宽度t与方波信号的周期T的比值(占空比),即对应为两信号的相位差,此时相位差
。其中,脉冲宽度的测量方法与方波周期的测量方法相同。相位差测量的原理图如下:
图2 相位差测量原理图 六、单元电路设计,元器件选择,总体电路设计 6.1 单片机最小系统设计 单片机最小系统是能补足单片机工作的最简单电路,它由单片机、电源、晶体振荡器、复位电路等构成。它是本系统的处理单元也是控制单元,负责处理信号、外设的接口与控制,同时它也是所有软件的载体。 本系统采用AT89C52是美国Atmel公司生产的低电压、高性能CMOS 8位单片机,片内含8KB的可反复檫写的程序存储器和12B的随机存取数据存储器(RAM),器件采用Atmel公司的高密度、非易失性存储技术生产,兼容标准MCS-51指令系统,片内配置通用8位中央处理器(CPU)和Flash存储单元,功能强大的AT89C52单片机可灵活应用于各种控制领域。AT89C52单片机属于AT89C51单片机的增强型,与Intel公司的80C52在引脚排列、硬件组成、工作特点和指令系统等方面兼容。 主要管脚有: XTAL1(19 脚)和XTAL2(18 脚)为振荡器输入输出端口,外接12MHz 晶振。 RST/Vpd(9 脚)为复位输入端口,外接电阻电容组成的复位电路。 VCC(40 脚)和VSS(20 脚)为供电端口,分别接+5V电源的正负端。 P0~P3 为可编程通用I/O 脚,其功能用途由软件定义。 其管脚如下图所示:
图3 AT89C52单片机管脚图 本设计中,P0 端口(32~39 脚)被定义为N1 功能控制端口,分别与N1的相应功能管脚相连接。单片机正常工作时,都需要有一个时钟电路和一个复位电路。本设计 中选择了内部时钟方式和按键电平复位电路,来构成单片机的最小电路。如图4所示。
图4 单片机最小系统 6.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和B的频率和相位差,其D0~D7与单片机的P0端口连接,使能端E、RS、RW分别与单片机P2.4、P1.7、P1.6连接,此电路原理简单,电路连接方便,如图7所示。
图7 液晶LCD1602显示电路 6.3频率、相位差测量电路 本设计中将方波A输入,采用定时中断测量其频率,同时将方波A和方波B经过异或门74LS86异或后输入即可测量出两路方波的相位差。 异或门74LS86真值表如表4所示: 表4 74LS86真值表 综上所述,频率、相位表的总体电路图如图8所示:
图8 频率相位表的总体电路图 6.4程序设计 6.4.1资源分配表 表5 资源分配表 七、软件设计 7.1频率、相位表的程序流程图如图所示:
图9 程序流程图 八、安装(仿真)、调试 8.1仿真 仿真软件PROTUES中按照电路图连接好电路。输入两待测方波信号波形,当测试频率时,先依次设置好方波A和B的频率,进行仿真测得数据;当测试相位差,先将方波A和B频率设置为500HZ,然后依次设置相位差,测试波形和结果如图10所示:
图10 仿真波形 表6 仿真频率测试结果 表7 仿真相位差测试结果 8.2性能分析 根据表6测试所得结果可以看出:当输入频率0-550HZ时,频率误差大约为0.05HZ,小于0.1HZ;当输入频率大于600HZ时,频率误差大于0.1HZ,并且随着输入频率增大,频率误差均大于0.1HZ,故输入频率为0-550HZ时满足要求。根据表7测试所得结果可以看出:当输入的两路方波的相位差0-180度时,测试相位差大约为0度,小于0.1度,测试所得相位差性能比较好。由此可得如下结论:本次所设计的频率/相位差表适合测试低频信号,最佳频率范围为0-550HZ,输入方波相位差任意均可。 九、心得与体会 本次课程设计有较强的综合性,不仅要求设计者能灵活使用单片机,熟练使用单片计计数器和定时器,熟练编写顺序结构程序,循环结构程序以及分支结构程序,还要求对单片机的电路连接结构,对数码管芯片有明确清晰的了解与认识,否则在设计的第一步就会遇到障碍。巩固和应用了C语言的程序编写,对于仿真,基于以往对PROTUTES和KEIL的使用,此次仿真更是得心应手,基本上没遇到大问题,不过这次设计学会了虚拟示波器的使用。 看着自己亲自通过自己的知识和努力设计的频率计,心里是很欣慰的,还学到了很多,例如面对问题要保持冷静,特别是在程序的编写这一块,通过大量查阅资料和思考,还有组员的讨论与鼓励,最终解决了问题,使我深刻感知要找出程序的错误一定要保持一个冷静的头脑,否则很难发现错误甚至是越改越错。另外我还认识到与他人合作的重要性,虚心向别人学习,能力和意志力都有所提高。 最后,感谢在这次课程设计中汪斌老师、袁菊明老师及谢东福老师提供的指导和帮助! 十、参考文献 李朝青,刘艳玲.单片机原理及接口技术[M].4版.北京:北京航空航天大学出版社,2013. 附录一: 源程序 - #include
- #include
- #define uint unsigned int
- #define uchar unsigned char
- uchar m=0,n=0;
- uchar u,v;
- uint i,j;
- uint x,y;
- uint c,d; //相位数据结果保存
- float t0,t1,f,p;
- uint a[]={70,61,48,48,48,48,48,46,48,48,72,90}; //频率数据结果保存
- //F,=,0,0,0,0,0,.,0,0,H,Z
- uint b[]={80,61,48,48,48,46,48,48,34}; //相位数据结果保存
- //P,=,0,0,0,.,0,0," //相位数据结果保存
- sbit lcdrw=P1^6;
- sbit lcdrs=P1^7;
- sbit 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 ITC1() interrupt 2 //外部中断1服务程序
- {
- v=n; //读定时计数器1溢出次数
- n=0; //溢出次数清零
- y=TH1*256+TL1; //读定时计数器1当前值
- TH1=0; //定时计数器1清零
- TL1=0;
- }
- void TIME1() interrupt 3 //定时计数器1溢出中断
- {
- n++; //溢出次数加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[i]);
- delay(10);
- }
- t1=v*65536+y; //计算脉冲宽度
- p=(t1/(2*t0))*360; //计算相位差
- d=p*100; //将计算结果逐位保存
- b[7]=d%10+48;
- b[6]=(d/10)%10+48;
- d=p;
- b[4]=d%10+48;
- b[3]=(d/10)%10+48;
- b[2]=(d/100)%10+48;
- write_com(0x80+0X40);
- for(j=0;j<=8;j++)
- {
- write_data(b[j]);
- delay(10);
- }
- }
- }
复制代码
|