出租车计价器与实现单片机电路设计报告毕业论文.doc
设计题目:出租车计价器设计与实现29 / 291. 前言本文介绍了出租车计价器系统在实际生产生活中的重要性,介绍一种以单片机STC89C52 为核心的出租车计价器的设计,阐述硬件设计过程中关键技术的处理。在出租车是城市交通的重要组成部分,行业健康和发展也获得越来越多的关注。汽车计价器是乘客与司机双方的交易准则,它是出租车行业发展的重要标志,是出租车中最重要的工具。它关系着交易双方的利益。具有良好性能的计价器无论是对广大出租车司机朋友还是乘客来说都是很必要的。因此,汽车计价器的研究也是十分有一个应用价值的。 本设计采用STC89C52单片机为主控器,实现对出租车的计价设计,输出采8段数码显示管,74LS245芯片和74LS138芯片驱动。本电路设计的计价器不但能实现基本的计价,而且还能根据白天,黑夜来调节单价,同时具有计时功能。2系统整体设计设计要求设计一款基于STC89C52单片机的出租车计价器基本功能(1)根据输入的模拟脉冲实现同步计费,起步价设为7元,每公里费用初始设为2元 (2)能够根据白天/晚上切换单价(3)具有清零功能(4)八位数码管动态显示(计费模式下4位显示路程,4位显示费用)(5)具有计时功能(6)能够在计时模式和计费模式之间切换(7)按键要求:白天/晚上切换、中断输入、清零、计时模式/计费模式切换系统功能本次设计的出租车计价器的主要功能有:金额输出、里程输出、数据复位、白天/晚上单价转换、计时等。输出采用2个4位8段共阳极数码管。计费模式下前四位显示金额,后四位显示里程,计时模式下八位全用来显示时间。设计方案本设计是由硬件设计和软件设计两部分所组成。软件设计要进行程序的编写和软件仿真;硬件设计要进行原理图设计,PCB设计,制作电路板和硬件调试等硬件设计方案:本系统的硬件设计主要包括单片机STC89C52、数据显示部分、按键单元、电源部分、RS232串口部分。在硬件设计过程中,充分利用各部件的功能,实现多功能出租车计价器的设计计价器的系统框图如图1所示:C51单片机按键输入数码管显示电路电源输入图1 总体方案方框图软件设计方案本设计采用C语言编写程序,使用KeilC51和Proteus 7 软件进行软件调试和仿真。其中的里程计算方案和金额计算方案如下:里程计算(1) 用按键输入来代替霍尔传感器对车轮检测的输出脉冲到单片机(2) 单片机对按键输入的信号进行计数,并进行路程计算。一个输入代表路程0.1km金额计算(1) 起步价初始设定为7元,并且2km不加价(2) 当路程超过2km后,开始加价。白天按2元/公里,晚上按3元/公里开始设置定时器、中断参数扫描独立键盘白天/晚上按键按下?定时器1计时清零是否按下?复位结束NO 3元/公里YES 2元/公里YES计时/计费按下?NO YES 进入计时模式图2 软件流程3.硬件设计本系统的硬件设计主要包括单片机STC89C52、数据显示电路、按键单元、电源电路部分、RS232串口电路STC89C52STC89C52主要特征 与MCS-51系列单片机产品兼容 4K字节在系统可编程Flash存储器(片具有4K字节闪速存储器) 1000次擦写周期 128Bytes的部RAM单元 4个8位I/O口,即32位可编程I/O口线 2个16位定时器/计数器 6个中断源 可编程全双工串行口 低功耗空闲和掉电模式 掉电后中断可唤醒 看门狗定时器 双数据指针 灵活的ISP在线编程功能(字或字节模式) 宽围的工作电压,VCC的允许变化围为了2.76.0V 可设置为待机状态和掉电状态 振荡器与时钟电路,全静态工作方式,时钟频率可为0Hz24MHz。具有全静态的工作方式,表明它不一定要求连续的工作时钟定时,在等待部事件期间,时钟频率可降至0。 STC89C52芯片在出厂时,闪存处于可擦除状态,各地址单元容为FFH,可随时进行编程。编程是按字节进行的。编程电压VPP有高压12V的,也有低压5V的。STC89C52的部结构框图如图3所示:STC89C52管脚结构图与管脚说明如图4所示VCC:供电电压。 GND:接地 P0口:P0口为一个8位漏级开路双向I/O口,每脚可吸收8TTL门电流。当P1口的管脚第一次写1时,被定义为高阻输入。P0能够用于外部程序数据存储器,它可以被定义为数据/地址的第八位。在FLASH编程时,P0 口作为原码输入口,当FLASH进行校验时,P0输出原码,此时P0外部必须被拉高。 P1口:P1口是一个部提供上拉电阻的8位双向I/O口,P1口缓冲器能接收输出4TTL门电流。P1口管脚写入1后,被部上拉为高,可用作输入,P1口被外部下拉为低电平时,将输出电流,这是由于部上拉的缘故。在FLASH编程和校验时,P1口作为第八位地址接收。 图4 STC89C52管脚结构图 P0.0P0.7 P2.0P2.7P2驱动P0驱动RAM地址寄存器RAMP0锁存器FPEROMP2锁存器动程序地址寄存器ACCB寄存器缓冲堆栈指针TMP1TMP2PC增加1中断、串行口和定时器ALUPCPSWPSENDPTR定时控制指令寄存器P3锁存器P1锁存器OSCP1驱动P1驱动P3.0P3.7P1.0P1.7 + 图3 STC89C52的部结构框图P2口:P2口为一个部上拉电阻的8位双向I/O口,P2口缓冲器可接收,输出4个TTL门电流,当P2口被写“1”时,其管脚被部上拉电阻拉高,且作为输入。并因此作为输入时,P2口的管脚被外部拉低,将输出电流。这是由于部上拉的缘故。P2口当用于外部程序存储器或16位地址外部数据存储器进行存取时,P2口输出地址的高八位。在给出地址“1”时,它利用部上拉优势,当对外部八位地址数据存储器进行读写时,P2口输出其特殊功能寄存器的容。P2口在FLASH编程和校验时接收高八位地址信号和控制信号。 P3口:P3口管脚是8个带部上拉电阻的双向I/O口,可接收输出4个TTL门电流。当P3口写入“1”后,它们被部上拉为高电平,并用作输入。作为输入,由于外部下拉为低电平,P3口将输出电流(ILL)这是由于上拉的缘故。 P3口也可作为AT89C51的一些特殊功能口,如表3-1所示: P3口管脚 备选功能P3.0 RXD(串行输入口)P3.1 TXD(串行输出口)P3.2 /INT0(外部中断0)P3.3 /INT1(外部中断1)P3.4 T0(记时器0外部输入)P3.5 T1(记时器1外部输入)P3.6 /WR(外部数据存储器写选通)P3.7 /RD(外部数据存储器读选通)P3口同时为闪烁编程和编程校验接收一些控制信号。表5 STC89C52部分引脚功能表 端口引脚 复用功能 P3.0 RXD(串行输入口) P3.1 TXD(串行输出口) P3.2 /INT0(外部中断0) P3.3 /INT1(外部中断1) P3.4 T0(定时器0的外部输入) P3.5 T1(定时器1的外部输入) P3.6 /WR(外部数据存储器写选通) P3.7 /RD (外部数据存储器读选通)RST:复位输入。当振荡器复位器件时,要保持RST脚两个机器周期的高电平时间。ALE/PROG:当访问外部存储器时,地址锁存允许的输出电平用于锁存地址的地位字节。在FLASH编程期间,此引脚用于输入编程脉冲。在平时,ALE端以不变的频率周期输出正脉冲信号,此频率为振荡器频率的1/6。因此它可用作对外部输出的脉冲或用于定时目的。然而要注意的是:每当用作外部数据存储器时,将跳过一个ALE脉冲。如想禁止ALE的输出可在SFR8EH地址上置0。此时, ALE只有在执行MOVX,MOVC指令是ALE才起作用。另外,该引脚被略微拉高。如果微处理器在外部执行状态ALE禁止,置位无效。 /PSEN:外部程序存储器的选通信号。在由外部程序存储器取指期间,每个机器周期两次/PSEN有效。但在访问外部数据存储器时,这两次有效的/PSEN信号将不出现 /EA/VPP:当EA保持低电平时,则在此期间外部程序存储器(0000H-FFFFH),不管是否有部程序存储器。注意加密方式1时,/EA将部锁定为RESET;当/EA端保持高电平时,此间部程序存储器。在FLASH编程期间,此引脚也用于施加12V编程电源(VPP)XTAL1:反向振荡放大器的输入与部时钟工作电路的输入XTAL2:来自反向振荡器的输出STC89C52的振荡器特性XTAL1和XTAL2分别为反向放大器的输入和输出。该反向放大器可以配置为片振荡器。石晶振荡和瓷振荡均可采用。如采用外部时钟源驱动器件,XTAL2应不接。有余输入至部时钟信号要通过一个二分频触发器,因此对外部时钟信号的脉宽无任何要求,但必须保证脉冲的高低电平要求的宽度。STC89C52最小系统单片机最小系统,是指能维持单片机运行的最简单配置的系统。这种系统成本低廉、结构简单,常用来构成简单的控制系统。复位电路单片机在启动运行时都需要进行复位操作,以便使CPU和系统中的其它部件都处于某一确定的初始状态,并从这个状态开始工作。AT89C52单片机有一个引脚RST,它是施密特触发器的输入端,其输出端接复位电路的输入。复位信号是高电平有效,其有效时间应持续24个振荡脉冲周期(即二个机器周期)以上,若使用频率为6MHz的晶振,则复位信号持续时间应超过4s才能完成复位操作。复位有电复位和手动复位两种。手动复位有电平方式和脉冲方式两种。本次设计中,采用上电复位。 复位电路连接图如图6所示:图6 复位电路振荡电路时钟电路产生的振荡脉冲经过触发器进行二分频之后,才能为单片机的时钟脉冲信号。振荡频率取决于石英晶体的振荡频率,频率围可取1.2MHz12MHz。C2、C4主要起频率微调和稳定作用,电容值可取530pF。晶体振荡频率高,则系统的时钟频率也高,单片机运行也就快,但反过来运行速度快对存储器的速度要求就高,对印刷电路板的工艺要求也高(线间寄生电容要小)。在本次设计中,选取晶振频率为12MHz,C2和C4的值均为22pF。振荡电路如图7所示图7 振荡电路电源电路部分任何电子设备都需要用直流电源供电,比较经济实用的的方法是直接使用计算机USB接口供电,其输出电压稳定,可靠性高,调试方便电源电路见图8图8 电源电路数据显示电路LED显示器介绍在单片机应用系统中,为了控制系统的工作状态,以与向系统中输入数据和信息,系统应设有按键或键盘。为了观察和监视键盘输入的信息,为了了解系统的工作情况以与得到系统完成任务的结果,系统应设有显示装置。单片机最常用的显示装置是LED显示器。图9 LED管脚配置图LED显示器原理LED显示块是由发光二极管显示字段的显示器件。在单片机应用系统常使用的是七段LED。这种显示块有共阴极和共阳极两种,如上图所示,共阴极LED显示块的发光二极管阴极共地,如图中所示,当某个发光二极管的阳极为高电平时,发光二极管点亮。共阳极LED显示块的发光二极管阳极并接,当某个二极管的阴极为低电平时,该二极管点亮。通常的七段LED显示块中有八个发光二极管,故也称为八段显示器。其中七个二极管构成七笔字型“8”,一个发光二极管构成小数点。控制不同组合的二极管导通,就能显示各种字符。设8位控制器按低到高的次序依次控制LED显示块的af和小数点dp,我们称控制器输出的控制LED显示块显示字符的 8位字节数据为段选码。共阳极与共阴极的段选码互为反码。在单片机应用系统中使用LED还可构成任意位的LED显示器。 如 8位LED显示器有8根位选线和88根段选线。每根位选线控制该位的LED的8根段选线控制该位LED显示什么字符。段选线控制显示字符的字型,而位选线控制显示位的亮、暗。显然,多位LED控制线占用太多。在多位LED显示时,为了简化电路,降低成本,将所有位LED的段选线并接在一起,在某一刻时,将要显示的字符段码同时送到每一个显示器的各段,但是只让这一位LED显示。下一时刻又送下一位LED要显示字符的段码,并只让下一位LED显示.如此轮流,使每位显示该为的字符,这样不断的循环送出响应的段选码位选码,就可以获得视觉稳定的显示状态。用单片机驱动LED数码管有很多方法,按显示方式分,有静态显示和动态(扫描)显示,按译码方式可分硬件译码和软件译码之分。静态显示就是显示驱动电路具有输出锁存功能,单片机将所要显示的数据送出后就不再管,直到下一次显示数据需要更新时再传送一次新数据,显示数据稳定,占用很少的CPU时间。动态显示需要CPU时刻对显示器件进行数据刷新,显示数据有闪烁感,占用的CPU时间多。这两种显示方式各有利弊;静态显示虽然数据稳定,占用很少的CPU时间,但每个显示单元都需要单独的显示驱动电路,使用的硬件较多;动态显示虽然有闪烁感,占用的CPU时间多,但使用的硬件少,能节省线路板空间,更重要的是能节省成本。 硬件译码就是显示的段码完全由硬件完成,CPU只要送出标准的BCD码即可,硬件接线有一定标准。软件译码是用软件来完成硬件的功能,硬件简单,接线灵活,显示段码完全由软件来处理,是目前常用的显示驱动方式。LED显示器的显示方式(1)静态方式:LED显示器工作在静态显示方式下,共阴极或共阳极点连接在一起接地或+5V;每位的段选线(a-dp)与一个8位并行口相连。如图所示,该图表示了一个四位静态LED显示器电路。该电路每一位可独立显示,只要在该位的段选线上保持段选码电平,该位就能保持相应的显示字符。由于每一位由一个8位输出口控制段选码,故在同一时间里每一位显示的字符可以各不一样。N位静态显示器要求有N*8根I/O口线,占用I/O口资源较多。故在位数较多时往往采用动态显示方法。(2)动态方式在多位LED显示时,为了简化电路,降低成本,将所有位的段选码并联在一起。由一个8位I/O口控制,而共阴点或共阳点分别由相应的I/O口线控制。显示时通过位控信号采用扫描的方法逐位的循环点亮各位数码管。动态显虽然在任一时刻只有一位数码管被点亮,但是由于人眼具有视觉暂留效应,看起来与全部数码管持续点亮的效果完全一样。本设计中主要用7段LED显示器,下面对其进行简要介绍。7段LED显示器由7条发光二极管组成显示字段,并按“日”字形排列,这7段发光管分别称为a,b,c,d,e,f,g,有的还带有一个小数点dp,7段LED由此得名,将7段发光管阴极都连在一起,称为共阴极接法,当某个字段的阳极为高电平时,对应的字段就点亮。共阳极接法是将LED显示器的所有阳极并接后连到+5V电源上,当某一字段的阴极为0时,对应的字段就点亮下面以共阴极接法说明显示字符和数字量与段编码关系。由于加在7段阳极上的电压可以用数字量表示,对于共阴极,如果某位为1,则对应段发光;如为0,则不发光。数字量与段的对应关系如表4-2所示:表10 数码管数字量与段的对应关系表D7 D6 D5 D4 D3 D2 D1 D0dpgfedcba例如:当加到阳极的数字量为00111111B=3FH时,除dp,g不发光外,其他6段均发光,因此显示一个0字符。对于共阳极接法,加到阴极的数字量为:11000000=C0H,则显示0字符。由此可见,共阳极接法的段选码与共阴极接法的段选码是逻辑“非”关系。如果采用LCD 液晶显示,在距离屏幕1 m 之外就无法看清数据,而且在白天其对比度也不能够满足要求,因此采用高亮度LED 数码管显示。当为空车时,为了节电,只显示时间,为供司机查看时间提供方便,当司机要查询以往的营运数据时,按查询键可提供显示;在乘客时显示营运的单价、等待时间、路程、金额与时钟。本设计的数码管电路如图11所示:图11 数码管显示电路按键单元本次设计的按键单元分为4个按键,分别是中断输入、白天/晚上、清零、时间模式/计费模式,每个按键都有对应的功能和作用按键电路如图12所示图12 按键电路图12 按键电路RS232串口电路通信过程中只有两个脚参与通信2脚:电脑的输入RXD 3脚:电脑的输出TXD 通过2 ,3 脚就可以实现全双工(可同时收发)的串行异步通信5脚:接地 RS232的引脚电路连接完成RS232电路见图13图13 RS232串口电路4.软件设计主程序在主程序中,需要完成对各参量和接口的初始化、出租车起步价和单价的初始化以与中断、计算、循环等工作。另外,在主程序模块中还需要设置启动/清除标志寄存器、里程寄存器和价格寄存器,并对它们进行初始化。然后,主程序将根据各标志寄存器的容,分别完成启动、清除、计程和计价等不同的操作。主程序流程图路程计数中断程序每当按键输入一个低电平信号就使单片机中断一次,路程增加0.1km,并根据白天/晚上按键的状态设定单价是2元/公里还是3元/公里,然后计算出金额 计算程序计算程序根据路程数分别进入不同的计算公式。如果路程大于2公里,则执行公式:总金额=起步价+(路程-20)*单价。白天单价2元/公里,晚上单价3元/公里显示程序显示程序利用定时器每1ms产生一次中断,相应变量置位,点亮一个数码管,显示一位数据,利用主函数的循环,实现动态扫描显示,同时根据数码管余辉和人眼暂留现象,即可实现显示。按键程序键盘采用查询的方式,放在主程序中,当没有按键按下的时候,单片机循环主程序,一旦有按键按下,便转向相应的子程序处理,处理结束再返回。5.仿真调试根据系统设计方案,本系统调试分为两部分:软件调试和硬件调试软件仿真调试编译软件使用keilC51进行软件调试和编译,编译成功后生成“Taxi.hex”文件图14 keilC51编译仿真调试在proteus 7中绘制出电路原理图,将keilC51编译生成后的“Taxi.hex”文件导入到单片机中,单机“运行”按键进行仿真图15 proteus仿真软件仿真结果图16 起步价7元,两公里不加价图17 白天2元/公里图18 晚上3元/公里图19 计时器硬件调试绘制PCB图使用altium designer 9绘制出原理图,然后转换成PCB图,进行元件布局、布线图16 PCB图电路板调试将PCB图送至公司制成PCB版,购买元器件进行焊接,焊接完成后将程序下载到单片机里进行硬件调试图20 硬件调试6.结论在这段时间里,经过自己努力,基本上完成了设计要求的容,在系统可行性分析、原理图设计、PCB绘制等方面都作了许多实际工作,取得了一些成绩,同时也遇到了一些问题,存在一些不足。经过这段时间的学习和工作,我觉得自己不论是在理论知识方面还是在动手能力方面都有了不小的进步,自己从中受益匪浅。这次设计很好的把以前学到的理论知识应用于实践,使我认识到理论知识与实践之间有一定的差距,只有通过不断的努力学习和实践才能很好的把理论知识应用到实践当中,也只有通过不断的实践才能对理论知识的理解。通过这次设计不仅学会了如何去查找相关资料,更重要的是通过查找资料和翻阅书籍学到了不少知识,扩大了知识面,提高了知识水平。经过单元设计和系统设计巩固了以前所学的专业知识,自己真正认识到理论联系实际的重要性,为以后的学习和工作提供了很多有价值的经验。通过这次设计不仅增强了自己的动脑能力和动手能力,也提高了我思考问题、分析问题、解决问题的能力,更重要的是学会用工程化的思想来解决问题。这在以前的学习过程中是不曾学到的。这次设计是我认真认识到完整、严谨、科学分析问题、解决问题的思想是多么的重要,只有拥有了科学的态度才能设计出有用的产品。另外通过本次设计,使我认识到自己理论知识的应用能力有很大的欠缺,需要在以后的学习中进一步提高。7.致在这里,我要感我的指导老师田玉敏老师在设计期间给与我的关心、指导和教诲。田玉敏老师治学严谨的作风与平易近人的态度使我受益匪浅,并且也是对我的鞭策和激励。同时我也要感我的同学们,感他们给予我的关心和帮助8.附录电路原理图程序#include<reg52.h>#include<intrins.h>#define uint unsignedint#define uchar unsignedcharsbit ACC_0=ACC0;sbit ACC_7 = ACC7; /位寻址寄存器定义sbit SCLK = P11; / DS1302时钟信号 7脚sbit DIO= P10; / DS1302数据信号 6脚sbit RST = P12; / DS1302片选 5脚sbit Start=P15;sbit Clear=P16;sbit Switch = P17;sbit key4 = P32;uchar shi1,shi2,fen1,fen2,miao1,miao2,tt0;uchar num,PRI1,PRI2,PRI3,PRI4,DIS1,DIS2,DIS3,DIS4;uchar tt =0;uchar tt0,signal;uchar Switch_a = 1;uchar Switch_b = 1;float Price; uint num1,num2,tt1;uchar code table=0x3F,0X30,0X5b,0X4f,0x66,0x6d,0x7d,0x07,0x7f,0x6f,0x00,0x40;/共阴数码管"0-9","灭","-"编码uchar code wei=0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07;/位选编码/*计费部分*/延时ms子程序void delay(uint i)uint j;for(i; i > 0; i-)for(j = 110; j > 0; j-);void Price_DistanRST_display()switch(num) /数码管显示case 1:P2=0x00;P0=tablePRI1;delay(1);break;case 2:P2=0x01;P0=tablePRI2;delay(1);break;case 3:P2=0x02;P0=tablePRI3+0x80;delay(1);break;case 4:P2=0x03;P0=tablePRI4;delay(1);break;case 5:P2=0x04;P0=tableDIS1;delay(1);break;case 6:P2=0x05;P0=tableDIS2;delay(1);break;case 7:P2=0x06;P0=tableDIS3+0x80;delay(1);break;case 8:P2=0x07;P0=tableDIS4;delay(1);break;void zhuanhuan()/数据转换DIS1=num1/1000;DIS2=num1%1000/100;DIS3=num1%1000%100/10;DIS4=num1%10;PRI1=num2/1000;PRI2=num2%1000/100;PRI3=num2%1000%100/10;PRI4=num2%10;void int1() interrupt 0/速度采集 /外部中断(INTO)if(key4 = 0)delay(20);if(key4 = 0)num1+;while(!key4);if(Switch_b = 1)Price = 2;/白天元/公里if(Switch_b = 2)Price = 3;/晚上元/公里if(num1 != 0) if(num1 < 21) num2 = 70; else num2 += Price;/两公里元,超过两公里按每公里/3元计费 void time0() interrupt 1TH0=(65536-50000)/256;TL0=(65536-50000)%256;tt0+;if(tt0=20)tt0=0;miao1+;if(miao1=10)miao1=0;miao2+;if(miao2=6)miao2=0;fen1+;if(fen1=10)fen1=0;fen2+;if(fen2=6)fen2=0;shi1+;if(shi1=10)shi1=0;shi2+; void time1() interrupt 3 /定时/计数器(T1)TH1=(65536-2000)/256;TL1=(65536-2000)%256;tt+;if(tt = 2) /20ms*2tt=0;num+;if(num = 9) /限制num围在-9num=1;if(Switch_a = 1)zhuanhuan(); /数据转换Price_DistanRST_display();if(Switch_a = 2)switch(num) /时间数码管显示case 1:P2=0x00;P0=tableshi2;break;case 2:P2=0x01;P0=tableshi1;break;case 3:P2=0x02;P0=0x40;break;case 4:P2=0x03;P0=tablefen2;break;case 5:P2=0x04;P0=tablefen1;break;case 6:P2=0x05;P0=0x40;break;case 7:P2=0x06;P0=tablemiao2;break;case 8:P2=0x07;P0=tablemiao1;break;delay(1);/*计费部分*/void main()/init1302(); /初始化EA=1; /CPU开中断 IT0=1; /下降沿触发有效 TMOD=0x11; /time0,time1,位定时器模式 TH0=(65536-50000)/256; /延时ms TL0=(65536-50000)%256; ET0=1; TR0=0; TH1=(65536-50000)/256; TL1=(65536-50000)%256; ET1=1; /允许定时器中断 TR1=1; /启动 num=0; num1=0; num2=0; Price=0;/单价初始化为EX0=1; /打开外部中断TR0=1;while(1)if(Start=0) /白天/晚上切换 delay(20);if(Start=0) Switch_b+;if(Switch_b > 2) Switch_b = 1; while(!Start); /松开检测if(Clear=0) /清零键 delay(20);if(Clear=0) return; while(!Clear); if(Switch=0) /切换键 delay(20); /防抖动if(Switch=0) Switch_a+;if(Switch_a>2)Switch_a=1; while(!Switch);