找回密码
 立即注册

QQ登录

只需一步,快速开始

搜索
查看: 19815|回复: 3
收起左侧

单片机简易频率计课程设计报告

[复制链接]
ID:137190 发表于 2016-9-26 15:26 | 显示全部楼层 |阅读模式

0.png

仿真图及报告.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.001.jpg

图1 系统设计框图
五、设计基本原理
5.1测量频率的原理
    定时/计数器工作在方式1,每产生一次定时器0中断,计数65536个脉冲,此时的脉冲来自振荡器的12分频后的脉冲,其周期为1uS。根据产生外部中断0时,定时器0中断的次数u,以及此时定时/计数器0计数寄存器的数值X,即可求得待测方波的周期为:T=(65536*u+X)us ,取其倒数即可求得待测方波的频率,小数点后保留两位,即可使得频率精度为0.1HZ。

5.2相位差的测量原理

将两路同频不同相的方波信号进过鉴相器(即异或)后得到的脉冲宽度t与方波信号的周期T的比值(占空比),即对应为两信号的相位差,此时相位差 1.002.jpg 。其中,脉冲宽度的测量方法与方波周期的测量方法相同。相位差测量的原理图如下:

1.003.jpg

图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 脚,其功能用途由软件定义。

其管脚如下图所示:

1.004.jpg

图3 AT89C52单片机管脚图

本设计中,P0 端口(32~39 脚)被定义为N1 功能控制端口,分别与N1的相应功能管脚相连接。单片机正常工作时,都需要有一个时钟电路和一个复位电路。本设计
中选择了内部时钟方式和按键电平复位电路,来构成单片机的最小电路。如图4所示。

1.005.jpg

图4 单片机最小系统

6.2液晶LCD1602显示电路
字符型液晶显示模块是一种专门用于显示字母、数字、符号等点阵式LCD,目前常用16*1,16*2,20*2和40*2行等的模块。LCD1602分为带背光和不带背光两种,基控制器大部分为HD44780,带背光的比不带背光的厚,是否带背光在应用中并无差别。LCD1602采用标准的14脚(无背光)或16脚(带背光)接口,各引脚接口说明如下表1所示:
表 1  LCD1602引脚接口说明

编号

符号

引脚说明

编号

符号

引脚说明

1

VSS

电源地

9

D2

数据

2

VDD

电源正极

10

D3

数据

3

VL

液晶显示偏压

11

D4

数据

4

RS

数据/命令选择

12

D5

数据

5

R/W

读/写选择

13

D6

数据

6

E

使能信号

14

D7

数据

7

D0

数据

15

BLA

背光源正极

8

D1

数据

16

BLK

背光源负极

1602液晶模块的读写操作、屏幕和光标的操作都是通过指令编程来实现的。1602液晶模块内部的控制器共有11条控制指令,如下表2所示,其中1为高电平、0为低电平。
表 2  LCD1602控制指令

序号

指令

RS

R/W

D7

D6

D5

D4

D3

D2

D1

D0

1

清显示

0

0

0

0

0

0

0

0

0

1

2

光标返回

0

0

0

0

0

0

0

0

1

*

3

置输入模式

0

0

0

0

0

0

0

1

I/D

S

4

显示开/关控制

0

0

0

0

0

0

1

D

C

B

5

光标或字符移位

0

0

0

0

0

1

S/C

R/L

*

*

6

置功能

0

0

0

0

1

DL

N

F

*

*

7

置字符发生存贮器地址

0

0

0

1

字符发生存贮器地址

8

置数据存贮器地址

0

0

1

显示数据存贮器地址

9

读忙标志或地址

0

1

BF

计数器地址

10

写数到CGRAM或DDRAM)

1

0

要写的数据内容

指令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=H,E=H

输出

D0—D7=状态字

写指令

输入

RS=L,R/W=L,

D0—D7=指令码,E=高脉冲

输出

读数据

输入

RS=H,R/W=H,E=H

输出

D0—D7=数据

写数据

输入

RS=H,R/W=L,

D0—D7=数据,E=高脉冲

输出

其操作时序图如下所示:

1.006.jpg

图5 读操作时序图

1.007.jpg

图6 写操作时序图

