基于51单片机的数字频率计(电路图+pcb+论文+仿真+源码)

于51单片机的数字频率计
设计的频率计范围能够达到1HZ-1MHZ(实际上51单片机达不到这个范围,不要在实验环境下进行),这个是课设来着,用Proteus仿真实现的,给有需要的同学参考一下

仿真原理图如下(proteus仿真工程文件可到本帖附件中下载).
 

 

本文提出设计数字频率计的方案,重点介绍以单片机AT89C51为控制核心,实现频率测量的数字频率设计。测频的基本原理是采用在低频段直接测频法,在低频段直接测频法的设计思路,硬件部分由单片机和数计显示电路组成;软件部分由信号频率测量模块和数据显示模块等模块实现。应用单片机的控制功能和数学运算能力,实现计数功能和频率的换算。设计的频率计范围能够达到1HZ~1MHZ,满足所要求的频率范围,测量精度较高。


目录
前  言
第一章  总体设计方案
1.1 总设计框图
1.2 硬件设计分析
1.2.1 电源的设计
(4):LCD1602的指令说明及时序
(5): LCD1602的RAM地址映射及标准字库表
第二章  软件设计与分析
2.1 软件设计的组成
2.2  各部分软件分析
2.2.1  定时器0中断子函数
2.2.2  定时器1中断子函数
2.2.3  主函数
2.3  总源程序
第三章  软件介绍
3.1 PROTEUS简介
3.2 PROTEL 99 SE简介
3.2.1 电路工程设计部分
3.2.2 电路仿真与PLD部分
3.3 Protel 99 SE的功能特性
3.4 Protel99SE快捷键大全
3.6仿真图
3.7原理图
第四章  减小误差措施及扩展方面
4.1减小误差措施
4.2扩展方面
(1)预处理电路部分
(2)增加电源部分
4.3 功能上的完善
4.3.1 增加键盘控制
4.3.2 实现自动量程转换
4.3.3 液晶显示器(LCD)进行数据的显示
总结
致谢词
参考文献

前  言
频率是电子技术领域的一个基本参数,同时也是一个非常重要的参数,因此,频率测量已成为电子测量领域最基本最重要的测量之一。 随着科学技术的不断发展提高,人们对科技产品的要求也相应的提高,数字化的电子产品越来越受到欢迎。频率计作为比较常用和实用的电子测量仪器,广泛应用于科研机构、学校、家庭等场合,因此它的重要性和普遍性勿庸质疑。数字频率计具有体积小、携带方便;功能完善、测量精度高等优点,因此在以后的时间里,必将有着更加广阔的发展空间和应用价值。比如:将数字频率计稍作改进,就可制成既可测频率,又能测周期、占空比、脉宽等功能的多用途数字测量仪器。将数字频率计和其他电子测量仪器结合起来,制成各种智能仪器仪表,应用于航空航天等科研场所,对各种频率参数进行计量;应用在高端电子产品上,对其中的频率参数进行测量;应用在机械器件上,对机器振动产生的噪声频率进行监控;等等。研究数字频率计的设计和开发,有助于频率计功能的不断改进、性价比的提高和实用性的加强。以前的频率计大多采用TTL数字电路设计而成,其电路复杂、耗电多、体积大、成本高。随后大规模专用IC(集成电路)出现,如ICM7216,ICM7226频率计专用IC,使得频率计开发设计变得简单,但由于价格较高,因此利用IC设计数字频率计的较少。现在,单片机技术发展非常迅速,采用单片机来实现数字频率计的开发设计,实现频率的测量,不但测量准确,精度高,而且误差也很小。我们将介绍一种简单、实用的基于单片机的数字频率计的设计和制作。

第一章  总体设计方案
以AT89C51单片机为核心,起着控制作用。系统包括LCD1602液晶显示电路、复位电路、时钟电路。设计思路分为四个模块:复位电路、晶振电路模块、AT89C51、LCD1602液晶显示电路。

1.1 总设计框图


图1-1-1 总设计框图

1.2 硬件设计分析1.2.1 电源的设计
(1):系统电源使用直流5伏。


(2):单片机最小系统

单片机选用型号为AT89C51。

AT89C51是一个低电压,高性能CMOS 8位单片机,片内含4k bytes的可反复擦写的Flash只读程序存储器和128bytes的随机存取数据存储器(RAM),器件采用ATMEL公司的高密度、非易失性存储技术生产,兼容标准MCS-51指令系统,内置功能强大的微型计算机的AT89C51提供了高性价比的解决方案。

如图1-2-3所示为AT89C51单片机基本构造,其基本性能介绍如下:


