|
第一章、 总述
本智能小车采用80C51单片机为控制核心,利用超声波传感器检测道路上的障碍,控制电动小汽车的自动避障,快慢速行驶,以及自动停车,并可以自动记录时间、里程和速度,自动寻迹和寻光功能。整个系统的电路结构简单,可靠性能高。本文着重介绍了该系统的硬件设计方法及测试结果分析。
采用的技术主要有:
(1)通过编程来控制小车的速度;
(2)传感器的有效应用;
(3)新型显示芯片的采用.
具体实现:在现有玩具电动车的基础上,加装光电、红外线、超声波传感器及金属探测器,实现对电动车的速度、位置、运行状况的实时测量,并将测量数据传送至单片机进行处理,然后由单片机根据所检测的各种数据实现对电动车的智能控制。这种方案能实现对电动车的运动状态进行实时控制,控制灵活、可靠,精度高,可满足对系统的各项要求。本设计采用MCS-51系列中的80C51单片机。以80C51为控制核心,利用超声波传感器检测道路上的障碍,控制电动小汽车的自动避障,快慢速行驶,以及自动停车,并可以自动记录时间、里程和速度,自动寻迹和寻光功能。80C51引脚如下所示:
一 、直流调速系统 方案一:串电阻调速系统。 方案二:静止可控整流器。简称V-M系统。
方案三:脉宽调速系统。
- 旋转变流系统由交流发电机拖动直流电动机实现变流,由发电机给需要调速的直流电动机供电,调节发电机的励磁电流即可改变其输出电压,从而调节电动机的转速。改变励磁电流的方向则输出电压的极性和电动机的转向都随着改 变,所以G-M系统的可逆运行是很容易实现的。该系统需要旋转变流机组,至少包含两台与调速电动机容量相当的旋转电机,还要一台励磁发电机,设备多、体积大、费用高、效率低、维护不方便且技术落后,因此搁置不用。
- V-M系统是当今直流调速系统的主要形式。它可以是单相、三相或更多相数,半波、全波、半控、全控等类型,可实现平滑调速。V-M系统的缺点是晶闸管的单向导电性,它不允许电流反向,给系统的可逆运行造成困难。它的另一个缺点是运行条件要求高,维护运行麻烦。最后,当系统处于低速运行时,系统的功率因数很低,并产生较大的谐波电流危害附近的用电设备。
- 采用晶闸管的直流斩波器基本原理与整流电路不同的是,在这里晶闸管不受相位控制,而是工作在开关状态。当晶闸管被触发导通时,电源电压加到电动机上,当晶闸管关断时,直流电源与电动机断开,电动机经二极管续流,两端电压接近于零。脉冲宽度调制(Pulse Width Modulation),简称PWM。脉冲周期不变,只改变晶闸管的导通时间,即通过改变脉冲宽度来进行直流调速。
与V-M系统相比,PWM调速系统有下列优点:
(1)由于PWM调速系统的开关频率较高,仅靠电枢电感的滤波作用就可以获得脉动很小的直流电流,电枢电流容易连续,系统的低速运行平稳,调速范围较宽,可达1:10000左右。由于电流波形比V-M系统好,在相同的平均电流下,电动机的损耗和发热都比较小。
(2)同样由于开关频率高,若与快速响应的电机相配合,系统可以获得很宽的频带,因此快速响应性能好,动态抗扰能力强。
(3)由于电力电子器件只工作在开关状态,主电路损耗较小,装置效率较高。
根据以上综合比较,以及本设计中受控电机的容量和直流电机调速的发展方向,本设计采用了H型单极型可逆PWM变换器进行调速。脉宽调速系统的主电路采用脉宽调制式变换器,简称PWM变换器。脉宽调速也可通过单片机控制继电器的闭合来实现,但是驱动能力有限。为顺利实现电动小汽车的前行与倒车,本设计采用了可逆PWM变换器。可逆PWM变换器主电路的结构式有H型、T型等类型。在设计中采用了常用的双极式H型变换器,它是由4个三极电力晶体管和4个续流二极管组成的桥式电路。
二 、检测系统 检测系统主要实现光电检测,即利用各种传感器对电动车的避障、位置、行车状态进行测量。
1.行车起始、终点及光线检测:
本系统采用反射式红外线光电传感器用于检测路面的起始、终点(2cm宽的黑线),玩具车底盘上沿黑线放置一套,以适应起始的记数开始和终点的停车的需要。利用超声波传感器检测障碍。光线跟踪,采用光敏三极管接收灯泡发出的光线,当感受到光线照射时,其c-e间的阻值下降,检测电路输出高电平,经LM393电压比较器和74LS14施密特触发器整形后送单片机控制。
本系统共设计两个光电三极管,分别放置在电动车车头的左、右两个方向,用来控制电动车的行走方向,当左侧光电管受到光照时,单片机控制转向电机向左转;当右侧光电管受到光照时,单片机控制转向电机向右转;当左、右两侧光电管都受到光照时,单片机控制直行。见图2.1 电动车的方向检测电路(a)。
行车方向检测电路(见图2.2 电动车的方向检测电路(b))采用反射接收原理配置了一对红外线发射、接收传感器。该电路包括一个红外发光二极管、一个红外光敏三极管及其上拉电阻。红外发光二极管发射一定强度的红外线照射物体,红外光敏三极管在接收到反射回来的红外线后导通,发出一个电平跳变信号。
此套红外光电传感器固定在底盘前沿,贴近地面。正常行驶时,发射管发射红外光照射地面,光线经白纸反射后被接收管接收,输出高电平信号;电动车经过黑线时,发射端发射的光线被黑线吸收,接收端接收不到反射光线,传感器输出低电平信号后送80C51单片机处理,判断执行哪一种预先编制的程序来控制玩具车的行驶状态。前进时,驱动轮直流电机正转,进入减速区时,由单片机控制进行PWM变频调速,通过软件改变脉冲调宽波形的占空比,实现调速。最后经反接制动实现停车。前行与倒车控制电路的核心是桥式电路和继电器。电桥上设置有两组开关,一组常闭,另一组常开。电桥一端接电源,另一端接了一个三极管。三极管导通时,电桥通过三极管接地,电机电枢中有电流通过;三极管截止时,电桥浮空,电机电枢中没有电流通过。系统通过电桥的输出端为转向电机供电。通过对继电器开闭的控制即可控制电机的开断和转速方向进而达到控制玩具车前行与倒车的目的,实现随动控制系统的纠偏功能。如图2.3 前行与倒车控制电路所示。
图2.1电动车的方向检测电路(a)
图2.3前行与倒车控制电路
检测放大器方案:
方案一:使用普通单级比例放大电路。其特点是结构简单、调试方便、价格低廉。但是也存在着许多不足。如抗干扰能力差、共模抑制比低等。
方案二:采用差动放大电路。选择优质元件构成比例放大电路,虽然可以达到一定的精度,但有时仍不能满足某些特殊要求。例如,在测量本设计中的光电检测信号时需要把检测过来的电平信号放大并滤除干扰,而且要求对共模干扰信号具有相当强的抑制能力。这种情况下须采用差动放大电路,并应设法减小温漂。但在实际操作中,往往满足了高共模抑制比的要求,却使运算放大器输出饱和;为获得单片机能识别的TTL电平却又无法抑制共模干扰。
方案三:电压比较器方案。电压比较器的功能是比较两个电压的大小,例如将一个信号电压Ui和一个参考电压Ur进行比较,在Ui>Ur和Ui<Ur两种不同情况下,电压比较器输出两个不同的电平,即高电平和低电平。而Ui变化经过Ur时,比较器的输出将从一个电压跳变到另一个电平。比较器有各种不同的类型。对它的要求是:鉴别要准确,反应要灵敏,动作要迅速,抗干扰能力要强,还应有一定的保护措施,以防止因过电压或过电流而造成器件损坏。
比较器的特点:
⑴ 工作在开环或正反馈状态。放大、运算电路为了实现性能稳定并满足
一定的精度要求,这些电路中的运放均引入了深度负反馈;而为了提高比较器的反应速度和灵敏度,它所采用的运放不但没有引入负反馈,有时甚至还加正反馈。因此比较器的性能分析方法与放大、运算电路是不同的。
⑵ 非线性。由于比较器中运放处于开环或正反馈状态,它的两个输入端之间的电位差与开环电压放大倍数的乘积通常超过最大输出电压,使其内部某些管子进入饱和区或截止区,因此在绝大多数情况下输出与输入不成线性关系,即在放大、运算等电路中常用的计算方法对于比较器不再适用。
⑶ 开关特性。比较器的输出通常只有高电平和低电平两种稳定状态,因此它相当与一个受输入信号控制的开关,当输入电压经过阈值时开关动作,使输出从一个电平跳变到另一个电平。由于比较器的输入信号是模拟量,而它的输出电平是离散的,因此电压比较器可作为模拟电路与数字电路之间的过渡电路。
由于比较器的上述特点,在分析时既不能象对待放大电路那样去计算放大倍数,也不能象分析运算电路那样去求解输出与输入的函数关系,而应当着重抓住比较器的输出从一个电平跳变到另一个电平的临界条件所对应的输入电压值(阈值)来分析输入量与输出量之间的关系。
如果在比较器的输入端加理想阶跃信号,那么在理想情况下比较器的输出也应当是理想的阶跃电压,而且没有延迟。但实际集成运放的最大转换速率总是有限的,因此比较器输出电压的跳变不可能是理想的阶跃信号。电压比较器的输出从低电平变为高电平所须的时间称为响应时间。响应时间越短,响应速度越快。
减小比较器响应时间的主要方法有:
(1) 尽可能使输入信号接近理想情况,使它在阈值附近的变化接近理想阶跃
且幅度足够大。
(2) 选用集成电压比较器。
(3) 如果选用集成运放构成比较器,为了提高响应速度可以加限幅措施,以避免集成运放内部的管子进入深饱和区。具体措施多为在集成运放的两个输入端并联二极管。如图2.4 电压比较器电路所示:
图2.4 电压比较器电路
在本设计中,光电传感器只输出一种高低电平信号且伴有外界杂波干扰,所以我们尝试采用了一种滞回比较器。简单电压比较器结构简单,而且灵敏度高,但它的抗干扰能力差,也就是说如果输入信号因受干扰在阈值附近变化,则比较器输出就会反复的从一个电平跳到另一个电平。如果用这样的输出电压控制电机或继电器,将出现频繁动作或起停现象。这种情况,通常是不允许的。而滞回比较器则解决了这个问题。滞回比较器有两个数值不同的阈值,当输入信号因受干扰或其他原因发生变化时,只要变化量不超过两个阈值之差,滞回比较器的输出电压就不会来回变化。所以抗干扰能力强。但是,滞回比较器毕竟是模拟器件,温度的漂移是它无法消除的。
方案四:施密特触发器。综合考虑系统的各项性能,最后我们决定采用数字器件——施密特触发器。施密特触发器是双稳态触发器的变形,它有两个稳定状态,触发方式为电平触发,只要外加触发信号的幅值增加到足够大,它就从一个稳定状态翻转到另一个稳定状态。施密特触发器具有与滞回比较器相类似的滞回特性,但施密特触发器的抗干扰能力比滞回比较器更强。
2.行车距离检测
由于红外检测具有反应速度快、定位精度高,可靠性强以及可见光传感器所不能比拟的优点,故采用红外光电码盘测速方案。具体电路同图2.5 行车距离检测电路所示:
图2.5 行车距离检测电路
红外测距仪由测距轮,遮光盘,红外光电耦合器及凹槽型支架组成的。测长轮的周长为记数的单位,最好取有效值为单一的数值(如本设计中采用0.1米),精度根据电动车控制的需要确定。测距轮安装在车轮上,这样能使记数值准确一些。遮光盘有一缺口,盘下方的凹形物为槽型光电耦合器,其两端高出部分的里面分别装有红外发射管和红外接收管。遮光盘在凹槽中转动时,缺口进入凹槽时,红外线可以通过,缺口离开凹槽红外线被阻挡。由此可见,测距轮每转一周,红外光接收管均能接收到一个脉冲信号经过整形器后送入计数器或直接送入单片机中。
为实现可逆记数功能,我们在测距仪中并列放置了两个槽型光电耦合器,遮光盘先后通过凹槽可产生两个脉冲信号。根据两个脉冲信号发生的先后顺序与两个光电耦合器的位置关系,即可计算出玩具车的行驶方向(前进或后退)。
遮光盘及槽型光电耦合器均安装在不透光的盒子里,以避免外界光线的干扰,使电路不能正常工作。
测距原理:将光栅安装在电机轴上,当电机转动时,光栅也随之转动,同时安装在光栅一侧的红外发光二极管点亮,在光栅的另一侧设有红外三极管,用于接收红外发光二极管发出的红外线信号。由于光栅随电机高速转动,则红外线三极管接收到的就是一系列脉冲信号。将该信号传输到80C51单片机的内部计数器计数,根据预先实测的数据换算关系即可计算出电动机车的行车距离。
三、显示电路
本设计中用两片4位八段数码作显示器,并具有双重功能,在小车不行驶时其中一片显示年、月,另一片显示时、分; 当小车行驶时,分别显示时间和行驶距离。
四 、系统原理图 简易智能电动车采用80C51单片机进行智能控制。开始由手动启动小车,并复位,当经过规定的起始黑线,由超声波传感器和红外光电传感器检测,通过单片机控制小车开始记数显示并避障、调速;系统的自动避障功能通过超声波传感器正前方检测和红外光电传感器左右侧检测,由单片机控制实现;在电动车进驶过程中,采用双极式H型PWM脉宽调制技术,以提高系统的静动态性能;采用动态共阴显示行驶时间和里程。 系统原理图如图2.6所示。 图2.6 系统原理图
第三章、 硬件设计
单片机应用系统的硬件电路设计包含有两部分内容: 一是系统扩展,即单片机内部的功能单元,如ROM﹑RAM﹑I/O口﹑定时/记数器﹑中断系统等能量不能满足应用系统的要求时,必须在片外进行扩展,选择适当的芯片,设计相应的电路。 二是系统配置,既按照系统功能要求配置外围设备,如键盘显示器﹑打印机﹑A/D﹑D/A转换器等,要设计合适的接口电路。
一 、80C51单片机硬件结构 80C51单片机是把那些作为控制应用所必需的基本内容都集成在一个尺寸有限的集成电路芯片上[2]。如果按功能划分,它由如下功能部件组成,即微处理器、数据存储器、程序存储器、并行I/O口、串行口、定时器/计数器、中断系统及特殊功能寄存器。它们都是通过片内单一总线连接而成,其基本结构依旧是CPU加上外围芯片的传统结构模式。但对各种功能部件的控制是采用特殊功能寄存器的集中控制方式。 - 1、微处理器:该单片机中有一个8位的微处理器,与通用的微处理器基本相同,同样包括了运算器和控制器两大部分,只是增加了面向控制的处理功能,不仅可处理数据,还可以进行位变量的处理。
- 2、数据存储器:片内为128个字节,片外最多可外扩至64k字节,用来存储程序在运行期间的工作变量、运算的中间结果、数据暂存和缓冲、标志位等,所以称为数据存储器。
- 3、程序存储器:由于受集成度限制,片内只读存储器一般容量较小,如果片内的只读存储器的容量不够,则需用扩展片外的只读存储器,片外最多可外扩至64k字节。
- 4、中断系统:具有5个中断源,2级中断优先权。
- 5、定时器/计数器:片内有2个16位的定时器/计数器, 具有四种工作方式。
- 6、串行口:1个全双工的串行口,具有四种工作方式。可用来进行串行通讯,扩展并行I/O口,甚至与多个单片机相连构成多机系统,从而使单片机的功能更强且应用更广。
- 7、P1口、P2口、P3口、P4口为4个并行8位I/O口。
- 8、特殊功能寄存器:共有21个,用于对片内的个功能的部件进行管理、控制、监视。实际上是一些控制寄存器和状态寄存器,是一个具有特殊功能的RAM区。
由上可见,80C51单片机的硬件结构具有功能部件种类全,功能强等特点。特别值得一提的是该单片机CPU中的位处理器,它实际上是一个完整的1位微计算机,这个一位微计算机有自己的CPU、位寄存器、I/O口和指令集。1位机在开关决策、逻辑电路仿真、过程控制方面非常有效;而8位机在数据采集,运算处理方面有明显的长处。MCS-51单片机中8位机和1位机的硬件资源复合在一起,二者相辅相承,它是单片机技术上的一个突破,这也是MCS-51单片机在设计的精美之处。
二 、最小应用系统设计 80C51是片内有ROM/EPROM的单片机,因此,这种芯片构成的最小系统简单﹑可靠。用80C51单片机构成最小应用系统时,只要将单片机接上时钟电路和复位电路即可,如图3.1 80C51单片机最小系统所示。由于集成度的限制,最小应用系统只能用作一些小型的控制单元。其应用特点: (1)有可供用户使用的大量I/O口线。 (2)内部存储器容量有限。 (3)应用系统开发具有特殊性。
图3.1 80C51单片机最小系统
1、时钟电路
80C51虽然有内部振荡电路,但要形成时钟,必须外部附加电路。80C51单片机的时钟产生方法有两种。内部时钟方式和外部时钟方式。
本设计采用内部时钟方式,利用芯片内部的振荡电路,在XTAL1、XTAL2引脚上外接定时元件,内部的振荡电路便产生自激振荡。本设计采用最常用的内部时钟方式,即用外接晶体和电容组成的并联谐振回路。振荡晶体可在1.2MHZ到12MHZ之间选择。电容值无严格要求,但电容取值对振荡频率输出的稳定性、大小、振荡电路起振速度有少许影响,CX1、CX2可在20pF到100pF之间取值,但在60pF到70pF时振荡器有较高的频率稳定性。所以本设计中,振荡晶体选择6MHZ,电容选择65pF。在设计印刷电路板时,晶体和电容应尽可能靠近单片机芯片安装,以减少寄生电容,更好的保证振荡器稳定和可靠地工作。为了提高温度稳定性,应采用NPO电容。
2、复位电路
80C51的复位是由外部的复位电路来实现的。复位引脚RST通过一个斯密特触发器用来抑制噪声,在每个机器周期的S5P2,斯密特触发器的输出电平由复位电路采样一次,然后才能得到内部复位操作所需要的信号。
复位电路通常采用上电自动复位和按钮复位两种方式。
最简单的上电自动复位电路中上电自动复位是通过外部复位电路的电容充电来实现的。只要Vcc的上升时间不超过1ms,就可以实现自动上电复位。时钟频率用6MHZ时C取22uF,R取1KΩ。
除了上电复位外,有时还需要按键手动复位。本设计就是用的按键手动复位。按键手动复位有电平方式和脉冲方式两种。其中电平复位是通过RST端经电阻与电源Vcc接通而实现的。按键手动复位电路见图3.2。时钟频率选用6MHZ时,C取22uF,Rs取200Ω,RK取1KΩ。
图3.2 80C51复位电路
三、 前向通道设计
单片机用与测控系统时,总要有与被测对象相联系的前向通道。因此,前向通道设计与被测对象的状态、特征、所处环境密切相关。在前向通道设计时要考虑到传感器或敏感元件选择、通道结构、信号调节、电源配置、抗干扰设计等。在通道电路设计中还涉及到模拟电路诸多问题。
1﹑前向通道的含义
当将单片机用作测﹑控系统时,系统中总要有被测信号输入通道,有计算机拾取必要的输入信息。作为测试系统,对被测对象拾取必要的原始参量信号是系统的核心任务,对控制系统来说,对被控对象状态的测试以及对控制条件的监测也是不可缺少的环节。对被测对象状态的测试一般都离不开传感器或敏感元件,这是因为被测对象的状态参数常常是一些非电物理量,如温度、压力、载荷、位移等,而计算机是一个数字电路系统。因此,在前向通道中,传感器、敏感元件及其相关电路占有重要地位。
对被测对象的信号的拾取其主要任务就是最忠实地反映被测对象的真实状态,它包括实时性与测量精度。同时使这些测量信号能满足计算机输入接口的电平要求。
因此,单片机应用系统中的前向通道体现了被测对象与系统相互联系的信号输入通道,原始参数输入通道。由于在该通道中主要是传感器与传感器有关的信号调节、变换电路,故也可称为传感器接口通道。
在单片机应用系统中,对信号输入、传感、变换应作广义理解,例如开关量的检测及信号输入,在单片机的各种应用系统中有着广泛的应用。最简单的开关量输入通道就是一个具有TTL电平的状态开关,如水银温度触点、温度晶闸管、时间继电器、限位开关等。故只要反映外界状态的信号输入通道都可称为前向通道。并不是所有单片机应用系统都有前向通道,例如时序控制系统,只根据系统内部的时间序列来控制外部的运行状态;分布式测控系统中的智能控制总站完成上级主计算机与现场测、控子站计算机之间的指令、数据传送。这些应用系统没有被测对象,故不需要前向通道。
2﹑前向通道的设计
(1)传感器的比较如下识别障碍的首要问题是传感器的选择,下面对几种传感器的优缺点进行说。探测障碍的最简单的方法是使用超声波传感器,它是利用向目标发射超声波脉冲,计算其往返时间来判定距离的。该方法被广泛应用于移动机器人的研究上。其优点是价格便宜,易于使用,且在10m以内能给出精确的测量。不过在ITS系统中除了上文提出的场景限制外,还有以下问题。首先因其只能在10m以内有效使用,所以并不适合ITS系统。另外超声波传感器的工作原理基于声,即使可以使之测达100m远,但其更新频率为2Hz,而且还有可能在传输中受到它信号的干扰,所以在CW/ICC系统中使用是不实际的。
视觉传感器在CW系统中使用得非常广泛。其优点是尺寸小,价格合理,在一定的宽度和视觉域内可以测量定多个目标,并且可以利用测量的图像根据外形和大小对目标进行分类。但是算法复杂,处理速度慢。雷达传感器在军事和航空领域已经使用了几十年。主要优点是可以鲁棒地探测到障碍而不受天气或灯光条件限制。近十年来随着尺寸及价格的降低,在汽车行业开始被使用。但是仍存在性价比的问题。
(2)超声波障碍检测 超声波是一种在弹性介质中的机械振荡,其频率超过20KHz,分横向振荡和纵向振荡两种,超声波可以在气体、液体及固体中传播,其传播速度不同。它有折射和反射现象,且在传播过程中有衰减。利用超声波的特性,可做成各种超声波传感器,结合不同的电路,可以制成超声波仪器及装置,在通讯、医疗及家电中获得广泛应用。 作为超声波传感器的材料,主要为压电晶体。压电晶体组成的超声波传感器是一种可逆传感器,它可以将电能转变成机械振荡而产生超声波,同时它接收到超声波时,也能转变成电能,故它分为发送器和接收器。超声波传感器有透射型、反射型两种类型,常用于防盗报警器、接近开关、测距及材料探伤、测厚等。 本设计采用T/R-40-12小型超声波传感器作为探测前方障碍物体的检测元件,其中心频率为40Hz,由80C51发出的40KHz脉冲信号驱动超声波传感器发送器发出40KHz的脉冲超声波,如电动车前方遇到有障碍物时,此超声波信号被障碍物反射回来,由接收器接收,经LM318两级放大,再经带有锁相环的音频解码芯片LM567解码,当LM567的输入信号大于25mV时,输出端由高电平变为低电平,送80C51单片机处理。超声波检测如图3.3超声波检测电路所示。
图 3.3 超声波检测电路
四、后向通道设计
在工业控制系统中,单片机总要对控制对象实现操作,因此,在这样的系统中,总要有后向通道。后向通道是计算机实现控制运算处理后,对控制对象的输出通道接口。
根据单片机的输出和控制对象实现控制信号的要求,后向通道具有以下特点:
(1) 小信号输出、大功率控制。根据目前单片机输出功率的限制,不能输出控制对象所要求的功率信号。
(2) 是一个输出通道。输出伺服驱动系统控制信号,而伺服驱动系统中的状态反馈信号通常是作为检测信号输入前向通道。
(3) 接近控制对象,环境恶劣。控制对象多为大功率伺服驱动机构,电磁、机械干扰较为严重。但后向通道是一个输出通道,而且输出电平较高,不易受到直接损害。但这些干扰易从系统的前向通道窜入。
单片机在完成控制处理后,总是以数字信号通过I/O口或数据总线送给控制对象。这些数字信号形态主要有开关量、二进制数字量和频率量,可直接用于开关量、数字量系统及频率调制系统,但对于一些模拟量控制系统,则应通过数/模转换成模拟量控制信号。
根据单片机输出信号形态及控制对象要求,后向通道应解决:
(1} 功率驱动。将单片机输出信号进行功率放大,以满足伺服驱动的功率要求。
(2)干扰防治。主要防治伺服驱动系统通过信号通道﹑电源以及空间电磁场对计算机系统的干扰。通常采用信号隔离﹑电源隔离和对功率开关实现过零切换等方法进行干扰防治。
(3)数/模转换。对于二进制输出的数字量采用D/A变换器;对于频率量输出则可以采用本设计调速采用PWM调速:
为顺利实现电动小汽车的左转和右转,本设计采用了可逆PWM变换器。可逆PWM变换器主电路的结构式有H型、T型等类型。我们在设计中采用了常用的双极式H型变换器,它是由4个三极电力晶体管和4个续流二极管组成的桥式电路。图3.4为双极式H型可逆PWM变换器的电路原理图。4个电力晶体管的基极驱动电压分为两组。VT1和VT4同时导通和关断,其驱动电路中Ub1=Ub4;VT2和VT3同时动作,其驱动电压Ub2=Ub3= -Ub1。
双极式PWM变换器的优点如下:
(1)电流一定连续;
(2)可使电动机在四象限中运行;
(3)电机停止时有微振电流,能消除静摩擦死区;
(4)低速时,每个晶体管的驱动脉冲仍较宽,有利于保证晶体管可靠导通;
(5)低速平稳性好,调速范围可达20000左右。
图3.4 双极式H型可逆PWM变换器电路原理图
1、脉宽调制原理:
脉宽调制器本身是一个由运算放大器和几个输入信号组成的电压比较器。运算放大器工作在开换状态,稍微有一点输入信号就可使其输出电压达到饱和值,当输入电压极性改变时,输出电压就在正、负饱和值之间变化,这样就完成了把连续电压变成脉冲电压的转换作用。加在运算放大器反相输入端上的有三个输入信号。一个输入信号是锯齿波调制信号,另一个是控制电压,其极性大小可随时改变,与锯齿波调制信号相减,从而在运算放大器的输出端得到周期不变、脉宽可变的调制输出电压。只要改变控制电压的极性,也就改变了PWM变换器输出平均电压的极性,因而改变了电动机的转向.改变控制电压的大小,则调节了输出脉冲电压的宽度,从而调节电动机的转速.只要锯齿波的线性度足够好,输出脉冲的宽度是和控制电压的大小成正比的.
2、逻辑延时环节:
在可逆PWM变换器中,跨接在电源两端的上下两个晶体管经常交替工作.由于晶体管的关断过程中有一段存储时间和电流下降时间,总称关断时间,在这段时间内晶体管并未完全关断.如果在此期间另一个晶体管已经导通,则将造成上下两管之通,从而使电源正负极短路.为避免发生这种情况,设置了由RC电路构成的延时环节.
3、电源的设计
本设计的电源为车载电源。为保证电源工作可靠,单片机系统与动力伺服系统的电源采用了大功率、大容量的蓄电池;而传感器的工作电源则采用了小巧轻便的干电池。
五、 显示电路设计
本设计中用两片4位八段数码管gem4561ae作显示器,并具有双重功能,在小车不行驶时其中一片显示年月,另一片显示时.分. 当小车行驶时,分别显示时间和行驶距离原理图如图1.
本设计中采用新型芯片EM78P458作为显示驱动器,它的管脚如图3.5 EM78P458管脚介绍所示,用单片机的并行口控制,一个数码显示电路用4个口线,用专用驱动芯片控制可以减少对CPU的利用时间,单片机将有更多的时间去完成其他功能.
图3.5 EM78P458的管脚
- 该芯片共有20个管脚,管脚LED1﹑LED2﹑LED3﹑LED4分别接10k电阻和三极管后与4位八段数码管5461中的a1﹑a2﹑a3﹑a4四个数位选择端相连,这四个数位选择端用来产生LED选通信号。
- 管脚a﹑b﹑c﹑d﹑e﹑f﹑g﹑dp分别接680欧电阻后与四位八段数码管5461中的a﹑b﹑c﹑d﹑e﹑f﹑g﹑dp相连,分别控制各段码和小数点。
- 管脚d0﹑d1﹑d2﹑d3接单片机并行口,通过对单片机对芯片进行控制。管脚vss串上10k电阻后与vcc管脚相接后再接+5v电源,管脚gnd接地。
该芯片所驱动的显示电路如图3.6 EM78P458集成显示电路所示 显示驱动器支持动态显示,其显示功能如表4.2真值表所示,0000-1001显示从0-9数字,1010是未进位时是小数点清位,1011是进位后加小数点,1100-1111是八段共阴数码管的位选。
图3.6 EM78P458集成显示电路
第四章、软件设计
系统软件设计说明
在进行微机控制系统设计时,除了系统硬件设计外,大量的工作就是如何根据每个生产对象的实际需要设计应用程序。因此,软件设计在微机控制系统设计中占重要地位。对于本系统,软件更为重要。
在单片机控制系统中,大体上可分为数据处理、过程控制两个基本类型。数据处理包括:数据的采集、数字滤波、标度变换等。过程控制程序主要是使单片机按一定的方法进行计算,然后再输出,以便控制生产。
为了完成上述任务,在进行软件设计时,通常把整个过程分成若干个部分,每一部分叫做一个模块。所谓“模块”,实质上就是所完成一定功能,相对独立的程序段,这种程序设计方法叫模块程序设计法。
模块程序设计法的主要优点是:
1、单个模块比起一个完整的程序易编写及调试;
2、模块可以共存,一个模块可以被多个任务在不同条件下调用;
3、模块程序允许设计者分割任务和利用已有程序,为设计者提供方便。
本系统软件采用模块化结构,由主程序﹑定时子程序、避障子程序﹑中断子程序显示子程序﹑调速子程序﹑算法子程序构成。
一 、主程序设计 程序清单如下:
- limiw equ 30h ;厘米位
- miao equ 31h ;秒位
- fenmi equ 32h ;分米位
- fmiao equ 33h ;分秒位
- meter equ 34h ;米位
- fenzh equ 35h ;分位
- point equ 36h ;小数点位
- shimi equ 37h ;十米位
- shifn equ 38h ;十分位
- sudu equ 39h ;速度控制
- jishk equ 3ah ;记时开始
- zhond equ 3bh
- zhodu equ 3ch
- zhon equ 3eh
- maicho equ 3fh
- jinweb equ 40h
- bhcs equ 41h
- dpan equ 42h
- fenchu equ 43h
- fencun equ 44h
- pand equ 45h
- fenmc equ 51h
- org 0000h
- ajmp main
- org 000bh
- ajmp st0
- org 001bh
- ajmp st1
- org 0100h
- main:
- mov limiw,#00h
- mov miao,#00h
- mov fenmi,#00h
- mov fmiao,#00h
- mov meter,#00h
- mov fenzh,#00h
- mov point,#0bh
- mov shimi,#00h
- mov shifn,#00h
- mov jishk,#00h
- mov zhond,#00h
- mov zhodu,#00h
- mov zhon,#00h
- mov maicho,#00h
- mov jinweb,#03h
- mov bhcs,#00h
- mov sp,#6fh
- mov tmod,#21h
- mov th0,#3ch
- mov tl0,#0b0h
- mov th1,#9ch
- mov tl1,#9ch
- setb ea
- setb et0
- setb et1
- mov p1,#0aah
- acall xianshi
复制代码 二、 显示子程序设计
程序清单如下:
- xianshi:
- mov p1,#0aah
- mov p1,#0cch
- mov a,limiw
- swap a
- add a,miao
- mov p1,a
- nop
- nop
- mov p1,#0ddh
- mov a,fenmi
- swap a
- add a,fmiao
- mov p1,a
- nop
- nop
- mov p1,#0eeh
- mov a,#0b0h
- add a,point
- mov p1,a
- nop
- nop
- mov p1,#0eeh
- mov a,meter
- swap a
- add a,fenzh
- mov p1,a
- nop
- nop
- mov p1,#0ffh
- mov a,shimi
- swap a
- add a,shifn
- mov p1,a
- ret
复制代码
三 、避障子程序设计
程序清单如下:
- <font face="黑体">zhangai:
- jb 25h,stop
- jnb 22h,youzhuan
- jnb 23h,youzhuan
- jnb 24h,zuozhuan
- jnb 26h,zuozhuan
- ajmp jiance
- zuozhuan:
- clr p0.5
- clr p0.4
- mov sudu,#05h
- acall delaa
- setb p0.4
- setb p0.5
- mov sudu,#07h
- ajmp jiance
- youzhuan:
- clr p0.6
- clr p0.7
- mov sudu,#05h
- acall delaa
- setb p0.7
- setb p0.6
- mov sudu,#07h
- ajmp jiance
- stop:
- acall delay
- jnb 25h,zhangai
- clr tr0
- mov a,fenmi
- mov fenmc,a
- mov a,#02h
- add a,fenmc
- mov fenmc,a
- here: cjne a,fenmi,here
- clr tr1
- setb p2.6
- acall delaa
- setb p2.7
- ajmp $
- </font>
复制代码
四、 整体程序设计如下所示:
程序清单如下:
- limiw equ 30h ;厘米位
- miao equ 31h ;秒位
- fenmi equ 32h ;分米位
- fmiao equ 33h ;分秒位
- meter equ 34h ;米位
- fenzh equ 35h ;分位
- point equ 36h ;小数点位
- shimi equ 37h ;十米位
- shifn equ 38h ;十分位
- sudu equ 39h ;速度控制
- jishk equ 3ah ;记时开始
- zhond equ 3bh
- zhodu equ 3ch
- zhon equ 3eh
- maicho equ 3fh
- jinweb equ 40h
- bhcs equ 41h
- dpan equ 42h
- fenchu equ 43h
- fencun equ 44h
- pand equ 45h
- fenmc equ 51h
- org 0000h
- ajmp main
- org 000bh
- ajmp st0
- org 001bh
- ajmp st1
- org 0100h
- main:
- mov limiw,#00h
- mov miao,#00h
- mov fenmi,#00h
- mov fmiao,#00h
- mov meter,#00h
- mov fenzh,#00h
- mov point,#0bh
- mov shimi,#00h
- mov shifn,#00h
- mov jishk,#00h
- mov zhond,#00h
- mov zhodu,#00h
- mov zhon,#00h
- mov maicho,#00h
- mov jinweb,#03h
- mov bhcs,#00h
- mov sp,#6fh
- mov tmod,#21h
- mov th0,#3ch
- mov tl0,#0b0h
- mov th1,#9ch
- mov tl1,#9ch
- setb ea
- setb et0
- setb et1
- mov p1,#0aah
- acall xianshi
- qidong:
- jb p0.0,qidong
- acall delay
- jb p0.0,qidong
- mov sudu,#03h
- clr p2.6
- clr p2.7
- setb tr1
- start:
- jnb p2.3,start
- acall delay
- jnb p2.3,start
- mov sudu,#07h
- setb tr0
- mov jishk,#01h
- call delaa
- call delaa
- call delaa
- call delaa
- call delaa
- jiance:
- mov c,p2.0
- mov 22h,c
- mov c,p2.1
- mov 23h,c
- mov c,p2.2
- mov 24h,c
- mov c,p2.3
- mov 25h,c
- mov c,p2.4
- mov 26h,c
- zhangai:
- jb 25h,stop
- jnb 22h,youzhuan
- jnb 23h,youzhuan
- jnb 24h,zuozhuan
- jnb 26h,zuozhuan
- ajmp jiance
- zuozhuan:
- clr p0.5
- clr p0.4
- mov sudu,#05h
- acall delaa
- setb p0.4
- setb p0.5
- mov sudu,#07h
- ajmp jiance
- youzhuan:
- clr p0.6
- clr p0.7
- mov sudu,#05h
- acall delaa
- setb p0.7
- setb p0.6
- mov sudu,#07h
- ajmp jiance
- stop:
- acall delay
- jnb 25h,zhangai
- clr tr0
- mov a,fenmi
- mov fenmc,a
- mov a,#02h
- add a,fenmc
- mov fenmc,a
- here: cjne a,fenmi,here
- clr tr1
- setb p2.6
- acall delaa
- setb p2.7
- ajmp $
- st0:
- push acc
- push psw
- mov th0,#3ch
- mov tl0,#0b0h
- inc zhond
- mov a,#0ah
- cjne a,zhond,out
- mov zhond,#00h
- inc zhodu
- mov a,#02h
- cjne a,zhodu,miepo
- mov point,#0bh
- mov zhodu,#00h
- inc miao
- mov a,#0ah
- cjne a,miao,out
- mov miao,#00h
- inc fmiao
- mov a,#06h
- cjne a,fmiao,out
- mov fmiao,#00h
- inc fenzh
- mov a,#0ah
- cjne a,fenzh,out
- mov fenzh,#00h
- inc shifn
- out:
- call xianshi
- outb:
- pop psw
- pop acc
- reti
- miepo:
- mov point,#0ah
- ajmp out
- st1:
- push acc
- push psw
- inc zhon
- mov a,sudu
- cjne a,zhon,hig
- setb p2.7
- ajmp outi
- hig:
- mov a,#0ah
- cjne a,zhon,outi
- mov zhon,#00h
- clr p2.7
- outi:
- mov a,#01h
- cjne a,jishk,outb
- jb p2.5,gao
- mov c,p2.5
- mov 21h,c
- orl c,20h
- clr 20h
- jc youbh
- ajmp outb
- gao:
- setb 20h
- ajmp outb
- youbh:
- inc maicho
- mov a,jinweb
- cjne a,maicho,outb
- mov maicho,#00h
- inc bhcs
- mov a,#02h
- cjne a,bhcs,jici
- mov jinweb,#03h
- goon:inc limiw
- mov a,#0ah
- cjne a,limiw,out
- mov limiw,#00h
- inc fenmi
- cjne a,fenmi,out
- mov fenmi,#00h
- inc meter
- cjne a,meter,out
- mov meter,#00h
- inc shimi
- ajmp out
- jici:
- mov jinweb,#02h
- ajmp goon
- xianshi:
- mov p1,#0aah
- mov p1,#0cch
- mov a,limiw
- swap a
- add a,miao
- mov p1,a
- nop
- nop
- mov p1,#0ddh
- mov a,fenmi
- swap a
- add a,fmiao
- mov p1,a
- nop
- nop
- mov p1,#0eeh
- mov a,#0b0h
- add a,point
- mov p1,a
- nop
- nop
- mov p1,#0eeh
- mov a,meter
- swap a
- add a,fenzh
- mov p1,a
- nop
- nop
- mov p1,#0ffh
- mov a,shimi
- swap a
- add a,shifn
- mov p1,a
- ret
- delay:
- mov 46h,#0ffh
- mov 47h,#0ffh
- i:djnz 47h,i1
- i1:djnz 46h,i
- ret
- delaa:
- mov 48h,#0ah
- ii:mov 49h,#0afh
- ii2:mov 50h,#0ffh
- ii3:djnz 50h,ii3
- djnz 49h,ii2
- djnz 48h,ii
- ret
复制代码
五、软件抗干扰技术
提高玩具车智能控制的可靠性,仅靠硬件抗干扰是不够的,需要进一步借助于软件抗干扰技术来克服某些干扰。在单片机控制系统中,如能正确的采用软件抗干扰技术,与硬件干扰措施构成双道抗干扰防线,无疑为了将大大提高控制系统的可靠性。经常采用的软件抗干扰技术是数字滤波技术、开关量的软件抗干扰技术、指令冗余技术、软件陷阱技术等。
1、数字滤波技术:
一般单片机应用系统的模拟输入信号中,均含有种种噪音和干扰,它们来自被测量本身、传感器、外界干扰等。为了进行准确测量和控制,必须消除被测信号中的噪音和干扰。对于这类信号,采用积分时间等于20ms的整数倍的双积分A/D转换器,可有效的消除其影响。后者为随机信号,它不是周期信号。对于随机干扰,我们可以用数字滤波方法予以削弱或滤除。所谓数字滤波,就是通过一定的计算或判断程序减少干扰在有用信号中的比重。故实质上它是一种程序滤波。数字滤波克服了模拟滤波器的不足,它与模拟滤波器相比 ,有以下几个优点:
- 数字滤波是用程序实现的,不需要增加硬设备,所以可靠性高,稳定性好。
- 数字滤波可以根据信号的不同,采用不同的滤波方法或滤波参数,具有灵活、方便,功能强的特点。
- 数字滤波可以对频率很低的信号实现滤波,克服了模拟滤波器的缺陷。
- 数字滤波器具有以上优点,所以数字滤波在微机应用系统中得到了广泛应用。
2、开关量的软件抗干扰技术:
干扰信号多呈毛刺状,作用时间短,利用这一点,我们在采集某一开关量信号时,可多次重复采集,直到连续两次或两次以上结果完全一致方为有效。若多次采样后,信号总是变化不定,可停止采集,给出报警信号,由于开关量信号主要是来自各类开
关型状态传感器,如限位开关、操作按钮、电气触点等,对这些信号的采集不能用多次平均的方法,必须绝对一致才行。如果开关量信号超过8个,可按8个一组进行分组处理,也可定义多字节信息暂存区,按类似方法处理。在满足实时性要求的前提下,如果在各次采集数字信号之间接入一段延时,效果会好一些,就能对抗较宽的干扰。
输出设备是电位控制型还是同步锁存型,对干扰的敏感性相对较大。前者有良好的抗‘毛刺’干扰能力,后者不耐干扰,当锁存线上出现干扰时,它就会盲目锁存当前的数据,也不管此时数据是否有效。输出设备和惯性(响应速度)与干扰的耐受能力也有很大关系。惯性大的输出设备(如各类电磁执行机构)对‘毛刺’干扰有一定的耐受能力。惯性小的输出设备(如通行口、显示设备)耐受能力就小一些。在软件上,最为有效的方法就是重复输出同一个数据。只要有可能,其重复周期尽可能短些。外设设备接受到一个被干扰的错误信息后,还来不及作出有效的反应,一个正确的信息又来了,就可及时防止错误动作的产生。另外,各类数据锁存器尽可能和CPU安装在同一电路板上,使传输线上传送的都是锁存好的电位控制信号,对于重要的输出设备,最好建立检测通道,CPU可以检测通道来确定输出结果的正确性。
3、指令冗余技术:
当CPU受到干扰后,往往将一些操作数当作指令码来执行,引起程序混乱。当程序弹飞到某一字节指令上时,便自动纳入正轨。当弹飞到某一双字节指令上时,有可能落到其操作数上,从而继续出错。当程序弹飞到三字节指令上时,因它有两个操作数,继续出错的机会就更大。因此,我们应多采用单字节指令(NOP)或将单字节指令重复书写,这便是指令冗余。指令冗余无疑会降低系统的效率,但在绝大多数情况下,CPU还不至于忙到不能多执行几条指令的程度,故这种方法还是被广泛采用。
在一些对程序流向起决定作用的指令之前插入两条NOP指令,以保证弹飞的程序迅速纳入正确轨道。在某些对系统工作状态重要的指令前也可插入两条NOP指令,以保证正确执行。指令冗余技术可以减少程序弹飞的次数,使其很快进入程序轨道,但这并不能保证在失控期间不干坏事,更不能保证程序纳入正常轨道后就太平无事了,解决这个问题必须采用软件容错技术。
4﹑软件陷阱技术:
指令冗余使弹飞的程序安定下来是有条件的。首先,弹飞的程序必须落到程序区;其次,必须执行到冗余指令。所谓软件陷阱,就是一套引导指令,强行将捕获的程序引向一个指定的地址,在那里有一段专门对程序出错进行处理的程序。如果我们把这段程序的入口标号记为 ERR 的话,软件陷阱即为一条无条件转移指令,为了加强其捕捉效果,一般还在它前面加两条 NOP 指令,因此真正的软件陷阱由3条指令构成:
软件陷阱安排在以下四种地方:
(1)未使用的中断向量区。
(2)未使用的大片ROM空间
(3)表格
5、程序区
由于软件陷阱都安排在正常程序执行不到的地方,故不影响程序执行效率,在当前EPROM容量不成问题的条件下,还是多多益善。
六 、看门狗技术
PC受到干扰而失控,引起程序乱飞,也可能使程序陷入“死循环” [6]。指令技术、软件陷阱技术不能使失控的程序摆脱“死循环”的困境,这时系统完全瘫痪。如果操作者在场,就可以按下人工复位安钮,强制系统复位。但操作者不能一直监视着系统,也往往是在引起不良后果之后才进行人工复位。为使程序脱离“死循环”,通常采用“看门狗技术”。“看门狗”技术就是不断监视程序循环运行时间,若发现时间超过已知的循环设定时间,则认为系统陷入了“死循环”,然后强迫程序返回到0000H入口,在0000H处安排一段出错处理程序,使系统运行纳入正规。
“看门狗”技术可由硬件实现,可由软件实现,也可由两者结合实现。本系统采用硬件“看门狗”电路。
实现硬件“看门狗”电路方案较多,目前采用较多的方案有以下几种:
- 采用微处理器监控器;
- 采用单稳态电路来实现“看门狗”,单稳定电路可采用74LS123;
- 采用内带震荡器的记数芯片。
本设计采用第三种方案实现“看门狗”电路,下面就对该方案作以介绍。
(1)基本原理
CD4060 是带震荡器的14位计数器,由该芯片构成的看门狗电路4060记数频率由RT和CT决定。设实际的程序所需工作周期为T,分频器记满时间为T’,当T’>T 且系统正常工作时,程序每隔T对4060进行扫描一次,分频且永无记满输出信号。如系统工作不正常(如程序跑飞、死循环等),程序对4060发不出扫描信号,分频器记满输出一脉冲号使CPU复位。
(2)参数选择
4060的振荡频率f由 RT 、CT决定。Rs用于改善振荡器的稳定性,Rs 要大于RT。一般取Rs=10RT,且RT>1kΩ,CT≥100pF。如果Rs=450Ω,RT=45Ω,CT=1uF,则f=10HZ。4060的振荡频率和Qi(i=6,7,8,9,10,12,13,14)的选择要根据情况确定。
(3)几个原则
看门狗电路必须由硬件逻辑组成,不宜由可编程计数器充当,因为CPU失控后,可能会修改可编程器件参数,使看门狗失效。4060的RST线上阻容组成的微分电路很重要,因为扫描输入信号是CPU产生的正脉冲,若此信号变“1”后,由于干扰,程序乱飞,微分电路只能让上跳沿通过,不会封死4060,看门狗仍能计数起作用。若没有微分电路,扫描输入信号上的“1”状态封死4060,使之不能记数,看门狗不起作用。CPU必须在正确完成所有工作后才能发扫描输入信号,且程序中发扫描信号的地方不能太多。否则,正好在哪里有死循环,看门狗就不产生记满输出信号,不能重新启动CPU。4060的记满输出信号不但要接到MCS-51的RST脚,而且还应接到其它芯片的RST脚,因为程序乱飞后,其它具有RST脚的芯片也混乱了,必须全部复位。
六、可编程逻辑器件
可编程逻辑器件GAL16V8是LATTICE公司研制的一种电可擦除的可重复编程的低密度PLD器件。它采用更为灵活的可编I/O结构,并采用了先进的EECOMS工艺,数秒内即可完成芯片的擦除和编程过程,并可反复改写,是产品开发研制的理想器件之一。
GAL16V8技术特性
(1)电可擦除工艺
可重编程单元
100%成品率
可重配置逻辑
(2)高性能E2CMOS工艺
低功耗:45mA最大运行功耗,35mA最大维持功耗
高速度:15~25us最快存取速度
(3)8个输出逻辑单元
对于复杂逻辑设计具有最大灵活性,GAL16V8可仿真20条引脚的PAL器件,具有功能 / 熔丝图 /参数的完全兼容性
(4)预置、加电复位全部寄存器
(5)具有保密单元、电子标签
(6)数据保持超过20年。
80C51按键电路直接由80C51接口电路查询。消抖(延时20ms)由软件延时完成。
实现电压测量、频率测量与实时时钟功能的程序如下:(显示和操作通过矩阵键盘实现)
- #include "STC15.h"
- #include <intrins.h>
- sbit SCK=P1^7;
- sbit SDA=P2^3;
- sbit RST = P1^3; // DS1302复位
- void Write_Ds1302_Byte(unsigned char temp)
- {
- unsigned char i;
- for (i=0;i<8;i++)
- {
- SCK=0;
- SDA=temp&0x01;
- temp>>=1;
- SCK=1;
- }
- }
- void Write_Ds1302( unsigned char address,unsigned char dat )
- {
- RST=0;
- _nop_();
- SCK=0;
- _nop_();
- RST=1;
- _nop_();
- Write_Ds1302_Byte(address);
- Write_Ds1302_Byte(dat);
- RST=0;
- }
- unsigned char Read_Ds1302 ( unsigned char address )
- {
- unsigned char i,temp=0x00;
- RST=0;
- _nop_();
- SCK=0;
- _nop_();
- RST=1;
- _nop_();
- Write_Ds1302_Byte(address);
- for (i=0;i<8;i++)
- {
- SCK=0;
- temp>>=1;
- if(SDA)
- temp|=0x80;
- SCK=1;
- }
- RST=0;
- _nop_();
- RST=0;
- SCK=0;
- _nop_();
- SCK=1;
- _nop_();
- SDA=0;
- _nop_();
- SDA=1;
- _nop_();
- return (temp);
- }
复制代码- #include "STC15.h"
- #include "ds1302.h"
- #include "iic.h"
- #include "intrins.h"
- typedef unsigned char u8;
- typedef unsigned int u16;
- typedef unsigned long u32;
- u8 e_write_flag=0;
- u8 mode=0;
- u8 code t_display[]={ //标准字库
- // 0 1 2 3 4 5 6 7 8 9 -
- 0x3F,0x06,0x5B,0x4F,0x66,0x6D,0x7D,0x07,0x7F,0x6F,0x40};
- void Delay1ms() //@11.0592MHz
- {
- unsigned char i, j;
- _nop_();
- _nop_();
- _nop_();
- i = 11;
- j = 190;
- do
- {
- while (--j);
- } while (--i);
- }
- void delay_ms(u16 i)
- {
- while(i--)
- Delay1ms();
- }
- void dis_num(u8 x,u8 num) //数码管显示
- {
- P0=0X01<<x;
- P2=0XC0;
- P2=0X00;
- P0=~t_display[num];
- P2=0XE0;
- Delay1ms();
- P0=0XFF;
- P2=0X00;
- }
- u8 ad() //AD采集
- {
- u8 i;
- IIC_Start();
- IIC_SendByte(0x90);
- IIC_WaitAck();
- IIC_SendByte(0x03);
- IIC_WaitAck();
- IIC_Start();
- IIC_SendByte(0x91);
- IIC_WaitAck();
- i=IIC_RecByte();
- IIC_Stop();
- return i;
- }
- void DS1302_Init() //1302初始化
- {
- Write_Ds1302(0x8e,0x00);
- Write_Ds1302(0x80,0x55);
- Write_Ds1302(0x82,0x59);
- Write_Ds1302(0x84,0x23);
- Write_Ds1302(0x8e,0x80);
- }
- void show_time() //显示时间
- {
- u8 i;
- i=Read_Ds1302(0x85);
- dis_num(0,(i&0xf0)>>4);
- dis_num(1,(i&0x0f));
- dis_num(2,10);
- i=Read_Ds1302(0x83);
- dis_num(3,(i&0xf0)>>4);
- dis_num(4,(i&0x0f));
- dis_num(5,10);
- i=Read_Ds1302(0x81);
- dis_num(6,(i&0xf0)>>4);
- dis_num(7,(i&0x0f));
- }
- void write_eeprom(u8 adr,u8 dat) //写入EEPROM
- {
- IIC_Start();
- IIC_SendByte(0xa0);
- IIC_WaitAck();
- IIC_SendByte(adr);
- IIC_WaitAck();
- IIC_SendByte(dat);
- IIC_WaitAck();
- IIC_Stop();
- }
- u8 read_eeprom(u8 adr) //读取EEPROM
- {
- u8 i;
- IIC_Start();
- IIC_SendByte(0xa0);
- IIC_WaitAck();
- IIC_SendByte(adr);
- IIC_WaitAck();
- IIC_Start();
- IIC_SendByte(0xa1);
- IIC_WaitAck();
- i=IIC_RecByte();
- IIC_Stop();
- return i;
- }
- u8 scan_key() //按键扫描
- {
- u8 key,i;
- for(i=0;i<2;i++)
- {
- P3|=0X0F;
- switch(i)
- {
- case 0:{P44=0;P42=1;}break;
- case 1:{P44=1;P42=0;}break;
- }
- key=P3&0X0F;
- if(key!=0x0f)
- {
- delay_ms(30);
- key=P3&0X0F;
- if(key!=0x0f)
- {
- while((P3&0X0F)!=0X0F);
- switch(key)
- {
- case 0x0e:return i*4+7;break;
- case 0x0d:return i*4+6;break;
- case 0x0b:return i*4+5;break;
- case 0x07:return i*4+4;break;
- }
- }
- }
- }
- return 0;
- }
- void Time0_Init()
- {
- AUXR = 0x80; //定时器0为1T模式
- TMOD = 0x04; //设置定时器0为16位自动重装载外部记数模式
- TH0 = TL0 = 0xff; //设置定时器0初始值
- TR0 = 0; //定时器0开始工作
- ET0 = 1; //开定时器0中断
- }
- void Timer1Init(void) //50毫秒@11.0592MHz
- {
- AUXR &= 0xBF; //定时器时钟12T模式
- TMOD &= 0x0F; //设置定时器模式
- TL1 = 0x00; //设置定时初值
- TH1 = 0x4C; //设置定时初值
- TF1 = 0; //清除TF1标志
- TR1 = 0; //定时器1开始计时
- ET1 = 1;
- }
- void Timer2Init(void) //50毫秒@11.0592MHz
- {
- AUXR &= 0xFB; //定时器时钟12T模式
- T2L = 0x00; //设置定时初值
- T2H = 0x4C; //设置定时初值
- IE2 |= (1<<2); //允许中断
- AUXR |= 0x10; //定时器2开始计时
- IE2 |= 0x04; //开定时器2中断
- }
- //调整时间
- bit change_time()
- {
- u8 x,k,temp_0,temp_1,show_flag;
- u8 time[3]={0};
- x=Read_Ds1302(0x85);
- time[0]=((x&0xf0)>>4)*10+(x&0x0f);
- x=Read_Ds1302(0x83);
- time[1]=((x&0xf0)>>4)*10+(x&0x0f);
- x=Read_Ds1302(0x81);
- temp_0=x;
- time[2]=((x&0xf0)>>4)*10+(x&0x0f);
- x=0;
- show_flag=1;
- while(1)
- {
- if(show_flag)
- {
- dis_num(x*3,time[x]/10);
- dis_num(x*3+1,time[x]%10);
- }
- switch(x)
- {
- case 0:{dis_num(2,10);dis_num(3,time[1]/10);dis_num(4,time[1]%10);dis_num(5,10);dis_num(6,time[2]/10);dis_num(7,time[2]%10);}break;
- case 1:{dis_num(0,time[0]/10);dis_num(1,time[0]%10);dis_num(2,10);dis_num(5,10);dis_num(6,time[2]/10);dis_num(7,time[2]%10);}break;
- case 2:{dis_num(0,time[0]/10);dis_num(1,time[0]%10);dis_num(2,10);dis_num(3,time[1]/10);dis_num(4,time[1]%10);dis_num(5,10);}break;
- }
- k=scan_key();
- if(k==7)
- {
- Write_Ds1302(0x8e,0x00);
- Write_Ds1302(0x80,(((time[2]/10)<<4)|(time[2]%10)));
- Write_Ds1302(0x82,(((time[1]/10)<<4)|(time[1]%10)));
- Write_Ds1302(0x84,(((time[0]/10)<<4)|(time[0]%10)));
- Write_Ds1302(0x8e,0x80);
- return 0;
- }
- if(k!=0)
- {
- switch(k)
- {
- case 4:{x++;if(x==3)x=0;}break;
- case 11:{time[x]++;if(time[x]>59)time[x]=0;}break;
- case 10:{if((x!=0)&(time[x]==0))time[x]=60;if((x==0)&(time[x]==0))time[x]=13;time[x]--;}break;
- }
- }
- temp_1=Read_Ds1302(0x81);
- if(temp_1!=temp_0)
- {
- temp_0=temp_1;
- show_flag=!show_flag;
- }
-
- }
- }
- bit menu_1()//显示时间和设置时间
- {
- u8 k,x;
- x=0;
- while(1)
- {
- show_time();
- k=scan_key();
- if(k==4)
- {
- change_time();
- }
- switch(k)
- {
- case 6:{mode=1;return 1;}break;
- case 5:{mode=2;return 1;}break;
- case 9:{mode=3;return 1;}break;
- }
- }
- }
- u8 V[2]={0,0};
- bit change_V() //修改电压上下限
- {
- u8 k,x,show_flag,temp_0,temp_1;
- x=0;
- show_flag=1;
- temp_0=Read_Ds1302(0x81);
- while(1)
- {
- if(show_flag)
- {
- if(x)
- {
- dis_num(4,V[1]/10);
- dis_num(5,V[1]%10);
- dis_num(6,0);
- dis_num(7,0);
- }
- else
- {
- dis_num(0,V[0]/10);
- dis_num(1,V[0]%10);
- dis_num(2,0);
- dis_num(3,0);
- }
- }
- if(x)
- {
- dis_num(0,V[0]/10);
- dis_num(1,V[0]%10);
- dis_num(2,0);
- dis_num(3,0);
- }
- else
- {
- dis_num(4,V[1]/10);
- dis_num(5,V[1]%10);
- dis_num(6,0);
- dis_num(7,0);
- }
- k=scan_key();
- temp_1=Read_Ds1302(0x81);
- if(temp_1!=temp_0)
- {
- temp_0=temp_1;
- show_flag=!show_flag;
- }
- if(k!=0)
- {
- switch(k)
- {
- case 4:{x++;if(x==2)x=0;}break;
- case 11:{
- if((x==1)&(V[0]>V[1])&(V[1]<95))
- V[x]+=5;
- if((x==0)&(V[0]<95))
- V[x]+=5;
- }break;
- case 10:{
- if((x==0)&(V[0]>V[1])&(V[0]>4))
- V[x]-=5;
- if((x==1)&(V[1]>4))
- V[x]-=5;
- }break;
- }
- }
- if(k==6)
- {
- write_eeprom(0,V[0]);
- delay_ms(50);
- write_eeprom(1,V[1]);
- return 1;
- }
- }
- }
- bit menu_2() //显示电压
- {
- u16 i;
- u8 k;
- while(1)
- {
- dis_num(0,10);
- dis_num(1,1);
- dis_num(2,10);
- i=ad();
- i=(u16)((float)i*19.6+0.5);
- dis_num(4,i/1000);
- dis_num(5,i%1000/100);
- dis_num(6,i%100/10);
- dis_num(7,i%10);
- k=scan_key();
- if(k==4)
- {
- change_V();
- }
- switch(k)
- {
- case 7:{mode=0;return 1;}break;
- case 5:{mode=2;return 1;}break;
- case 9:{mode=3;return 1;}break;
- }
- }
- }
- u16 timer=0;
- u16 zhouqi=0;
- u16 c_flag=0;
- u8 over_flag=0;
- bit menu_3() //频率周期显示
- {
- u8 k,ft=0;
- u16 f,t;
- EA=1;
- TR0=1;
- TR1=1;
- while(1)
- {
- dis_num(0,10);
- dis_num(1,2);
- dis_num(2,10);
-
- if(over_flag)
- {
- ET0=1;
- TR0=1;
- TR1=1;
- over_flag=0;
- f=c_flag*10;
- c_flag=0;
-
- }
- k= scan_key();
- if(k==4)
- ft=!ft;
- switch(k)
- {
- case 7:{mode=0;return 1;}break;
- case 6:{mode=1;return 1;}break;
- case 9:{mode=3;return 1;}break;
- }
- if(ft) //f
- {
- dis_num(3,f/10000);
- dis_num(4,f%10000/1000);
- dis_num(5,f%10000%1000/100);
- dis_num(6,f%100/10);
- dis_num(7,f%10);
- }
- else
- {
- t=1000000/f;
- dis_num(3,t/10000);
- dis_num(4,t%10000/1000);
- dis_num(5,t%10000%1000/100);
- dis_num(6,t%100/10);
- dis_num(7,t%10);
- }
- }
- }
- bit menu_4() //查询
- {
- u8 k;
- while(1)
- {
- dis_num(6,0);
- dis_num(7,read_eeprom(2));
- k= scan_key();
- if(k==4)
- {
- k=0;
- while(1)
- {
- dis_num(0,read_eeprom(3)/10);
- dis_num(1,read_eeprom(3)%10);
- dis_num(2,10);
- dis_num(3,read_eeprom(4)/10);
- dis_num(4,read_eeprom(4)%10);
- dis_num(5,10);
- dis_num(6,read_eeprom(5)/10);
- dis_num(7,read_eeprom(5)%10);
- k=scan_key();
- if((k==7)|(k==6)|(k==5)|(k==4))
- break;
- }
- }
- switch(k)
- {
- case 7:{mode=0;return 1;}break;
- case 6:{mode=1;return 1;}break;
- case 5:{mode=2;return 1;}break;
- }
-
- }
- }
- void main()
- {
- u16 i,j;
- P0=0X00;
- P2=0XA0;
- P2=0X00;
- P0=0XFF;
- P2=0X80;
- P2=0X00;
- V[0]=read_eeprom(0);
- delay_ms(10);
- V[1]=read_eeprom(1);
- DS1302_Init();
- Time0_Init();
- Timer1Init();
- Timer2Init();
- EA=1;
- while(1)
- {
- switch(mode)
- {
- case 0:menu_1();break; //shijian
- case 1:menu_2();break; //dianya
- case 2:menu_3();break; //zhouqi
- case 3:menu_4();break; //chaxun
- }
- }
- }
- //中断服务程序
- void t0int() interrupt 1 //中断入口
- {
- c_flag++;
- }
- bit t1_c=0;
- void t1int() interrupt 3
- {
- if(t1_c==0)
- t1_c=1;
- else
- {
- t1_c=0;
- ET0=0;
- TR0=0;
- TR1=0;
- over_flag=1;
- }
- }
- u8 t2_flag=0;
- void timer2_int (void) interrupt 12 //50ms *100 5s
- {
- u16 i;
- t2_flag++;
- if(t2_flag>=100)
- {
- t2_flag=0;
-
- i=ad();
- i=(u16)((float)i*19.6+0.5);
- if(i>V[0]*100)
- {
- write_eeprom(2,1);
- delay_ms(8);
- i=Read_Ds1302(0x85);
- i=((i&0xf0)>>4)*10+i&0x0f;
- write_eeprom(3,i);
- delay_ms(8);
- i=Read_Ds1302(0x83);
- i=((i&0xf0)>>4)*10+i&0x0f;
- write_eeprom(4,i);
- delay_ms(8);
- i=Read_Ds1302(0x81);
- i=((i&0xf0)>>4)*10+i&0x0f;
- write_eeprom(5,i);
- }
- if(i<V[1]*100)
- {
- write_eeprom(2,0);
- delay_ms(8);
- i=Read_Ds1302(0x85);
- i=((i&0xf0)>>4)*10+(i&0x0f);
- write_eeprom(3,i);
- delay_ms(8);
- i=Read_Ds1302(0x83);
- i=((i&0xf0)>>4)*10+(i&0x0f);
- write_eeprom(4,i);
- delay_ms(8);
- i=Read_Ds1302(0x81);
- i=((i&0xf0)>>4)*10+(i&0x0f);
- write_eeprom(5,i);
- }
- }
- }
复制代码
附:硬件整体设计如下所示:
给大家分享我收集的单片机经典程序:
|
|