《基于单片机的出租车计价器设计毕业设计(22页).docx》由会员分享,可在线阅读,更多相关《基于单片机的出租车计价器设计毕业设计(22页).docx(22页珍藏版)》请在淘文阁 - 分享文档赚钱的网站上搜索。
1、-基于单片机的出租车计价器设计毕业设计2013年12月30日至2014年1月10日目 录第一章 绪论111 课题背景112 研究的目的和意义113 设计内容及难点1第二章 总体方案设计22. 1 方案论证22. 2 总体设计框图3第三章 系统软件设计43. 1 程序框图43. 1. 1 主程序设计43. 1. 2 设计概述43. 1. 3 主程序流程图532 子程序设计7321 显示子程序7322 键盘扫描子程序8323 延时子程序93. 2. 4 计费子程序103. 2. 5 中断子程序11第四章 keil仿真134. 1 Keil软件的介绍及使用134. 1. 1 什么是keil软件134
2、. 1. 2 怎样操作keil仿真软件13第五章 实物制作与调试165.1 电路板焊接165.2 电路板调试16第六章 心得体会17附录181、参考文献182、元件清单193、电路原理图204、实物图215、程序清单22-第 19 页题目:基于单片机的出租车计价器设计第一章 绪论11 课题背景我国在70年代开始出现出租车,但那时的计费系统大都是国外进口不但不够准确,价格还十分昂贵。随着改革开放日益深入,出租车行业的发展势头已十分突出,国内各机械厂家纷纷推出国产计价器。出租车计价器的功能从刚开始的只显示路程(需要司机自己定价,计算后四舍五入),到能够自主计费,以及现在的能够打一发票和语音提示、按
3、时间自主变动单价等功能。随着城市旅游业的发展,出租车行业已成为城市的窗口,象征着一个城市的文明程度。12 研究的目的和意义出租车计价器是乘客与司机双方的交易准则,它是出租车行业发展的重要标志,是出租车中最重要的工具。它关系着交易双方的利益。具有良好性能的计价器无论是对广大出租车司机朋友还是乘客来说都是很必要的。13 设计内容及难点 1、设计内容硬件要求:做出实物。 软件要求:需要显示起步价、单价、路程、总金额、上下车时间、中途等待时间,用8位数码管显示,运用按键的切换功能进行页式管理。2、设计难点硬件:数码管引脚的焊接复杂。软件:随时存储相应点的时间,便于后面的调用。数码管显示要正常不能闪烁有
4、重影,亮度要好。用DS1302的时钟显示编程有点复杂。还有就是个函数之间的嵌套。第二章 总体方案设计2. 1 方案论证方案一:采用数字电路控制。其原理方框图如图2所示。采用传感器件,输出脉冲信号,经过放大整形作为移位寄存器的脉冲,实现计价,但是考虑到这种电路过于简单,性能不够稳定,而且不能调节单价,也不能根据天气调节计费标准,电路不够实用。图2.1 数字电路实现框图方案二:采用单片机控制。利用单片机丰富的IO端口,及其控制的灵活性,实现基本的里程计价功能和价格调节、时钟显示功能。本方案有较大的活动空间,不但能实现所要求的功能而且能在很大的程度上扩展功能,而且还可以方便的对系统进行升级,所以我们
5、采用后一种方案。此次计价器设计的功能实现如下:左边第一个按键:按下:开始;未按下:停止;左边第二个按键:当第一个按键未按下时才起作用,用于功能选择,控制数码管;左边起第三个数码管,当数码管显示1时左边第三个按键起作用,按一下单价加一,此时按下开始按钮,开始计价;左边第四个按键:清零;右边按钮:按计价收费。2. 2 总体设计框图时钟电路89C51单片机显示路程与价钱复位电路按键控制信息储存电路图2.2 总体设计框图第三章 系统软件设计3. 1 程序框图 总程序流程框图描述:程序开始后,先对各个函数与变量进行声明,接着进行显示程序、延时程序、计价程序、中断程序的循环实现。程序开始 声明函数与变量显
6、示程序延时程序计价程序中断程序图3.1 程序总框图3. 1. 1 主程序设计3. 1. 2 设计概述在主程序模块中,需要定义各个寄存器,完成对接口芯片的初始化,出租车起步价和单价的初始化。另外,在主程序模块中还需要设置启动/消除标志寄存器、里程寄存器和价格寄存器,并对它们进行初始化。然后,主程序将根据各标志存储器的内容,分别完成启动、消除、计程和计价等不同的操作。当空车信号灯打下时,表示有乘客上车,并启动计价,将根据里程寄存器中的内容计算和判断出行驶里程是否已超过起价公里数。若已超过,则根据里程值、每公里的单价和起价来计算出当前的里程价格,并将结果存于价格寄存器中,然后将累计价格送到LED显示
7、电路显示出来。3. 1. 3 主程序流程图设计思路:对主程序进行初始化,按下K1,开计数器0,开始计费,当键松开时,停计数器0,停止计费;开始计费时,设置计数值,计满两次产生中断,关定时器,清零。开始计费同时,按下K2,功能调整键开启,单价标志位加1,当单价标志位=2时,单价标志位为0,否则为1;同时按下K3时,单价加1;按下K4,清零,显示标志位为0。开始初始化N按下K1Y停计数器1开计数器0停止计价开始计价N按下K2Y单价标志位(djflag)+1不能调节判djflag=2YNDjflag=1Djflag=0N按下K3Y显示起步价单价(dj)+1NDj=20Y显示当前单价Dj=0判按K4N
8、Y清零图 3.2 主程序设计流程图32 子程序设计321 显示子程序 显示子程序描述:此数码管是共阴极的,所以高电平有效,动态扫描显示,实现动态扫描显示,同时根据数码管余辉和人眼暂留现象,即可实现显示。首先对数码管初始化,P2口即P2.0到P2.5置零,通过调用zxscode数组的数,分别显示到数码管的6个数码管上,此为送片选码,此时,(每当输入一个低电平),点亮一个数码管;然后P0口通过调用xscode数组的数,(输入的脉冲为高电平时),显示在每个数码管A、B、C、D、E、F、G上,相应数字显示出来,完成送段码,如此循环显示。 开始 数码管初始化显示送段码调用xscode数组调用zxscod
9、e数组 送片选码 图3.3 显示子程序流程图 程序见附录 322 键盘扫描子程序键盘扫描子程序描述:键盘采用查询的方式,放在主程序中,当没有按键按下的时候,单片机循环主程序,一旦右按键按下,便转向相应的子程序处理,处理结束再返回。通过键盘的控制切换显示功能,K1,K2,K3分别表示起步价、单价,调节位,调节单价位。增设K4用于清零,K5用于表示总里程和总金额。按下按键同时需要执行按键消抖功能,保证按键被真的按下。此时K1、K2、K3、K4、K5键扫描方式相同,以K1为例,流程图如下:开始调用相应函数或赋值记数判断K1是否真的按下N判断K1是否按下按键去抖YNY结束图3.4 键盘扫描子程序流程图
10、程序见附录323 延时子程序延时程序如下:uint i,j;for(i=xms;i0;i-)for(j=110;j0;j-);这是一个for的嵌套语句,因为两个语句之间没有分号,所以编译器默认第二个for语句是第一个for语句的内部语句,就是说第一个for中的 i 减1一次,那第二个for中的语句将会执行110次,这个110其实是根据所用单片机的晶振频率来计算的,在这个程序当中,单片机的晶振频率虽然标的是12M,实际上应该是11.0592兆Hz,所以第二个for语句执行110次的时间大概就是100us,乘上第一个for中的 i 的初值就得到延时的时间了,这里的延时5ms,定义 i 的数据类型为
11、unsigned int i,然后j的数据类型不变,给 i 赋值50即可。有用到的公式:1、时钟周期即晶振的单位时间发出的脉冲数,12MHz=12*10的6次方,即每秒发出12000000个脉冲信号,那么发出一个脉冲的时间就是时钟周期,即1/12微秒。2、一个机器周期等于12个时钟周期,所以是1微秒。延时子程序的描述:延时开始后,执行键盘扫描功能,判断相应的键盘是否被按下,中间延时达到按键消抖的目的,确保按键是否真的被按下,如果真的按下,执行相应的按键,显示出按键的相应功能。流程图如下:开始扫描键盘是否有键盘按下并判断键号YN再次判断相应键是否被按下功能调整调节数据清零NY里程输入延时5ms图
12、3.5 延时子程序流程图程序见附录3. 2. 4 计费子程序 计费子程序描述:开始计价后,如果按下K5,计算程序根据里程数分别进入不同的计算公式,计费方案如下: KK=2时,JKK=起步价=4元; 2KK=35时,JKK=4+dj*(KK-2)+1; 35KK900时,JKK=4+2*dj*(KK-2)+1。最后显示出当前费用。计价开始N判按下K5Y不进行计价里程(KK)NN35KK=9002KK=35KK=2YYYJKK=4+2*dj*(KK-2)+1JKK=4JKK=4+dj*(KK-2)+1显示费用图3.6 计费子程序流程图程序见附录3. 2. 5 中断子程序中断子程序描述:作为基本组成
13、内容,51单片机共有两个可编程的定时器计数器,分别称定时器计数器0和定时器计数器1。它们都是十六位加法计数结构,分别由TH0和TL0及TH1和TH1两个8位计数器组成。1、计数功能所谓计数是指对外部事件进行计数。外部事件的发生以输入脉冲表示,因此计数功能的实质就是对外来脉冲进行计数。51芯片有T0(P3.4)和T1(P3.5)两个信号引脚,分别是这两个计数器的计数输入端。外部输入的脉冲在负跳变时有效,进行计数器加1(加法计数)。2、定时功能定时功能也是通过计数器的计数来实现的,不过这时的计数脉冲来自单片机的内部,既每个机器周期产生一个计数脉冲。也就是每个机器周期计数器加1。由于一个机器周期等于
14、12个振荡脉冲周期,因此计数频率为振荡频率的112。此出租车计价器单片机采用12MHZ晶体,则计数频率为1MHZ。即每微秒计数器加1。当计数器0中断服务时,中断标志位加1,当中断产生二次后,路程加1公里并清中断标志位。图 3.7 中断子程序流程图程序见附录第四章 keil仿真4. 1 Keil软件的介绍及使用4. 1. 1 什么是keil软件Keil C51是美国Keil Software公司出品的51系列兼容单片机C语言软件开发系统,与汇编相比,C语言在功能上、结构性、可读性、可维护性上有明显的优势,因而易学易 用。Keil提供了包括C编译器、宏汇编、连接器、库管理和一个功能强大的仿真调试器
15、等在内的完整开发方案,通过一个集成开发环境、将这些部分组合在一起。运行Keil软件需要WIN98、NT、WIN2000、WINXP等操作系统。如果你使用C语言编程,那么Keil几乎就是你的不二之选,其方便易用的集成环境、强大的软件仿真调试工具也会令你事半功倍。4. 1. 2 怎样操作keil仿真软件我使用的keil软件是keil uvision4版本的,protues仿真前要通过工程选项,在output选项卡把生成.HEX文件勾选上,然后编译生成.HEX文件供protues软件仿真使用。延时子程序的调试如图4.1:图4.1 延时子程序的调试显示子程序的调试如图4.2:图4.2 显示子程序的调试
16、计费子程序的调试如图4.3: 图4.3 计费子程序的调试中断子程序的调试如4.4:图4.4 中断子程序的调试程序见附录第五章 实物制作与调试5.1 电路板焊接一般来说,造成硬件问题的首要问题就是焊接了,也就是说焊接的好与坏直接响产品的正常运行。造成焊接质量不高的常见原因是:焊锡用量过多,形成焊点的锡堆积;焊锡过少,不足以包裹焊点。冷焊。焊接时烙铁温度过低或加热时间不足,焊锡未完全熔化、浸润、焊锡表面不光亮(不光滑),有细小裂纹(如同豆腐渣一样!)。夹松香焊接,焊锡与元器件或印刷板之间夹杂着一层松香,造成电连接不良。若夹杂加热不足的松香,则焊点下有一层黄褐色松香膜;若加热温度太高,则焊点下有一层
17、碳化松香的黑色膜。对于有加热不足的松香膜的情况,可以用烙铁进行补焊。对形成的黑膜,要吃净焊锡,清洁被焊元器件或印刷板表面,重新进行焊接才行。焊锡连桥。指焊锡量过多,造成元器件的焊点之间短路。这在对超小元器件及细小印刷电路板进行焊接时要尤为注意。焊剂过量,焊点明围松香残渣很多。当少量松香残留时,可以用电烙铁再轻轻加热一下,让松香挥发掉,也可以用蘸有无水酒精的棉球,擦去多余的松香或焊剂。焊点表面的焊锡形成尖锐的突尖。这多是由于加热温度不足或焊剂过少,以及烙铁离开焊点时角度不当浩成的内。5.2 电路板调试 最小系统的电路不工作,首先应该确认电源电压是否正常。用电压表测量接地引脚跟电源引脚之间的电压,
18、看是否符合电源电压,常用的是5V左右。接下来就是检测复位引脚的电压是否正常,EA引脚的电压要正常为5V左右。如果补焊电源后最小系统还是不能工作,有可能是AT89C52单片机坏掉了,重新选择一个AT89C52单片机焊接。如果是工作但是不能按需要的功能执行,也可用更换AT89C52单片机方法调试,但在此之前可以选择检查对应的模块是否有焊接问题,若没有再进行更换。实物图见附录4第六章 心得体会 实践是检验真理的唯一标准,实践也是检验我们学习成果的一种非常有效的办法。 在硬件设计方面我们需要考虑整体电路板的布局,元器件的摆放得当可以在一定程度上帮我们节约成本,导线的合理走线是使电路板美观,便于调试的有
19、效途径。当然焊接基本功是必须得有的,不可以在一个焊点上反复焊接,即使要焊多次也必须有一定的时间间隔。 软件编程是此次课程设计的重点也是难点。软件包括;键盘子程序、显示子程序、单片机的初始化子程序及DS1302时钟调用子程序。每一个子程序的编写都需要我们对相应芯片功能的理解,比如,如何让数码管正常显示就是一个不小的工程,我么要考虑消隐、防抖等功能。如果之前对单片机没有一点了解或是没有动手编过一些小程序的话,面对这些问题还是有点小麻烦的。在做实物或是编写程序之前可以查找一些书籍资料,对于一些小程序我们可以平时就积累在自己的电脑上,到用时可以直接调用。 软硬件的结合是每一个单片机工程师必备的素质,只
20、会硬件而不懂得软件编程的话,学习单片机永远达不到至高境界,如果只是埋头编程而不动手实践的话,是无法尝到其中无穷乐趣的。附录1、参考文献1、戴胜华,蒋大明单片机原理与应用北京:清华大学出版社20052、李刚新概念单片机教程天津:天津大学出版社20043、王宗和单片机实验与综合训练北京高等教育出版社 20004、李广弟,朱月秀,冷祖祁.单片机基础M.第3版.北京航空航天大学出版社,20075、李群芳,肖看.单片机原理接口与应用.北京:清华大学出版社,20052、元件清单序号文字标号名称数量规格型号备注1R9电阻器11K2R10电阻器12003R2、R3电阻器210K4C1、C2电容230pf无极性
21、5C3电容110uf有极性6U1单片机1AT89C517U3单片片1AT24C028U2单片片174LS2459LED显示器1GN-5461AH9SW1-SW8按钮5TD-03B10START等按钮1TD-03B12X1晶振1UM-514RP1排阻1控制电源157805稳压管13、电路原理图4、实物图5、程序清单 #include /#include #include #define uchar unsigned char#define uint unsigned intint xscode6=0x3f,0x06,0x5b,0x4f,0x66,0x6d;/显示存储区int zxscode6=0
22、x1f,0x2f,0x37,0x3b,0x3d,0x3e;/共阴显示片选码int codetab=0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7f,0x6f;/共阴极数码int i,j,flag;uchar sec;int kk=0;/路程标志位int jkk=0;/费用int jflag=0;/费用标志位int kflag=0;/路程标志位int zdflag=0;/中断标志位int kilo=0;/路程int dj=1;/路程单价 int djflag=0;/路程单价标志sbit key1=P10;sbit key2=P11;sbit key3=P1
23、2;sbit key4=P13;sbit key5=P34;sbit SDA=P31; /IIC引脚sbit SCL=P30;void delay()void delay1 (xms)/延时程序子程序 uint i,j; for(i=xms;i0;i-) for(j=110;j0;j-); void start() /IIC开始位 SDA = 1; SCL = 1; delay(); SDA = 0; delay();void stop() / IIC停止位 SDA = 0; delay(); SCL = 1; delay(); SDA = 1; void respons() /IIC应答位
24、uchar i; SCL=1; delay(); while(SDA=1)&(i250) i+; SCL=0; delay();void init() SDA=1; delay(); SCL=1; delay();uchar read_byte() / 从EEPROM读到MCU uchar i,j; for(i=0;i8;i+) SCL=1; j=1; j|=SDA; SCL=0; return(j);void write_byte(uchar date) / 从MCU写到EEPROM uchar i,temp; temp=date; for(i=0;i8;i+) temp=temp1; SC
25、L=0; delay(); SDA=CY; delay(); SCL=1; delay(); SCL=0; delay(); SDA=1; delay();void write_data(uchar addr, uchar date) / 在指定地址addr处写入数据date start(); write_byte(0xa0); respons(); write_byte(addr); respons(); write_byte(date); respons(); stop();uchar read_data(uchar addr) / 在指定地址addr读取数据 uchar date; st
26、art(); write_byte(0xa0); respons(); write_byte(addr); respons(); start(); write_byte(0xa1); respons(); date=read_byte(); stop(); return date; void xianshi()/显示程序子程序 for(flag=0;flag6;flag+) P0= xscodeflag;/送显示码 P2= zxscodeflag;/ 送片选码 delay1(2);P0=0; void jijia()/计费子程序 if(kk2&kk35&kk900) jkk=4+2*dj*(k
27、k-2)+1; kflag=kk/100;/路程百位 jflag=jkk/100;/路费百位 xscode2=codetabkflag; xscode5=codetabjflag; kflag=kk/10;/路程十位 jflag=jkk/10;/路费十位 xscode1=codetabkflag; xscode4=codetabjflag; kflag=kk%10;/路程个位 jflag=jkk%10;/路费个位 if(kflag=0)kflag=2;/不足两公里时,显示两公里 xscode0=codetabkflag; xscode3=codetabjflag;void qingling()
28、 for(i=0;i20) sec=20;dj=sec; TL0=(65536-2)%256 ;/计数值设置,记满两次产生中断 TH0=(65536-2)/256 ; TMOD=0x06; EA=1; ET0=1; TR0=0;/关定时器 kilo=0; qingling(); aa: if(key1=0)/当键按下去,开始计费 TR0=1;/开计数器0kk=kilo;jijia(); if(key1=1)/当键松开,停止计费TR0=0;/停计数器1 if(key2=0)/功能调整键 delay1(10);/延时判断键是否松开 if(key2=0) while(key2=0); djflag+
29、; if(djflag=2) djflag=0; xscode2=codetabdjflag; xscode1= codetabdj/10%10; xscode0= codetabdj%10; /当p1.2口的按键按下时功能标志位加一 if(key3=0&djflag=1)/当功能键标志位等1时,改变每公里的价钱 delay1(10); if(key3=0) while(key3=0); dj+;if(dj=20)dj=0;write_data(2, dj); xscode1= codetabdj/10%10 ;/把价钱十位送显示区,单价不能超100 xscode0=codetabdj%10; if(key4=0)/有键按下,清显示,单价会初始值,单价标志位清零 qingling(); dj=1; djflag=0;xianshi();/调显示子程序goto aa; void Timer0_Int() interrupt 1 using 2 / 计数器0中断服务 zdflag=zdflag+1;/中断标志位加一 if(zdflag=2)/当中断产生二次后,路程加一公里并清中断标志位 zdflag=0; kilo=kilo+1;
限制150内