图1-2-3 AT89C51单片机
AT89C51本身内含40个引脚,32个外部双向输入/输出(I/O)端口,同时内含2个外中端口,3个16位可编程定时计数器,2个全双工串行通信口,AT89C51可以按照常规方法进行编程,但不可以在线编程。其将通用的微处理器和Flash存储器结合在一起,特别是可反复擦写的Flash存储器可有效地降低开发成本。

AT89C51的主要特性如下表所示:

兼容MCS—51指令系统
32个可编程I/O线
4k字节可编程闪烁存储器
可编程UARL通道
三个16位可编程定时/计数器中断
时钟频率0-24MHz
2个外部中断源,共8个中断源
256×8bit内部RAM
2个读写中断口线
可直接驱动LED
软件设置睡眠和唤醒功能
低功耗空闲和掉电模式
表1-2-1 AT89C51主要功能描述
AT89C51为40脚双列直插封装的8位通用微处理器,采用工业标准的C51内核,在内部功能及管脚排布上与通用的8xc51相同,其主要用于会聚调整时的功能控制。功能包括对会聚主IC内部寄存器、数据RAM及外部接口等功能部件的初始化,会聚调整控制,会聚测试图控制,红外遥控信号IR的接收解码及与主板CPU通信等。主要管脚有:XTAL1(19脚)和XTAL2(18脚)为振荡器输入输出端口,外接12MHz 晶振。RST/Vpd(9脚)为复位输入端口,外接电阻电容组成的复位电路。VCC(40脚)和VSS(20脚)为供电端口,分别接+5V电源的正负端。P0~P3 为可编程通用I/O脚,其功能用途由软件定义,在本设计中,P0端口(32~39脚)被定义为N1功能控制端口,分别与N1的相应功能管脚相连接,13脚定义为IR输入端,10脚和11脚定义为I2C总线控制端口,分别连接N1的SDAS(18脚)和SCLS(19脚)端口,12脚、27脚及28脚定义为握手信号功能端口,连接主板CPU的相应功能端,用于当前制式的检测及会聚调整状态进入的控制功能。

P0口:P0口是一组8位漏极开路型双向I/O 口,也即地址/数据总线复用口。作为输出口用时,每位能吸收电流的方式驱动8个TTL逻辑门电路,对端口P0写“1”时,可作为高阻抗输入端用。在访问外部数据存储器或程序存储器时,这组口线分时转换地址(低8位)和数据总线复用,在访问期间激活内部上拉电阻。在Flash 编程时,P0口接收指令字节,而在程序校验时,输出指令字节,校验时,要求外接上拉电阻。

P1口:P1是一个带内部上拉电阻的8位双向I/O口,P1的输出缓冲级可驱动(吸收或输出电流)4个TTL逻辑门电路。对端口写“1”,通过内部的上拉电阻把端口拉到高电平,此时可作输入口。作输入口使用时,因为内部存在上拉电阻,某个引脚被外部信号拉低时会输出一个电流(IIL)。与AT89C51不同之处是,P1.0和P1.1还可分别作为定时/计数器2 的外部计数输入(P1.0/T2)和输入(P1.1/T2EX)。Flash编程和程序校验期间,P1接收低8位地址。

P2口:P2是一个带有内部上拉电阻的8 位双向I/O口,P2的输出缓冲级可驱动(吸收或输出电流)4个TTL逻辑门电路。对端口P2写“1”,通过内部的上拉电阻把端口拉到高电平,此时可作输入口,作输入口使用时,因为内部存在上拉电阻,某个引脚被外部信号拉低时会输出一个电流(IIL)。在访问外部程序存储器或16位地址的外部数据存储器(例如执行MOVX @DPTR指令)时,P2口送出高8位地址数据。在访问8位地址的外部数据存储器(如执行MOVX @RI指令)时,P2口输出P2锁存器的内容。Flash编程或校验时,P2亦接收高位地址和一些控制信号。

P3口:P3口是一组带有内部上拉电阻的8位双向I/O口。P3口输出缓冲级可驱动(吸收或输出电流)4个TTL逻辑门电路。对P3口写入“1”时,它们被内部上拉电阻拉高并可作为输入端口。此时,被外部拉低的P3口将用上拉电阻输出电流(IIL)。P3口除了作为一般的I/O口线外,更重要的用途是它的第二功能P3口还接收一些用于Flash 闪速存储器编程和程序校验的控制信号。

RST:复位输入。当振荡器工作时,RST引脚出现两个机器周期以上高电平将使单片机复位。

ALE/PROG:当访问外部程序存储器或数据存储器时,ALE(地址锁存允许)输出脉冲用于锁存地址的低8位字节。一般情况下,ALE仍以时钟振荡频率的1/6输出固定的脉冲信号,因此它可对外输出时钟或用于定时目的。要注意的是:每当访问外部数据存储器时将跳过一个AL脉冲。对Flash存储器编程期间,该引脚还用于输入编程脉冲(PROG)。如有必要,可通过对特殊功能寄存器(SFR)区中的8EH单元的D0位置位,可禁止ALE操作。该位置位后,只有一条 MOVX 和MOVC指令才能将ALE激活。此外,该引脚会被微弱拉高,单片机执行外部程序时,应设置ALE禁止位无效。