本设计中采用液晶LCD1602显示输入方波A和B的频率和相位差,其D0~D7与单片机的P0端口连接,使能端E、RS、RW分别与单片机P2.4、P1.7、P1.6连接,此电路原理简单,电路连接方便,如图7所示。

1.008.jpg

图7 液晶LCD1602显示电路

6.3频率、相位差测量电路
本设计中将方波A输入,采用定时中断测量其频率,同时将方波A和方波B经过异或门74LS86异或后输入即可测量出两路方波的相位差。

异或门74LS86真值表如表4所示:

表4  74LS86真值表

A

B

C

0

0

0

0

1

1

1

0

1

1

1

0

综上所述,频率、相位表的总体电路图如图8所示:

1.009.jpg

图8 频率相位表的总体电路图
6.4程序设计
6.4.1资源分配表
表5 资源分配表
I/O口
作用
P0
LCD1602数据接口
P1.6
LCD1602 RW接口
P1.7
LCD1602 RS接口
P2.4
LCD1602 E接口
P3.2
频率测量接口
P3.3
相位差测量接口
七、软件设计
7.1频率、相位表的程序流程图如图所示

1.010.jpg

图9   程序流程图
八、安装(仿真)、调试
8.1仿真
仿真软件PROTUES中按照电路图连接好电路。输入两待测方波信号波形,当测试频率时,先依次设置好方波A和B的频率,进行仿真测得数据;当测试相位差,先将方波A和B频率设置为500HZ,然后依次设置相位差,测试波形和结果如图10所示:

1.011.jpg

图10 仿真波形

表6 仿真频率测试结果

输入频率/HZ
0
5
10
50
100
150
200
250
测得频率/HZ
0.99
5.00
10.00
50.00
100.00
150.01
200.00
250.00
输入频率/HZ
300
350
400
450
500
550
600
650
测得频率/HZ
299.94
349.95
400.00
450.04
500.00
550.05
600.24
650.19
输入频率/HZ
700
750
800
850
900
950
1000
1050
测得频率/HZ
699.94
750.26
800.64
850.98
899.92
950.21
1000.64
1050.06

表7 仿真相位差测试结果