PSEN:程序储存允许(PSEN)输出是外部程序存储器的读选通信号,当AT89C51由外部程序存储器取指令(或数据)时,每个机器周期两次PSEN有效,即输出两个脉冲。在此期间,当访问外部数据存储器,将跳过两次PSEN信号。

EA/VPP:外部访问允许。欲使CPU仅访问外部程序存储器(地址为0000H—FFFFH),EA端必须保持低电平(接地)。需注意的是:如果加密位LB1被编程,复位时内部会锁存EA端状态。如EA端为高电平(接Vcc端),CPU则执行内部程序存储器中的指令。Flash存储器编程时,该引脚加上+12V的编程允许电源Vpp,当然这必须是该器件是使用12V编程电压Vpp。

XTAL1:振荡器反相放大器的及内部时钟发生器的输入端。

XTAL2:振荡器反相放大器的输出端。

单片机最小原理图如图1-2-4所示。


图1-2-4 单片机最小系统
单片机最小系统说明:
时钟信号的产生:在MCS-51芯片内部有一个高增益反相放大器,其输入端为芯片引脚XTAL1,其输出端为引脚XTAL2。而在芯片的外部,XTAL1和XTAL2之间跨接晶体振荡器和微调电容,从而构成一个稳定的自激振荡器,这就是单片机的时钟振荡电路。

时钟电路产生的振荡脉冲经过触发器进行二分频之后,才成为单片机的时钟脉冲信号。

一般地,电容C1和C2取30pF左右,晶体的振荡频率范围是1.2-12MHz。如果晶体振荡频率高,则系统的时钟频率也高,单片机的运行速度也就快。

单片机复位使CPU和系统中的其他功能部件都处在一个确定的初始状态下,并从这个状态开始工作。单片机复位条件:必须使9脚加上持续两个机器周期(即24个振荡周期)的高电平。

(3):显示系统
LCD1602分为带背光和不带背光两种,基控制器大部分为HD44780,带背光的比不带背光的厚,是否带背光在应用中并无差别,两者尺寸差别如下图1-2-5所示:

LCD1602的主要技术参数:

1、显示容量:16×2个字符

2、芯片工作电压:4.5—5.5V

3、工作电流:2.0mA(5.0V)

4、模块最佳工作电压:5.0V

5、字符尺寸:2.95×4.35(W×H)mm

引脚功能说明

LCD1602采用标准的14脚(无背光)或16脚(带背光)接口,各引脚接口说明如图1-2-6所示:


编号
符号
引脚说明
编号
符号
引脚说明
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
背光源负极


图1-2-1:引脚接口说明表

第1脚:VSS为地电源。

第2脚:VDD接5V正电源。

第3脚:VL为液晶显示器对比度调整端,接正电源时对比度最弱,接地时对比度最高,对比度过高时会产生“鬼影”,使用时可以通过一个10K的电位器调整对比度。

第4脚:RS为寄存器选择,高电平时选择数据寄存器、低电平时选择指令寄存器。

第5脚:R/W为读写信号线,高电平时进行读操作,低电平时进行写操作。当RS和R/W共同为低电平时可以写入指令或者显示地址,当RS为低电平R/W为高电平时可以读忙信号,当RS为高电平R/W为低电平时可以写入数据。

第6脚:E端为使能端,当E端由高电平跳变成低电平时,液晶模块执行命令。

第7~14脚:D0~D7为8位双向数据线。

第15脚:背光源正极。

第16脚:背光源负极。

(4):LCD1602的指令说明及时序
1602液晶模块内部的控制器共有11条控制指令,如图1-2-7所示:

序号
指令
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
要写的数据内容
11
从CGRAM或DDRAM读数
1
1
读出的数据内容


1602液晶模块的读写操作、屏幕和光标的操作都是通过指令编程来实现的。(说明: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:写数据。

指令11:读数据。

(5): LCD1602的RAM地址映射及标准字库表
液晶显示模块是一个慢显示器件,所以在执行每条指令之前一定要确认模块的忙标志为低电平,表示不忙,否则此指令失效。要显示字符时要先输入显示字符地址,也就是告诉模块在哪里显示字符,图2-2-6是1602的内部显示地址。

例如第二行第一个字符的地址是40H,那么是否直接写入40H就可以将光标定位在第二行第一个字符的位置呢?这样不行,因为写入显示地址时要求最高位D7恒定为高电平1所以实际写入的数据应该是01000000B(40H)+10000000B(80H)=11000000B(C0H)。

在对液晶模块的初始化中要先设置其显示模式,在液晶模块显示字符时光标是自动右移的,无需人工干预。每次输入指令前都要判断液晶模块是否处于忙的状态。

1602液晶模块内部的字符发生存储器(CGROM)已经存储了160个不同的点阵字符图形,这些字符有:阿拉伯数字、英文字母的大小写、常用的符号、和日文假名等,每一个字符都有一个固定的代码,比如大写的英文字母“A”的代码是01000001B(41H),显示时模块把地址41H中的点阵字符图形显示出来,我们就能看到字母“A”。

图1-2-9 液晶显示电路

3.6仿真图


3.7原理图


3.8元件清单


第四章  减小误差措施及扩展方面4.1减小误差措施
(1)选用频率较高和稳定性好晶振。如选24KHZ的晶振可使测量范围扩大,稳定性好的晶振可以减小误差。

(2)测量频率低的信号时,可适当调整程序,延长门限时间,减少原理上±1的相对误差。

(3)测量频率高的信号时,可先对信号进行分频,在进行测量。

4.2扩展方面
(1)预处理电路部分

在实际工作中,如若两级NPN放大管仍不能使放大作用明显,则可以再级联一个NPN放大管;或者采用放大能力更强的三极管或CMOS管代替。后一种思路虽然在价格上有所增加,但却减少了电路的复杂程度,并且在电路板一旦出现问题时,能尽最大可能的减少元器件的更换和连接线路的修改,非常方便和实用。

(2)增加电源部分            

在上面数字频率计的设计工程中,使用的是外部干电池电源对单片机和其他电路供电,操作起来很方便,但有一个缺点是外部提供的电源准确度不是很高。比如,单片机需要提供5V的标准电压,我们使用的干电池,由于使用时间过久或型号不同而使得提供的电压达不到5V或高于5V,这样使得电路不能在正常的状态下工作或损坏元器件。因此在原理图中,我们可以加入电源部分,采用元件7805或7809和整流电路对外来电压进行整流、限压,提供标准的5V电压给电路,这样就增加了硬件电路的稳定性和测试的准确性。

4.3 功能上的完善4.3.1 增加键盘控制
通过按键实现数字频率计的测频率,周期,占空比,脉宽等各项功能。按不同的键起到不同的作用,也就是完成不同的功能。还可以根据按键数的多少来选择不同的键盘。所以我们可以从实际操作中知道键盘的扩展是非常方便的。

4.3.2 实现自动量程转换
在测量频率时,软件编程也可以实现频率测量量程的自动转换。频率计每个工作循环开始时使用计数方法实现频率测量,测量完后判断测量结果是否具有2位有效数字,如果成立,将结果送去显示,本工作循环结束;否则将计数闸门宽度依次扩大10倍,继续进行测量判断,直到计数闸门宽度达到1s,这时对应的频率测量范围为100Hz~999Hz。如果测量结果仍不具有2位有效数字,频率计则使用定时方法实现频率测量。

4.3.3 液晶显示器(LCD)进行数据的显示
LED显示管只能显示0~9和一些简单的英文字母,频率计的功能就受到极大的限制,而LCD显示管能够解决LED的不足,增强显示功能。LCD具有体积小、低耗电量、无辐射危险,平面直角显示以及影像稳定不闪烁等优势,因此广泛应用于各种仪表设备中去。LCD显示器主要有字符型和点阵型两种。


总结
系统的分析与设计过程也是对学习的总结过程,更是进一步学习和探索的过程。在这过程中,我对利用可编程控制器进行控制系统的设计与开发有了深刻的的认识,对机械手的工作原理有了进一步的掌握,对控制系统的分析与设计有了切身的认识和体会,并在学习和实践过程中增长了知识,丰富了经验。控制系统的开发设计是一项复杂的系统工程,必须严格按照系统分析、系统设计、系统实施、系统运行与调试的过程来进行。系统的分析与设计是一项很辛苦的工作,同时也是一个充满乐趣的过程。在设计过程中,要边学习,边实践,遇到新的问题就不断探索和努力,即可使问题得到解决。

同时,在本次设计中,也深刻体会到理论和实践相集合的重要性。虽然之前收集了大量的资料但在实际应用中却有很大差异,出现了许多意想不到的问题。但经过长时间的摸索最终还是设计出达到要求的系统。由于时间紧迫,有些设计工作还有待完善,在以后的工作中我会继续努力,不断提高自己的技术水平,以适应未来的激烈竞争形势。


致谢词
毕业,意味着一个人一个阶段学习生涯的结束。在大学里,毕业论文是宣告这一事实的标准。从大一到现在三年的学习三年的磨练,在此刻沉淀成一篇毕业论文。
通过这次毕业设计,使我得到了一次用专业知识、专业技能分析和解决问题的全面系统的锻炼。我学到了很多书本上学不到的实践知识,尤其对电子硬件、电路设计有了更深刻的理解,了解了设计一个产品从方案的选择到最终产品的一系列的设计阶段,了解了产品的调试技术。使我真正体会到理论和实践相结合的重要性。
在此有无数感谢。
首先,感谢我的父母。是他们教会我做人做事的道理,他们的谆谆教导是.我前进的强大动力和坚实后盾。
感谢大学三年里教育过我的老师, 那些曾经的岁月,曾经的年华,我们一起走过的路。
感谢我的同学。无论是教室里的如切如磋,餐桌旁的高谈阔论。还是寝室里的欢声笑语,都留下了我们最美好的回忆。这是我最宝贵的财富之一。
当然,这里更要感谢的是xxx老师,他是我这次毕业设计的指导老师。衷心的感谢他在这段时间对我的帮助和对我的教导。任老师的言传身教我将谨记遵循,他渊博的学识和严谨的治学态度将是我收益终生。
最后感谢各位评委和答辩老师在百忙之中抽出时间来亲自检阅我的毕业设计。
2.2  各部分软件分析
2.2.1  定时器0中断子函数

void t0() interrupt 1 using 1
{

}
2.2.2  定时器1中断子函数

void t1() interrupt 3 using 3//定时器T1中断服务程序
{               
              if(num==3999)
              {
                            GATE=0;
                            TR0=0;
                            TR1=0;
                            aaa=TH0*256+TL0;
                            bbb=P1;
                            d=c/100.0;
                            c=0;
                            e=f;
                            f=1;
                            CLR=1;
                            CLR=0;
                            TH0=0x00;            
                            TL0=0x00;
                            TH1=0x06;
                            TL1=0x06;
                            num=0;
                            GATE=1;
                            TR0=1;
                            TR1=1;
              }
              else
                            num++;
}
2.2.3  主函数

void main()//主函数
{            
              unsigned long a=0;
              bit b=0;
              uchar tab[10];
              uint temp=0;
              LCD_init();
              init();
              LCD_sfj1(0,0);
              LCD_print("Welcome to use ");
              LCD_sfj1(0,1);
              LCD_print("Please Wating...");
              delay3();
              LCD_write(0,0x01);
              while(1)
              {
                            if(K1==0)
                            {            
                                          delay2(10);
                                          if(K1==0)            
                                          {
                                                        while(K1==0);
                                                        b=~b;
                                                        LCD_write(0,0x01);
                                          }
                            }
                            temp=fenjie(0);
                            if(temp>c)
                            c=temp;
                            if(temp>c>>3&&temp<c>>1)
                                          f=0;
                            if(b==0)
                            {
                                          a=(aaa*256)+bbb;
                                          if(a==0)
                                          {
                                                        LCD_sfj1(0,0);
                                                        LCD_print("F= 0000000000 Hz");            
                                                        LCD_sfj1(0,1);
                                                        LCD_print("F= 0000000000 Hz");              
                                          }
                                          else
                                          {                           
                                                        LCD_sfj1(0,0);
                                                        LCD_print("F=            Hz");
                                                        sprintf(tab,"%ld",a);
                                                        LCD_sfj1(2,0);LCD_print(tab);
                                                        LCD_sfj1(0,1);
                                                        LCD_print("P=            ms");
                                                        sprintf(tab,"%0.6f",1000.0/a);
                                                        LCD_sfj1(2,1);
                                                        LCD_print(tab);            
                                          }
                            }
                            else
                            {  
                                          sprintf(tab,"%bd",e);
                                          LCD_sfj1(0,0);
                                          LCD_print(tab);
                                          sprintf(tab,"Upp=%0.3fV",d);
                                          LCD_sfj1(0,1);
                                          LCD_print(tab);
                            }
              }
}
2.3  总源程序

#include<reg51.h>
#include<stdio.h>
#include<intrins.h>
typedef unsigned char uchar;
typedef unsigned int  uint;
sbit RS=P2^5;
sbit RW=P2^6;
sbit E=P2^7;
sbit CLK=P2^0;
sbit DO=P2^1;
sbit DI=P2^1;
sbit CS=P2^2;
sbit CLR=P3^0;
sbit GATE=P3^1;
sbit K1=P3^7;
uint  num=0;
uint  c=0;
float d=0;
uchar e=1,f=1;
unsigned long int aaa=0,bbb=0;
uchar LCD_wait()//LCD1602内部等待函数
{
              RS=0;
              RW=1;            
              _nop_();
              E=1;
              _nop_();
              E=0;
              return P0;                           
}
void LCD_write(bit aa,uchar bb)//向LCD写入命令或数据
{
              E=0;
              RS=aa;
              RW=0;                           
              _nop_();
              P0=bb;            
              _nop_();//注意顺序
              E=1;                           
              _nop_();//注意顺序
              E=0;                           
              _nop_();
              LCD_wait();//LCD1602内部等待函数            
}
void LCD_display(uchar temp)
{
              LCD_write(0,0x08|temp);            
}
void LCD_input(uchar cc)
{
              LCD_write(0,0x04|cc);
}
void LCD_init()//初始化LCD
{
              E=0;
              LCD_write(0,0x38);//8位数据端口,2行显示,5*7点阵
              LCD_write(0,0x38);
              LCD_display(0x04|0x00);//开启显示, 无光标
              LCD_write(0,0x01);//清屏
              LCD_input(0x02|0x00);//AC递增,画面不动
}
void LCD_sfj1(uchar x,uchar y)
{
              if(y==0)
                            LCD_write(0,0x80|x);
              if(y==1)
                            LCD_write(0,0x80|(x-0x40));
}
void LCD_print(uchar *p)
{
              while(*p!='\0')
              {
                            LCD_write(1,*p);
                            p++;
              }
}
void delay1(uchar x)//ms延时子函数
{                              
    uchar i;
    for(i=0;i<x;i++); //延时,脉冲一位持续的时间
}
uchar start(bit temp) //把模拟电压值转换成8位二进制数并返回,dat为通道选择。
{              
              uchar i,aa=0;
    CS=0;
    DO=0;//片选,DO为高阻态
    delay1(10);
    CLK=0;
    delay1(2);
    DI=1;            
    CLK=1;            
    delay1(2);//第一个脉冲,起始位
    CLK=0;                                                                       
    delay1(2);                                                                       
    DI=1;                                                                       
    CLK=1;                                                                       
    delay1(2);//第二个脉冲,DI=1表示双通道单极性输入            
    CLK=0;                                                                                                                                          
    delay1(2);                                                                                                                                          
    DI=temp;              /*******************************/                                                                                                                                                         
    CLK=1;
    delay1(2);//第三个脉冲,DI=1表示选择通道1(CH2)               
    DI=0;                                                                                                                                             
    DO=1;//DI转为高阻态,DO脱离高阻态为输出数据作准备
    CLK=1;                                                                                                                                                                                                                                                                                                                     
    delay1(2);                                                                                                                                
    CLK=0;                                                                                                                                
    delay1(2);//经实验,这里加一个脉冲AD便能正确读出数据,
        //不加的话读出的数据少一位(最低位d0读不出)                             
              for(i=0;i<8;i++)                                                                                                                              
    {
                  CLK=1;
                     delay1(2);
                     CLK=0;
                     delay1(2);
                     aa=(aa<<1)|DO;//在每个脉冲的下降沿DO输出一位数据,最终ch为8位二进制数
              }
    CS=1;//取消片选,一个转换周期结束
    return(aa);//把转换结果返回
}
uint fenjie(bit cc)
{
              uchar dd;
              uint  ee;
              dd=start(cc);
              ee=(uint)dd*100/51; //51是由5/255的倒数得来的,5是5V,255是8位AD。
              return(ee);
}            
void delay2(uint z)//按键消抖
{
              uint x;
              uchar y;
              for(x=0;x<z;x++)
                            for(y=0;y<110;y++);
}
void delay3()//1s延时子函数                 
{
              uchar h,i,j,k;
              for(h=5;h>0;h--)
                            for(i=4;i>0;i--)
                                          for(j=116;j>0;j--)
                                                        for(k=214;k>0;k--);
}
//定时计数初始化
void init()                  
{
              TMOD=0x25;                                                        // T0计数,T1定时
              TH0=0x00;            
              TL0=0x00;
              TH1=0x06;
              TL1=0x06;
              CLR=1;
              CLR=0;
              GATE=0;
              GATE=1;
              ET0=1;
              ET1=1;
              EA=1;
              TR0=1;
              TR1=1;
}
void main()//主函数
{            
              unsigned long a=0;
              bit b=0;
              uchar tab[10];
              uint temp=0;
              LCD_init();
              init();
              LCD_sfj1(0,0);
              LCD_print("Welcome to use ");
              LCD_sfj1(0,1);
              LCD_print("Please Wating...");
              delay3();
              LCD_write(0,0x01);
              while(1)
              {
                            if(K1==0)
                            {            
                                          delay2(10);
                                          if(K1==0)            
                                          {
                                                        while(K1==0);
                                                        b=~b;
                                                        LCD_write(0,0x01);
                                          }
                            }
                            temp=fenjie(0);
                            if(temp>c)
                            c=temp;
                            if(temp>c>>3&&temp<c>>1)
                                          f=0;
                            if(b==0)
                            {
                                          a=(aaa*256)+bbb;
                                          if(a==0)
                                          {
                                                        LCD_sfj1(0,0);
                                                        LCD_print("F= 0000000000 Hz");            
                                                        LCD_sfj1(0,1);
                                                        LCD_print("F= 0000000000 Hz");              
                                          }
                                          else
                                          {                           
                                                        LCD_sfj1(0,0);
                                                        LCD_print("F=            Hz");
                                                        sprintf(tab,"%ld",a);
                                                        LCD_sfj1(2,0);LCD_print(tab);
                                                        LCD_sfj1(0,1);
                                                        LCD_print("P=            ms");
                                                        sprintf(tab,"%0.6f",1000.0/a);
                                                        LCD_sfj1(2,1);
                                                        LCD_print(tab);            
                                          }
                            }
                            else
                            {  
                                          sprintf(tab,"%bd",e);
                                          LCD_sfj1(0,0);
                                          LCD_print(tab);
                                          sprintf(tab,"Upp=%0.3fV",d);
                                          LCD_sfj1(0,1);
                                          LCD_print(tab);
                            }
              }
}
void t0() interrupt 1 using 1
{

}
void t1() interrupt 3 using 3//定时器T1中断服务程序
{               
              if(num==3999)
              {
                            GATE=0;
                            TR0=0;
                            TR1=0;
                            aaa=TH0*256+TL0;
                            bbb=P1;
                            d=c/100.0;
                            c=0;
                            e=f;
                            f=1;
                            CLR=1;
                            CLR=0;
                            TH0=0x00;            
                            TL0=0x00;
                            TH1=0x06;
                            TL1=0x06;
                            num=0;
                            GATE=1;
                            TR0=1;
                            TR1=1;
              }
              else
                            num++;
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/642985.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

方言和大语言模型

方言多样性及其对语言模型的影响 语言的演变是不可避免的&#xff0c;反映并推动了重大的社会变革和传统。语言接触往往会推动我们说话方式的创新&#xff0c;在美国全球文化的影响下&#xff0c;一种新的叙事正在其语言织锦中展开。 例如&#xff0c;在佛罗里达州南部&#…

使用FFmpeg推流实现在B站24小时点歌直播

使用FFmpeg推流实现在B站24小时点歌直播 本文首发于个人博客 安装FFmpeg centos7 https://www.myfreax.com/how-to-install-ffmpeg-on-centos-7/ https://linuxize.com/post/how-to-install-ffmpeg-on-centos-7/ 使用FFmpeg在B站直播 https://zhuanlan.zhihu.com/p/2395…

内外网文件传输安全可控的方式有哪些?这几款软件值得参考

在信息化时代&#xff0c;随着企业对网络安全和数据保护需求的日益增强&#xff0c;内外网隔离已成为一种常见的网络安全策略。内外网隔离旨在防止未经授权的访问和数据泄露&#xff0c;确保企业网络的安全稳定。然而&#xff0c;在实施内外网隔离的同时&#xff0c;如何实现文…

记录使用 Vue3 过程中的一些技术点

1、自定义组件&#xff0c;并使用 v-model 进行数据双向绑定。 简述&#xff1a; 自定义组件使用 v-model 进行传参时&#xff0c;遵循 Vue 3 的 v-model 机制。在 Vue 3 中&#xff0c;v-model 默认使用了 modelValue 作为 prop 名称&#xff0c;以及 update:modelValue 作为…

springboot错误

错误总结 1、使用IDEA 的 initialalzer显示2、IDEA 新建文件 没有 java class3、java: 错误: 不支持发行版本 22解决方法4、IDEA-SpringBoot项目yml配置文件不自动提示解决办法 1、使用IDEA 的 initialalzer显示 IDEA创建SpringBoot项目时出现&#xff1a;Initialization fail…

【C++】类与对象——多态详解

目录 一、多态的定义 二、重载、覆盖(重写)、隐藏(重定义)的对比 三、析构函数重写 四、C11 override 和 final 1. final 2. override 五、抽象类 六、多态的原理 一、多态的定义 多态是在不同继承关系的类对象&#xff0c;去调用同一函数&#xff0c;产生了不同的行为…

MySQL的数据库和表

查看数据库 命令行的方式&#xff1a; cd /mysql/bin mysql.exe -uroot -p IP&#xff08;不是连接自己&#xff09; 端口&#xff08;不是3306&#xff09; show databases; 直接使用图形化界面点击&#xff1a; 查看库里的表 使用命令行查看&#xff1a; 进入mysql数据库 u…

基于高通公司AI Hub Models的On-Device AI学习:Introduction to On-Device AI

Introduction to On-Device AI 本文是学习 https://www.deeplearning.ai/short-courses/introduction-to-on-device-ai/这门课的学习笔记。 What you’ll learn in this course As AI moves beyond the cloud, on-device inference is rapidly expanding to smartphones, IoT…

从 0 实现一个文件搜索工具 (Java 项目)

背景 各文件系统下, 都有提供文件查找的功能, 但是一般而言搜索速度很慢 本项目仿照 everything 工具, 实现本地文件的快速搜索 实现功能 选择指定本地目录, 根据输入的信息, 进行搜索, 显示指定目录下的匹配文件信息文件夹包含中文时, 支持汉语拼音搜索 (全拼 / 首字母匹配…

java在类的定义中创建自己的对象?

当在main方法中新建自身所在类的对象&#xff0c;并调用main方法时&#xff0c;会不断循环调用main方法&#xff0c;直到栈溢出 package com.keywordStudy;public class mainTest {static int value 33;public static void main(String[] args) throws Exception{String[] sn…

营销短信XML接口对接发送示例

在现代社会中&#xff0c;通信技术日新月异&#xff0c;其中&#xff0c;短信作为一种快速、简便的通信方式&#xff0c;仍然在日常生活中占据着重要的地位。为了满足各种应用场景的需求&#xff0c;短信接口应运而生&#xff0c;成为了实现高能有效通信的关键。 短信接口是一种…

从机械尘埃到智能星河:探索从工业心脏到AI大脑的世纪跨越(一点个人感想)...

全文预计1400字左右&#xff0c;预计阅读需要8分钟。 近期&#xff0c;人工智能领域呈现出前所未有的活跃景象&#xff0c;各类创新成果如雨后春笋般涌现&#xff0c;不仅推动了科技的边界&#xff0c;也为全球经济注入了新的活力。 这不&#xff0c;最近报道16家国内外企业在A…

【铨顺宏RFID技术闪耀登场】广交会与您共绘智慧新篇章!

激动人心的时刻即将来临&#xff01;广交会作为中国最重要的综合性国际贸易盛会&#xff0c;每年都吸引着来自世界各地的参展商和观众。今年&#xff0c;我们铨顺宏公司也荣幸地参与其中&#xff0c;并将在广交会上展示我们最新的RFID技术产品。 &#x1f4cd;地点&#xff1a;…

Android Studio添加依赖 新版 和 旧版 的添加方式(Gradle添加依赖)(Java)

旧版的&#xff08;在线添加&#xff09; 1找 文件 在项目的build.gradle文件中添加依赖(在下面的节点中添加库 格式 ’ 组 &#xff1a;名字 &#xff1a; 版本号 ‘ ) dependencies {implementation com.example:library:1.0.0 }implementation 组:名字:版本…

网段与广播域

ip地址与子网掩码做与运算得到网络号&#xff0c;得到的网络号相同就是同一个网段&#xff0c;否则不是&#xff0c;跟他们在什么位置没有任何关系 这里面pc3和前两个pc虽然不在同一个网段&#xff0c;但是pc1发广播包的时候&#xff0c;pc3也能收到&#xff0c;因为路由器的所…

相关服务器介绍

服务器是一种高性能的计算机&#xff0c;它被设计用来为其他计算机或终端设备提供服务&#xff0c;如数据处理、文件存储、网络通信等。服务器通常具有强大的计算能力、大容量的存储空间和高效的网络连接能力。 常见的服务器种类及其特点 文件服务器 文件服务器主要负责中央存储…

[OpenGL] opengl切线空间

目录 一 引入 二 TBN矩阵 三 代码实现 3.1手工计算切线和副切线 3.2 像素着色器 3.3 切线空间的两种使用方法 3.4 渲染效果 四 复杂的物体 本章节源码点击此处 继上篇法线贴图 来熟悉切线空间是再好不过的。对于法线贴图来说,我们知道它就是一个2D的颜色纹理,根据rgb…

qmt量化教程4----订阅全推数据

文章链接 qmt量化教程4----订阅全推数据 (qq.com) 上次写了订阅单股数据的教程 量化教程3---miniqmt当作第三方库设置&#xff0c;提供源代码 全推就主动推送&#xff0c;当行情有变化就会触发回调函数&#xff0c;推送实时数据&#xff0c;可以理解为数据驱动类型&#xff0…

并发编程笔记7--并发编程基础

1、线程简介 1.1、什么是线程 现代操作系统中运行一个程序&#xff0c;会为他创建一个进程。而每一个进程中又可以创建许多个线程。现代操作系统中线程是最小的调度单元。 两者关系&#xff1a;一个线程只属于一个进程&#xff0c;而一个进程可以拥有多个线程。线程是一个轻量…

测试基础05:软件测试的分类

课程大纲 1、两种架构&#xff08;Architecture&#xff09; 1.1、B/S&#xff08;Browser/Server&#xff09; 浏览器服务器架构&#xff08;大体3步&#xff09;&#xff1a;用户通过浏览器向服务器发出请求&#xff0c;服务器处理请求&#xff0c;将结果通过网络返回到用户…