输入相位差/度
0
30
45
60
90
120
135
150
测得相位差/度
0
30.06
45.00
59.94
90.00
120.06
135.00
149.94

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.
附录一:
源程序
  1. #include     

  2. #include

  3. #define uint unsigned int

  4. #define uchar unsigned char

  5. uchar m=0,n=0;

  6. uchar u,v;

  7. uint i,j;

  8. uint x,y;

  9. uint c,d;                              //相位数据结果保存

  10. float t0,t1,f,p;

  11. uint a[]={70,61,48,48,48,48,48,46,48,48,72,90};                //频率数据结果保存

  12.                             //F,=,0,0,0,0,0,.,0,0,H,Z

  13. uint b[]={80,61,48,48,48,46,48,48,34};                              //相位数据结果保存

  14.                  //P,=,0,0,0,.,0,0,"                //相位数据结果保存

  15. sbit lcdrw=P1^6;

  16. sbit lcdrs=P1^7;

  17. sbit lcden=P2^4;

  18. /////////////////LCD1602的设置//////////////////////////////////

  19. void delay(uint s)//延时1MS

  20. {

  21.   uint r,g;

  22.    for(r=s;r>0;r--)

  23.      for(g=110;g>0;g--);

  24. }

  25. void write_com(uchar com) // 写指令

  26. {

  27.    lcdrs=0;

  28.    P0=com;

  29.    delay(5);

  30.    lcden=1;

  31.    delay(5);

  32.    lcden=0;            

  33. }

  34. void write_data(uchar date) // 写数据

  35. {

  36.    lcdrs=1;

  37.    P0=date;

  38.    delay(5);

  39.    lcden=1;

  40.    delay(5);

  41.    lcden=0;            

  42. }

  43. void initlcd()//初始化

  44. {

  45.   lcdrw=0;

  46.   lcden=0;

  47. //write_com(0x01);//显示清屏

  48.   write_com(0x38);//显示模式设置

  49.   write_com(0x0c); //显示开,开游标,不闪烁

  50.   write_com(0x06); // 字符时整体不移动

  51. }

  52. ////////////LCD1602设置///////////////

  53. ///////////定时器的设置//////////////

  54. void CT_init()                            //定时计数器初始化

  55. {              TMOD=0x99;                   //GATE=1,T1、T0工作在方式1,定时方式

  56.               TH0=0;                                          //定时计数器初值清零

  57.               TL0=0;

  58.               TH1=0;

  59.               TL1=0;

  60.               TR0=1;                                          //TR0,TR1置位,此时定时计数器的启动有INT0,INT1引脚电平决定

  61.               TR1=1;

  62.               ET0=1;                                          //开中断

  63.               ET1=1;

  64. }

  65. void ITC0() interrupt 0   //外部中断0服务程序

  66. {

  67.               u=m;                                                          //读定时计数器0溢出次数

  68.               m=0;                                                          //溢出次数清零

  69.               x=TH0*256+TL0;                              //读定时计数器0当前值

  70.               TH0=0;                                                          //定时计数器0清零

  71.               TL0=0;

  72. }

  73. void TIME0() interrupt 1  //定时计数器0溢出中断

  74. {

  75.               m++;                                                          //溢出次数加1

  76. }

  77. void ITC1() interrupt 2   //外部中断1服务程序

  78. {

  79.               v=n;                                                          //读定时计数器1溢出次数

  80.               n=0;                                                          //溢出次数清零

  81.               y=TH1*256+TL1;                              //读定时计数器1当前值

  82.               TH1=0;                                                          //定时计数器1清零

  83.               TL1=0;            

  84. }

  85. void TIME1() interrupt 3  //定时计数器1溢出中断

  86. {

  87.               n++;                                                          //溢出次数加1

  88. }

  89. ////////////定时器的设置//////////////

  90. void main()

  91. {

  92.               initlcd();                                            //液晶显示初始化

  93.     CT_init();                                            //定时计数器初始化

  94.               EA=1;                                                          //开总中断

  95.               EX0=1;                                                          //允许外部中断

  96.               EX1=1;

  97.               IT0=1;                                                          //设置外部中断方式为下降沿触发

  98.               IT1=1;

  99.               P3=0xff;            

  100.               while(1)

  101. {                                                                                    

  102.                             t0=u*65536+x;                                                           //计算脉冲时间宽度

  103.                             f=1000000/(2*t0);                                             //计算频率

  104.                             c=f*100;                                                                         //计算结果逐位保存

  105.                             a[9]=c%10+48;

  106.                             a[8]=(c/10)%10+48;

  107.                             c=f;

  108.                             a[6]=c%10+48;

  109.                             a[5]=(c/10)%10+48;

  110.                             a[4]=(c/100)%10+48;

  111.                             a[3]=(c/1000)%10+48;

  112.                             a[2]=(c/10000)%10+48;

  113.                             write_com(0x80);

  114.                             for(i=0;i<=11;i++)

  115.                             {

  116.                                           write_data(a[i]);

  117.                                           delay(10);

  118.                             }

  119.                   t1=v*65536+y;                                                          //计算脉冲宽度

  120.                             p=(t1/(2*t0))*360;                                            //计算相位差

  121.                             d=p*100;                                                                        //将计算结果逐位保存

  122.                             b[7]=d%10+48;

  123.                             b[6]=(d/10)%10+48;

  124.                             d=p;

  125.                             b[4]=d%10+48;

  126.                             b[3]=(d/10)%10+48;

  127.                             b[2]=(d/100)%10+48;

  128.                             write_com(0x80+0X40);

  129.                             for(j=0;j<=8;j++)

  130.                             {            

  131.                                   write_data(b[j]);

  132.                                delay(10);                           

  133.                             }

  134.               }            

  135. }
复制代码


回复

使用道具 举报

ID:156933 发表于 2016-12-22 18:28 | 显示全部楼层
楼主很厉害啊
回复

使用道具 举报

ID:353623 发表于 2018-6-18 12:58 | 显示全部楼层
牛逼     
回复

使用道具 举报

ID:355329 发表于 2018-6-20 16:38 | 显示全部楼层
厉害啊。我准备弄一下子
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

小黑屋|51黑电子论坛 |51黑电子论坛6群 QQ 管理员QQ:125739409;技术交流QQ群281945664

Powered by 单片机教程网

快速回复 返回顶部 返回列表