出租车计价器的设计
摘要:出租车计价器的硬件设计以STC89S52单片机为核心控制元件,利用灵敏的光电传感器对车轮的转数进行采集,从而对行驶距离进行测量,输出采用LCD1602液晶显示器,可以显示路程、金额、时间等信息,温度控制芯片采用体积微小,封装形式多样的DS18B20芯片。通过按键实现总价、路程及时间的切换显示。采用两种计价模式,区分白天黑夜计价,使该计价器的设计更加合理化。本次所设计出的出租车计价器在原有的基础上增加了语音播报及温度控制的功能,给乘客营造了一个舒适、温馨的乘车环境。
关键词:STC89S52单片机;ST181光电传感器;LCD1602显示
The design of the meter taxi
Abstract: the hardware design of the meter taxi STC89S52 single-chip microcomputer as the core control components, the use of sensitive photoelectric sensor acquisition of revolution of the wheel to measure distance, output using LCD1602 LCD display, can show the information such as distance, time, amount, temperature control chip with small volume, packaging forms of DS18B20 chips. By changing the keys to achieve price, distance and time display. Using two kinds of pricing mode, to distinguish between day and night and make the streamline the design of the meter. Designed by the taxi meter on the basis of original increased the function of speech broadcast and temperature control, passengers travelling create a comfortable, warm environment.
Key words: STC89S52 microcontroller; ST181 photoelectric sensor; LCD1602 display
目 录
1引言 ...................................................................................................................................................... 1
2系统硬件的设计 .................................................................................................................................. 1
2.1 系统指标要求及工作任务 ..................................................................................................... 1
2.2 系统设计方案选择 ................................................................................................................. 2
2.3 系统工作框图 ......................................................................................................................... 2
2.4 STC89S52单片机 .................................................................................................................... 2
2.4.1 复位电路 ..................................................................................................................... 3
2.4.2 晶振电路 ..................................................................................................................... 3
2.4.3单片机最小系统 .......................................................................................................... 3
2.5 测距单元的设计 ..................................................................................................................... 4
2.6 显示电路的设计 ..................................................................................................................... 5
2.6.1 显示电路方案选择 ..................................................................................................... 5
2.6.2 1602液晶显示器的概述 ............................................................................................ 5
2.7按键电路的设计 ...................................................................................................................... 6
2.8时钟电路的设计 ...................................................................................................................... 7
2.9发声电路的设计 ...................................................................................................................... 7
3 软件设计 ............................................................................................................................................. 7
3.1软件程序内容 .......................................................................................................................... 7
3.2程序流程图 .............................................................................................................................. 8
3.2.1 总流程图 ..................................................................................................................... 8
3.2.2 按键控制部分 ............................................................................................................. 8
4 系统调试 ............................................................................................................................................. 9
4.2 硬件调试 ......................................................................................................................... 9
4.2 程序调试 ......................................................................................................................... 9
5.结束语 ................................................................................................................................................ 10
参考文献 ............................................................................................................................................... 11 致谢 ....................................................................................................................... 错误!未定义书签。
附录 ....................................................................................................................................................... 12
1引言
随着我国经济的迅速发展,人们生活的显著提高,城市的交通日趋完善,出租车计价器的应用领域也越来越广泛,虽然私家车的拥有量在大幅度提升,但是出租车在运输行业中还是担当着非常重要的角色,而出租车计价器是出租车必不可少的一部分,传统的计价器已经不能满足人们越来越高的要求,随着集成电路大规模的发展,产生了第三代计价器,也就是全电子计价器,这不仅性能稳定、计价准确,同时也方便了出租车行业的管理。
出租车计价器的功能在不断的完善,当单片机出现并应用于计价器后,现代计价器的模型也就基本具备了,它可以实现记程、计价、显示等基本功能,国内出租车计价器已经经历了三个阶段的发展。从传统的全部有机械元器件组成的机械式,到半电子式即用电子线路代替部分机械元器件的出租车计价器;再从集成电路式到目前的单片机系统设计的出租车计价器。出租车计价器计费是否准确、出租车司机是否超速才是乘客最关心的问题,而计价器营运数据管理是否方便才是出租车司机最关注的。计价器作为出租车的一个重要组成部分,关系着出租车司机和乘客双方利益,起着重要的作用,因此,具有良好性能的计价器对广大出租车司机朋友来说是很必要的。
2系统硬件的设计
系统硬件电路设计包括光电传感器、按键电路设计、时钟电路设计、温度电路设计、发音电路设计、显示电路设计。
2.1 系统指标要求及工作任务
根据出租车计价器的多功能以及智能化要求,设计本产品的主要指标要求为:
(1)里程的计算:光电传感器对车轮进行信号检测,产生并输出脉冲信号到单片机;单片机对传感器输出的脉冲信号进行计数,并以km计算:每一个信号代表轮胎旋转一周,设轮胎的周长为1.2m ;每km产生的信号数为N ,里程显示为N × 1.2m = M(km);
(2)设定的收费标准:起步价9元,3km后2元/km,等待2元/5min;
(3)具有数据的复位功能;
(4)数据的输出:总金额输出(4位)和路程输出(4位)
(5)按键:启动开关和调节功能。
发挥部分:(1)增加了语音播报部分,在乘客上下车时自动产生简单的问候语,给乘客创造一个温馨的乘车环境;(2)使用继电器自动调节温度,使车内温度保持在人体的最适温度。
工作任务:本次设计的出租车计价器能够实现金额输出、路程输出、数据复位、计时计价、自动调温、语音播报等功能。输出采用2个4位8段共阳极数码管,车辆行走时前四位显示金额,后四位显示路程。
2.2 系统设计方案选择
系统设计的方案选择主要从两大方面考虑,即硬件电路设计和软件设计。硬件设计主要设计电路、硬件仿真和电路板;软件主要进行程序的编写和软件的仿真,要做到代码的精简、准确、易读懂,因此以C语言为编程语言。最后通过硬软件的结合实现计价器的基本功能。
2.3 系统工作框图
本系统的硬件设计主要包括单片机STC89S52、数据显示部分、里程计算及计价单元的设计。在硬件设计的过程中,充分利用个各件的功能,实现多功能的出租车计价器。
计价器的系统框图如图2-1所示,主要由STC89S52单片机、测距电路部分、时钟电路部分、显示电路部分、按键电路部分、温度电路部分、发声电路部分等组成。利用单片机丰富的IO端口及其控制的灵活性,实现基本的里程和价格的计算及显示功能,而且还可以方便的对系统进行升级。
图2-1 系统工作框图
2.4 STC89S52单片机
STC89S52为ATMEL所产生的一种低功耗、高性能CMOS8位微控制器,具有8K在系统可编程Flash存储器。晶片内部具有时钟振荡器,32个可编程I/O口线;
三个16位定时/计数器;全双工UART串行通道;STC89S52资料众多,编程与51兼容;支持ISP下载,方便使用;可靠性较高。
2.4.1 复位电路
复位电路是使单片机的CPU或系统中的其他部件处于某一确定的初始状态,并从这种状态开始工作。通常单片机复位电路有两种:上电复位电路和按键复位电路。上电复位电路:是单片机上电时复位操作,保证单片机上电后立即进入规定的复位状态。它利用的是电容充电的原理来实现的。按键复位电路:它不仅具有上电复位电路的功能,同时它的操作比上电复位电路的操作要简单的多。如果要实现复位的话,只要按下RESET键即可。它主要是利用电阻的分压来实现的。在此设计中,采用按键复位电路。
2.4.2 晶振电路
晶振电路用于产生单片机工作所需要的时钟信号,而时序所研究的是指令执行中各信号之间的相互关系。单片机本身就如一个复杂的同步时序电路,为了保证同步工作方式的实现,电路应在唯一的时钟信号控制下严格地工作。
2.4.3单片机最小系统
8KB ROM ,采用Flash STC89C52 在本系统中,有几个特殊引脚需要处理,分别是:第20引脚VSS接地,第40引脚VCC接高电平,第19、18引脚XTAL1、XTAL2要接外部晶振,第9引脚RST要
接复位电路,第31引脚EA接高电平。
单片机要正常运行,必须具备一定的硬件条件,其中最主要的是三个基本条件:
(1)电源正常;(2)时钟正常;(3)复位正常。
2.5 测距单元的设计
本次出租车计价器测距期间选用的是光电传感器。光电传感器是通过把光强度的变化转化成电信号的变化来实现控制的。通过对车轮的转数进行采集从而对行驶距离进行测量,具有非接触、响应快、性能稳定等优点,所以在现在的微电子领域选用的特别多。
光电式传感器它除能测量光强之外,还能利用光线的透射、遮挡、反射、干涉等测量多种物理量,如尺寸、位移、速度、温度等,因而是一种应用极广泛的重要敏感器件。光电测量时不与被测对象直接接触,光束的质量又近似为零,在测量中不存在摩擦和对被测对象几乎不施加压力。因此在许多应用场合,光电式传感器比其他传感器有明显的优越性。
通过对光电效应和器件原理的研究已发展了多种光电器件(如光敏电阻、光电二极管、光电三极管、场效应光电管、雪崩光电二极管、电荷耦合器件等),适用于不同的场合。光电式传感器的制造工艺也随薄膜工艺、平面工艺和大规模集成电路技术的发展而达到很高的水平,并使产品的成本大为降低。被称为新一代摄像器件的聚焦平面集成光敏阵列正在取代传统的扫描摄像系统。光电式传感器的最新发展方向是采用有机化学汽相沉积、分子束外延、单分子膜生长等新技术和异质结等新工艺。光电式传感器的应用领域已扩大到纺织、造纸、印刷、医疗、环境保护等领域。在红外探测、辐射测量、光纤通信,自动控制等传统应用领域的研究也有新发展。 在本次出租车计价器的设计中,光电传感器是通过对车轮的转数进行采集从而对行驶距离进行测量的.测距电路如图2-3所示。
图2-3 测距电路
2.6 显示电路的设计
2.6.1 显示电路方案选择
方案一:采用LCD1602液晶显示器作为显示模块。
LCD1602液晶显示器功耗低、体积小、显示内容丰富、超薄轻巧、占用单片机I/O口少等诸多优点,在袖珍式仪表和低功耗应用系统中得到越来越广泛的应用。 方案二:采用LED数码管作为显示模块。
采用LED数码管占用单片机I/O口较多,数码管显示时采用动态扫描功耗较低,显示清楚、易于辨认、程序编写简单,价格低等。缺点是显示信息量较少,不能显示符号。
综合考虑,由于LCD1602液晶显示器在显示以及方便携带等诸多方面都占有很大的优势,所以决定选择方案一。
2.6.2 1602液晶显示器的概述
液晶显示模块已作为很多电子产品的通过器件,如在计算器、万用表、电子表及很多家用电子产品中都可以看到,显示的主要是数字、专用符号和图形。1602型LCD显示模块具有体积小,功耗低,显示内容丰富等特点。1602型LCD可以显示2行16个字符,有8位数据总线D0-D7和RS,R/W,EN三个控制端口,工作电压为5V,并且具有字符对比度调节和背光功能。1602型LCD基本操作程序如表2-1所示。
表2-1 LCD1602基本操作程序
1602型LCD主要技术参数:
·显示容量:16×2个字符
·芯片工作电压:4.5—5.5V
·工作电流:2.0mA(5.0V)
·模块最佳工作电压:5.0V
·字符尺寸:2.95×4.35(W×H)mm
1602型LCD的接口信号如表2-2所示。
表2-2 LCD1602接口信号
2.7按键电路的设计
方案一:采用4个独立式按键。
如果设置过多按键,将会占用较多I/O口,而且会给布线带来不便,因此,此方案适用于按键较少的情况。如果选择此方案,由于按键较少,在修改时间或设置闹铃时间时就不能直接输入,只能通过加或减完成,稍为麻烦一些,但其程序简单。只占用4个单片机I/O口。
方案二:采用4×4矩阵式键盘。
如果选择此方案,那么在修改时钟或设置闹铃时间时就可以直接从键盘输入,方便、快捷,但程序较为复杂,且需占用8个单片机I/O口。
由于并不需要经常修改时间和设置闹铃时间,而且方案一的程序简单,按键少、成本低,因此,选择方案一。
图2-4按键电路
2.8时钟电路的设计
时钟电路是外部时钟和内部时钟组成。内部是由单片机本身及外部12MHZ的晶振和两个电容构成工作主频时钟电路,这样外电源断开时钟也不会停止。
图2-5时钟电路
2.9发声电路的设计
发音部分是通过三极管放大驱动蜂鸣器工作,再通过软件这时产生等时时间方波驱动蜂鸣器发出间断嘀声,这样就可以省去硬件振荡电路,降低成本。
图2-6 蜂鸣器驱动电路
3 软件设计
3.1软件程序内容
本系统的软件设计主要可分为主程序、里程计价中断服务程序、停车计时中断
服务程序、显示子程序和独立按键控制程序五大模块。程序是用C语言编写的。用C语言编写MCS-52单片机程序与用汇编语言编写MCS–52单片机程序不一样,用汇编语言编写MCS–52单片机程序必须要考虑其存储器结构,尤其必须考虑其片内数据存储器与特殊功能寄存器的使用以及按实际地址处理端口数据。用C语言编写的MCS–52单片机应用程序,则不用像汇编语言那样须具体组织、分配存储器资源和处理端口数据,但在C语言编程中,对数据类型与变量的定义,必须要与单片机的存储结构相关联,否则编译器不能正确地映射定位。
3.2程序流程图 3.2.1 总流程图
本次设计的出租车计价器的总流程图主要分为定时器初始化、温度调节、运行、暂停、结束时通过数据处理显示出路程和总价。
图3-1总流程框图
3.2.2 按键控制部分
单片机中应用的键盘一般是由机械触点构成。当键未被按下时,引脚输入信号为高电平;当键按下后,引脚输入信号为低电平。由于按键式机械触点,当机械触点断开、闭合时,触点将有抖动,单片机检测到按了多次键,产生非预期的结果。所以,需要用软件消抖法来避免抖动的影响,即当检测到按键按下后加一段延时后,再判断按键是否按下,如果仍为低电平即按键确实按下。
图3-2按键模块软件框图
4 系统调试
4.2 硬件调试
本设计我们通过烧写器将源程序输入到集成开发板和仿真实验仪的单片机芯片上,对系统进行硬件仿真的调试,并记录调试的结果和测试数据。此外,我们还购买了设计需要使用的元器件,在实验箱上进行电路仿真,检测设计的电路能否实现出租车计价器的功能。 4.2 程序调试
启动KEIL软件,新建一个工程文件,并保存为LED文件。新建一个NEW FILE文件保存为led_main.ASM,然后再将led_main.ASM文件添加到source group1文件上,然后单击close。最后将程序添加在编辑框里,点保存。编译程序:点击―项目/全部编译‖,如出现错误,则修改程序,再重复以上步骤,直到编译成功。将编译好的程序烧写到芯片中。接上电源,刚开始的时候除了不能显示其他的功能都能实现,经过多次修改软件最终基本能正常显示。
5.结束语
出租车计费器系统的设计已经全部完成,能按预期的效果进行模拟汽车启动,停止,暂停等功能并能够通过LCD显示车费数目。本款出租车计价器包括单价输出、路程输出、显示当前的系统时间等功能。另外,多功能出租车计价器还具有性能可靠、电路简单、成本低、实用性强等特点,加上经过优化的程序,使其有很高的智能化水平。
两个月来,经过自己努力,基本上完成了设计要求的内容,在系统可行性分析、原理图设计等方面都作了许多实际工作,取得了一些成绩,同时也遇到了一些问题,存在一些不足。经过这两个月的学习,我觉得自己不论是在理论知识方面还是在动手能力方面都有了很大的进步,自己从中受益匪浅。这次设计很好的把以前学到的理论知识应用于实践,使我认识到理论知识与实践之间有一定的差距,只有通过不断的努力学习和实践才能很好的把理论知识应用到实践当中,也只有通过不断的实践才能对理论知识的理解。
通过这次设计不仅学会了如何去查找相关资料,更重要的是通过查找资料和翻阅书籍学到了不少知识,扩大了知识面,提高了知识水平。经过单元设计和系统设计巩固了以前所学的专业知识,自己真正认识到理论联系实际的重要性,为以后的学习和工作提供了很多有价值的经验。通过这次设计不仅增强了自己的动脑能力和动手能力,也提高了我思考问题、分析问题、解决问题的能力,更重要的是学会用工程化的思想来解决问题。这在以前的学习过程中是不曾学到的。
这次设计是我认真认识到完整、严谨、科学分析问题、解决问题的思想是多么的重要,只有拥有了科学的态度才能设计出有用的产品。另外通过本次设计,是我认识到自己理论知识的应用能力有很大的欠缺,需要在以后的学习中进一步提高。
参考文献
[1]唐继贤.51单片机工程应用实例[M].北京. 北京航空航天大学出版社,2009.1 [2]王东锋,王会良,董冠强.单片机C语言应用100例[M].2009.02,254-284
[3]欧阳红,李仲秋.电子产品设计与制作知道教程[M]. 北京.清华大学出版社, 2012.3 [4]万隆.单片机原理与实例应用[M].北京.清华大学出版社, 2011.1
[5]高吉祥,库锡树.电子技术基础实验与课程设计[M].北京.电子工业出版社,2011.4 [6]楼然苗,李光飞.单片机课程设计指导[M].北京航空航天大学出版社,166-169 [7]李学海.PIC单片机实用教程:基础篇(第2版) [M].北京航空航天大学出版社,2007.02 [8]贺敬凯,刘德新等.单片机系统设计、仿真与应用[M]. 西安.西安电子科技大学出版社,2011.2
[9]肖位初,陈伟宏,杨明.基于单片机的多功能出租车计价器的设计[J].现代电子技术,2008.8.10
[10]何燕媚.出租车计价器安全计量的研究与设计[J].低碳世界,2014.6.8 [11]杨许.基于单片机控制的新型数显计价器电路设计[J].价值工程,2012.11.18
[12] 周永超,李志广,张辉,张志东.液晶显示出租车计价器设计[J].现代显示,2012.12.5 [13]王素芹.基于单片机的出租车计价器的设计[J].电子世界,2011.12.1
[14]王倩,许永生.出租车计价器的硬件设计[J].信息与电脑(理论版),2010.2.15 [15]赵建琳.简易出租车计价器的设计及实现[J].河南科技,2013.12.19
附录
1、电路原理图
2、系统仿真图
3、程序
//*******************************************
//******************************************* #include #include"temp.h" #include"ds1302.h"
#define uchar unsigned char
#define uint unsigned int
sbit rw=P2^6;//读或写 sbit rs=P2^7;//
sbit en=P2^5;//读写时能控制端 sbit b=P0^7;//液晶判断忙标志位 sbit beep=P2^2;
sbit dianji=P1^4; sbit huoer=P3^2;
void lcd_init();//
void wr_com(uchar command);//液晶写命令 void wr_data(uchar data0);//写数据 void lcd_clear();//液晶清屏
void lcd_set();//设置液晶的起始位置 void busy();//液晶判忙函数 void display();//显示
void printstring(uchar *s);//直接写字符 void display1(); void key1(); sbit K=P1^0; //sbit K1=P1^1; sbit K2=P1^1; sbit K3=P1^2; sbit K4=P1^3; sbit kt=P2^3; sbit nq=P2^4;
bit f_start;//开始标志位
bit jump_in;//跳入开始标志位 bit jump_out;//跳出标志位 void key();
uchar code table[]={0x30,0x31,0x32,0x33,0x34,0x35,0x36,0x37,0x38,0x39,0x70};//字符1,2,3,,,,,0
uchar dispbuf[]={0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}; uchar dispbuf1[]={0,0,0,0,0,0,0,0,0,0,0,0,0,0,0};
uchar v,v1;//按键次数累加变量 uchar i;
uchar hr_count=0; int temp1;
void init();//
void chuli();// void chuli1();//
void delay(uchar t);// void clear();//
void set(uchar x);// void set1(uchar y);// uchar command;//
uchar count,count1;//
uchar second,minite,second1,minite1;// unsigned int tt,tt1;// float lucheng=0.0;
unsigned char value1=90,value2=20,value3=20;//起始价,运行价,等待价 unsigned int money;//金额变量
void hr_init(void) { IT0=1;//下降沿触发 EX0=0;//打开中断0允许//EX0=1;//打开中断0允许 huoer=1;//初始化端口 }
//******************************************* void main() {
// int temp; float tp; init(); hr_init(); lcd_init(); Ds1302Init(); while(1) {
Ds1302ReadTime(); if((((TIME[2]/16*10+(TIME[2]&0x0f))>=6)&&(TIME[1]/16*10+(TIME[1]&0x0f))>0)||((TIME[2]/16*10+(TIME[2]&0x0f))
key1(); // lcd_init(); chuli(); display(); if(jump_in==1) {
jump_in=0; lcd_init(); while(1) {
key(); chuli1(); display1(); if(jump_out==1) { lcd_init(); jump_out=0; clear(); break; } // float tp; temp1=Ds18b20ReadTemp(); if(temp1
//后面的数自动去掉,不管是否大于0.5,而+0.5之后大于0.5的就是进1了,小于0.5的就 //算加上0.5,还是在小数点后面。 } if(temp1>350) { kt=0; } else { kt=1; } if(temp1
//******************************************* void clear()//跳出下一次 {
TR0=0; TR1=0; // beep=1; money=0; second=0; second1=0; minite=0; minite1=0; value1=50; value2=25; value3=15; v=0; v1=0;
for(i=0;i
dispbuf[i]=0; dispbuf1[i]=0;
} }
//******************************************* void init()//定时器初始化 {
TMOD=0x11;
TH0=(65536-50000)/256; TL0=(65536-50000)%256; TH1=(65536-50000)/256; TL1=(65536-50000)%256; ET0=1; ET1=1; EA=1; TR0=0; TR1=0; }
//******************************************* void t0_(void) interrupt 1 using 0//定时器0中断 {
count++; if(count==20) { count=0; second++; if(second==60) { second=0; minite++; if(minite==99) { minite=0; } } }
TH0=(65536-50000)/256; TL0=(65536-50000)%256; // dispbuf1[0]=minite/10; // dispbuf1[1]=minite%10; // dispbuf1[2]=second/10; // dispbuf1[3]=second%10; }
//******************************************* void t1_(void) interrupt 3 using 3//定时器1中断 {
count1++; if(count1==20) { count1=0; second1++; if(second1==60) { second1=0; minite1++; if(minite1==99) { minite1=0; } } }
TH1=(65536-50000)/256; TL1=(65536-50000)%256; dispbuf1[4]=minite1/10; dispbuf1[5]=minite1%10; dispbuf1[6]=second1/10; dispbuf1[7]=second1%10; }
//******************************************* void lcd_init()//液晶初始化 {
wr_com(0x3c); wr_com(0x06); wr_com(0x0c); wr_com(0x01); }
//******************************************* void wr_com(uchar command)//液晶写命令 {
busy(); rs=0; rw=0;
P0=command; en=1; en=0; }
//******************************************* void wr_data(uchar data0)//液晶写数据 {
busy();
rs=1; rw=0; P0=data0; en=1; en=0; }
//******************************************* void busy()//液晶判忙 {
while(1) {
en=0; rs=0; rw=1;
P0=0xff; en=1;
if(b!=1)break; } en=0; }
//******************************************* void chuli()//数值处理 {
dispbuf[0]=value1/100%10; dispbuf[1]=value1/10%10; dispbuf[2]=value1%10; dispbuf[3]=value2/100%10; dispbuf[4]=value2/10%10; dispbuf[5]=value2%10; dispbuf[6]=value3/100%10; dispbuf[7]=value3/10%10; dispbuf[8]=value3%10; }
//******************************************* void display() {
set(0);
printstring("step:");
wr_data(table[dispbuf[0]]); wr_data(table[dispbuf[1]]); printstring(".");
wr_data(table[dispbuf[2]]);
set(10);
printstring("mileage:"); set1(0);
wr_data(table[dispbuf[3]]); wr_data(table[dispbuf[4]]); printstring(".");
wr_data(table[dispbuf[5]]);
set1(5);
printstring("wait:");
wr_data(table[dispbuf[6]]); wr_data(table[dispbuf[7]]); printstring(".");
wr_data(table[dispbuf[8]]); }
//******************************************* void chuli1() {
if(f_start==1) {
lucheng=(hr_count-1)*0.12;//总时间 dispbuf1[0]=(int)lucheng/1000 ;
dispbuf1[1]=(int)lucheng%1000/100 ; dispbuf1[2]=(int)lucheng%100/10 ; dispbuf1[3]=(int)lucheng%10 ; tt1=minite1/5;//等待时间 if(lucheng
money=value1+(lucheng-300)*0.02+value3*tt1;//起始价+每公里价*时间*速度+等待价*等待时间 } }
else if(f_start==0) {
money=0; }
dispbuf1[8]=money/100%10;// dispbuf1[9]=money/10%10;// dispbuf1[10]=money%10;// }
//*******************************************
void display1() {
set1(7);
printstring("run:");
wr_data(table[dispbuf1[0]]); wr_data(table[dispbuf1[1]]); printstring(".");
wr_data(table[dispbuf1[2]]); wr_data(table[dispbuf1[3]]);
set(11);
printstring("wait:"); set1(0);
wr_data(table[dispbuf1[4]]); wr_data(table[dispbuf1[5]]); printstring(":");
wr_data(table[dispbuf1[6]]); wr_data(table[dispbuf1[7]]);
set(0);
printstring("money:");
wr_data(table[dispbuf1[8]]); wr_data(table[dispbuf1[9]]); printstring(".");
wr_data(table[dispbuf1[10]]); }
//******************************************* void printstring(uchar *s)//行字符函数 {
while(*s)
wr_data(*s++); }
//******************************************* void key() {
if(K3==0) {
delay(50); if(K3==0) {
while(K3==0); beep=1;
if(v1==4) v1=0; } }
switch(v1) {
case 1:EX0=1;f_start=1;TR0=0;TR1=0;dianji=0;break; case 2:EX0=0;TR0=0;TR1=1;dianji=1;break; case 3:EX0=0;TR0=0;TR1=0;dianji=1;break; }
if(K4==0) {
delay(50); if(K4==0) { while(K4==0); jump_out=1; beep=0; Delay1ms(1000); beep=1; hr_count=0; } } }
//******************************************* void delay(uchar t) {
while(--t); }
//******************************************* void set(uchar x) {
command=0x80+x; wr_com(command); }
//******************************************* void set1(uchar y) {
command=0xc0+y; wr_com(command); }
//******************************************* void key1() {
{
delay(100); if(K==0) { lcd_init(); set(0); printstring("Time:"); wr_data(table[TIME[2]/16]); wr_data(table[TIME[2]&0x0f]); printstring(":"); wr_data(table[TIME[1]/16]); wr_data(table[TIME[1]&0x0f]); Delay1ms(5000); lcd_init(); } }
if(K2==0) {
delay(50); if(K2==0) {
while(K2==0); jump_in=1;// beep=0; } } }
void hr_isr() interrupt 0 { hr_count++; }
#include"temp.h"
/******************************************************************************* * 函数名 : Delay1ms * 函数功能 : 延时函数 * 输入 : 无 * 输出 : 无
*******************************************************************************/
void Delay1ms(unsigned int y) { unsigned int x; for(y;y>0;y--) for(x=110;x>0;x--); }
/******************************************************************************* * 函数名 : Ds18b20Init * 函数功能 : 初始化 * 输入 : 无
* 输出 : 初始化成功返回1,失败返回0
*******************************************************************************/
unsigned char Ds18b20Init() { unsigned int i; DSPORT=0; //将总线拉低480us~960us i=70; while(i--);//延时642us DSPORT=1; //然后拉高总线,如果DS18B20做出反应会将在15us~60us后总线拉低 i=0; while(DSPORT) //等待DS18B20拉低总线 { i++; if(i>5000)//等待>5MS return 0;//初始化失败 } return 1;//初始化成功 }
/******************************************************************************* * 函数名 : Ds18b20WriteByte * 函数功能 : 向18B20写入一个字节 * 输入 : com * 输出 : 无
*******************************************************************************/
void Ds18b20WriteByte(unsigned char dat) { unsigned int i,j; for(j=0;j
i++; DSPORT=dat&0x01; //然后写入一个数据,从最低位开始 i=6; while(i--); //延时68us,持续时间最少60us DSPORT=1; //然后释放总线,至少1us给总线恢复时间才能接着写入第二个数值 dat>>=1; } }
/******************************************************************************* * 函数名 : Ds18b20ReadByte * 函数功能 : 读取一个字节 * 输入 : com * 输出 : 无
*******************************************************************************/
unsigned char Ds18b20ReadByte() { unsigned char byte,bi; unsigned int i,j; for(j=8;j>0;j--) { DSPORT=0;//先将总线拉低1us i++; DSPORT=1;//然后释放总线 i++; i++;//延时6us等待数据稳定 bi=DSPORT; //读取数据,从最低位开始读取 /*将byte左移一位,然后与上右移7位后的bi,注意移动之后移掉那位补0。*/ byte=(byte>>1)|(bi
/******************************************************************************* * 函数名 : Ds18b20ChangTemp * 函数功能 : 让18b20开始转换温度 * 输入 : com * 输出 : 无
*******************************************************************************/
void Ds18b20ChangTemp() {
Ds18b20Init(); Delay1ms(1); Ds18b20WriteByte(0xcc); //跳过ROM操作命令 Ds18b20WriteByte(0x44); //温度转换命令
// Delay1ms(100); //等待转换成功,而如果你是一直刷着的话,就不用这个延时了 }
/******************************************************************************* * 函数名 : Ds18b20ReadTempCom * 函数功能 : 发送读取温度命令 * 输入 : com * 输出 : 无
*******************************************************************************/
void Ds18b20ReadTempCom() { Ds18b20Init(); Delay1ms(1); Ds18b20WriteByte(0xcc); //跳过ROM操作命令 Ds18b20WriteByte(0xbe); //发送读取温度命令 }
/******************************************************************************* * 函数名 : Ds18b20ReadTemp * 函数功能 : 读取温度 * 输入 : com * 输出 : 无
*******************************************************************************/
int Ds18b20ReadTemp() { int temp=0; unsigned char tmh,tml; Ds18b20ChangTemp(); //先写入转换命令 Ds18b20ReadTempCom(); //然后等待转换完后发送读取温度命令 tml=Ds18b20ReadByte(); //读取温度值共16位,先读低字节 tmh=Ds18b20ReadByte(); //再读高字节 temp=tmh; temp
#include"ds1302.h"
//---DS1302写入和读取时分秒的地址命令---//
//---秒分时日月周年 最低位读写位;-------//
uchar code READ_RTC_ADDR[7] = {0x81, 0x83, 0x85, 0x87, 0x89, 0x8b, 0x8d};
uchar code WRITE_RTC_ADDR[7] = {0x80, 0x82, 0x84, 0x86, 0x88, 0x8a, 0x8c};
//---DS1302时钟初始化2013年1月1日星期二12点00分00秒。---//
//---存储顺序是秒分时日月周年,存储格式是用BCD码---//
uchar TIME[7] = {0, 0, 0x12, 0x01, 0x01, 0x02, 0x13};
/******************************************************************************* * 函 数 名 : Ds1302Write
* 函数功能 : 向DS1302命令(地址+数据)
* 输 入 : addr,dat
* 输 出 : 无
*******************************************************************************/
void Ds1302Write(uchar addr, uchar dat)
{
uchar n;
RST = 0;
_nop_();
SCLK = 0;//先将SCLK置低电平。
_nop_();
RST = 1; //然后将RST(CE)置高电平。
_nop_();
for (n=0; n
{
DSIO = addr & 0x01;//数据从低位开始传送
addr >>= 1;
SCLK = 1;//数据在上升沿时,DS1302读取数据
_nop_();
SCLK = 0;
_nop_();
}
for (n=0; n
{
DSIO = dat & 0x01;
dat >>= 1;
SCLK = 1;//数据在上升沿时,DS1302读取数据
_nop_();
SCLK = 0;
_nop_();
}
RST = 0;//传送数据结束
_nop_();
}
/******************************************************************************* * 函 数 名 : Ds1302Read
* 函数功能 : 读取一个地址的数据
* 输 入 : addr
* 输 出 : dat
*******************************************************************************/
uchar Ds1302Read(uchar addr)
{
uchar n,dat,dat1;
RST = 0;
_nop_();
SCLK = 0;//先将SCLK置低电平。
_nop_();
RST = 1;//然后将RST(CE)置高电平。
_nop_();
for(n=0; n
{
DSIO = addr & 0x01;//数据从低位开始传送
addr >>= 1;
SCLK = 1;//数据在上升沿时,DS1302读取数据
_nop_();
SCLK = 0;//DS1302下降沿时,放置数据
_nop_();
}
_nop_();
for(n=0; n
{
dat1 = DSIO;//从最低位开始接收
dat = (dat>>1) | (dat1
SCLK = 1;
_nop_();
SCLK = 0;//DS1302下降沿时,放置数据
_nop_();
}
RST = 0;
_nop_(); //以下为DS1302复位的稳定时间,必须的。
SCLK = 1;
_nop_();
DSIO = 0;
_nop_();
DSIO = 1;
_nop_();
return dat;
}
/******************************************************************************* * 函 数 名 : Ds1302Init
* 函数功能 : 初始化DS1302.
* 输 入 : 无
* 输 出 : 无
*******************************************************************************/
void Ds1302Init()
{
uchar n;
Ds1302Write(0x8E,0X00); //禁止写保护,就是关闭写保护功能
for (n=0; n
{
Ds1302Write(WRITE_RTC_ADDR[n],TIME[n]);
}
Ds1302Write(0x8E,0x80); //打开写保护功能
}
/******************************************************************************* * 函 数 名 : Ds1302ReadTime
* 函数功能 : 读取时钟信息
* 输 入 : 无
* 输 出 : 无
*******************************************************************************/
void Ds1302ReadTime()
{
uchar n;
for (n=0; n
} { } TIME[n] = Ds1302Read(READ_RTC_ADDR[n]);
出租车计价器的设计
摘要:出租车计价器的硬件设计以STC89S52单片机为核心控制元件,利用灵敏的光电传感器对车轮的转数进行采集,从而对行驶距离进行测量,输出采用LCD1602液晶显示器,可以显示路程、金额、时间等信息,温度控制芯片采用体积微小,封装形式多样的DS18B20芯片。通过按键实现总价、路程及时间的切换显示。采用两种计价模式,区分白天黑夜计价,使该计价器的设计更加合理化。本次所设计出的出租车计价器在原有的基础上增加了语音播报及温度控制的功能,给乘客营造了一个舒适、温馨的乘车环境。
关键词:STC89S52单片机;ST181光电传感器;LCD1602显示
The design of the meter taxi
Abstract: the hardware design of the meter taxi STC89S52 single-chip microcomputer as the core control components, the use of sensitive photoelectric sensor acquisition of revolution of the wheel to measure distance, output using LCD1602 LCD display, can show the information such as distance, time, amount, temperature control chip with small volume, packaging forms of DS18B20 chips. By changing the keys to achieve price, distance and time display. Using two kinds of pricing mode, to distinguish between day and night and make the streamline the design of the meter. Designed by the taxi meter on the basis of original increased the function of speech broadcast and temperature control, passengers travelling create a comfortable, warm environment.
Key words: STC89S52 microcontroller; ST181 photoelectric sensor; LCD1602 display
目 录
1引言 ...................................................................................................................................................... 1
2系统硬件的设计 .................................................................................................................................. 1
2.1 系统指标要求及工作任务 ..................................................................................................... 1
2.2 系统设计方案选择 ................................................................................................................. 2
2.3 系统工作框图 ......................................................................................................................... 2
2.4 STC89S52单片机 .................................................................................................................... 2
2.4.1 复位电路 ..................................................................................................................... 3
2.4.2 晶振电路 ..................................................................................................................... 3
2.4.3单片机最小系统 .......................................................................................................... 3
2.5 测距单元的设计 ..................................................................................................................... 4
2.6 显示电路的设计 ..................................................................................................................... 5
2.6.1 显示电路方案选择 ..................................................................................................... 5
2.6.2 1602液晶显示器的概述 ............................................................................................ 5
2.7按键电路的设计 ...................................................................................................................... 6
2.8时钟电路的设计 ...................................................................................................................... 7
2.9发声电路的设计 ...................................................................................................................... 7
3 软件设计 ............................................................................................................................................. 7
3.1软件程序内容 .......................................................................................................................... 7
3.2程序流程图 .............................................................................................................................. 8
3.2.1 总流程图 ..................................................................................................................... 8
3.2.2 按键控制部分 ............................................................................................................. 8
4 系统调试 ............................................................................................................................................. 9
4.2 硬件调试 ......................................................................................................................... 9
4.2 程序调试 ......................................................................................................................... 9
5.结束语 ................................................................................................................................................ 10
参考文献 ............................................................................................................................................... 11 致谢 ....................................................................................................................... 错误!未定义书签。
附录 ....................................................................................................................................................... 12
1引言
随着我国经济的迅速发展,人们生活的显著提高,城市的交通日趋完善,出租车计价器的应用领域也越来越广泛,虽然私家车的拥有量在大幅度提升,但是出租车在运输行业中还是担当着非常重要的角色,而出租车计价器是出租车必不可少的一部分,传统的计价器已经不能满足人们越来越高的要求,随着集成电路大规模的发展,产生了第三代计价器,也就是全电子计价器,这不仅性能稳定、计价准确,同时也方便了出租车行业的管理。
出租车计价器的功能在不断的完善,当单片机出现并应用于计价器后,现代计价器的模型也就基本具备了,它可以实现记程、计价、显示等基本功能,国内出租车计价器已经经历了三个阶段的发展。从传统的全部有机械元器件组成的机械式,到半电子式即用电子线路代替部分机械元器件的出租车计价器;再从集成电路式到目前的单片机系统设计的出租车计价器。出租车计价器计费是否准确、出租车司机是否超速才是乘客最关心的问题,而计价器营运数据管理是否方便才是出租车司机最关注的。计价器作为出租车的一个重要组成部分,关系着出租车司机和乘客双方利益,起着重要的作用,因此,具有良好性能的计价器对广大出租车司机朋友来说是很必要的。
2系统硬件的设计
系统硬件电路设计包括光电传感器、按键电路设计、时钟电路设计、温度电路设计、发音电路设计、显示电路设计。
2.1 系统指标要求及工作任务
根据出租车计价器的多功能以及智能化要求,设计本产品的主要指标要求为:
(1)里程的计算:光电传感器对车轮进行信号检测,产生并输出脉冲信号到单片机;单片机对传感器输出的脉冲信号进行计数,并以km计算:每一个信号代表轮胎旋转一周,设轮胎的周长为1.2m ;每km产生的信号数为N ,里程显示为N × 1.2m = M(km);
(2)设定的收费标准:起步价9元,3km后2元/km,等待2元/5min;
(3)具有数据的复位功能;
(4)数据的输出:总金额输出(4位)和路程输出(4位)
(5)按键:启动开关和调节功能。
发挥部分:(1)增加了语音播报部分,在乘客上下车时自动产生简单的问候语,给乘客创造一个温馨的乘车环境;(2)使用继电器自动调节温度,使车内温度保持在人体的最适温度。
工作任务:本次设计的出租车计价器能够实现金额输出、路程输出、数据复位、计时计价、自动调温、语音播报等功能。输出采用2个4位8段共阳极数码管,车辆行走时前四位显示金额,后四位显示路程。
2.2 系统设计方案选择
系统设计的方案选择主要从两大方面考虑,即硬件电路设计和软件设计。硬件设计主要设计电路、硬件仿真和电路板;软件主要进行程序的编写和软件的仿真,要做到代码的精简、准确、易读懂,因此以C语言为编程语言。最后通过硬软件的结合实现计价器的基本功能。
2.3 系统工作框图
本系统的硬件设计主要包括单片机STC89S52、数据显示部分、里程计算及计价单元的设计。在硬件设计的过程中,充分利用个各件的功能,实现多功能的出租车计价器。
计价器的系统框图如图2-1所示,主要由STC89S52单片机、测距电路部分、时钟电路部分、显示电路部分、按键电路部分、温度电路部分、发声电路部分等组成。利用单片机丰富的IO端口及其控制的灵活性,实现基本的里程和价格的计算及显示功能,而且还可以方便的对系统进行升级。
图2-1 系统工作框图
2.4 STC89S52单片机
STC89S52为ATMEL所产生的一种低功耗、高性能CMOS8位微控制器,具有8K在系统可编程Flash存储器。晶片内部具有时钟振荡器,32个可编程I/O口线;
三个16位定时/计数器;全双工UART串行通道;STC89S52资料众多,编程与51兼容;支持ISP下载,方便使用;可靠性较高。
2.4.1 复位电路
复位电路是使单片机的CPU或系统中的其他部件处于某一确定的初始状态,并从这种状态开始工作。通常单片机复位电路有两种:上电复位电路和按键复位电路。上电复位电路:是单片机上电时复位操作,保证单片机上电后立即进入规定的复位状态。它利用的是电容充电的原理来实现的。按键复位电路:它不仅具有上电复位电路的功能,同时它的操作比上电复位电路的操作要简单的多。如果要实现复位的话,只要按下RESET键即可。它主要是利用电阻的分压来实现的。在此设计中,采用按键复位电路。
2.4.2 晶振电路
晶振电路用于产生单片机工作所需要的时钟信号,而时序所研究的是指令执行中各信号之间的相互关系。单片机本身就如一个复杂的同步时序电路,为了保证同步工作方式的实现,电路应在唯一的时钟信号控制下严格地工作。
2.4.3单片机最小系统
8KB ROM ,采用Flash STC89C52 在本系统中,有几个特殊引脚需要处理,分别是:第20引脚VSS接地,第40引脚VCC接高电平,第19、18引脚XTAL1、XTAL2要接外部晶振,第9引脚RST要
接复位电路,第31引脚EA接高电平。
单片机要正常运行,必须具备一定的硬件条件,其中最主要的是三个基本条件:
(1)电源正常;(2)时钟正常;(3)复位正常。
2.5 测距单元的设计
本次出租车计价器测距期间选用的是光电传感器。光电传感器是通过把光强度的变化转化成电信号的变化来实现控制的。通过对车轮的转数进行采集从而对行驶距离进行测量,具有非接触、响应快、性能稳定等优点,所以在现在的微电子领域选用的特别多。
光电式传感器它除能测量光强之外,还能利用光线的透射、遮挡、反射、干涉等测量多种物理量,如尺寸、位移、速度、温度等,因而是一种应用极广泛的重要敏感器件。光电测量时不与被测对象直接接触,光束的质量又近似为零,在测量中不存在摩擦和对被测对象几乎不施加压力。因此在许多应用场合,光电式传感器比其他传感器有明显的优越性。
通过对光电效应和器件原理的研究已发展了多种光电器件(如光敏电阻、光电二极管、光电三极管、场效应光电管、雪崩光电二极管、电荷耦合器件等),适用于不同的场合。光电式传感器的制造工艺也随薄膜工艺、平面工艺和大规模集成电路技术的发展而达到很高的水平,并使产品的成本大为降低。被称为新一代摄像器件的聚焦平面集成光敏阵列正在取代传统的扫描摄像系统。光电式传感器的最新发展方向是采用有机化学汽相沉积、分子束外延、单分子膜生长等新技术和异质结等新工艺。光电式传感器的应用领域已扩大到纺织、造纸、印刷、医疗、环境保护等领域。在红外探测、辐射测量、光纤通信,自动控制等传统应用领域的研究也有新发展。 在本次出租车计价器的设计中,光电传感器是通过对车轮的转数进行采集从而对行驶距离进行测量的.测距电路如图2-3所示。
图2-3 测距电路
2.6 显示电路的设计
2.6.1 显示电路方案选择
方案一:采用LCD1602液晶显示器作为显示模块。
LCD1602液晶显示器功耗低、体积小、显示内容丰富、超薄轻巧、占用单片机I/O口少等诸多优点,在袖珍式仪表和低功耗应用系统中得到越来越广泛的应用。 方案二:采用LED数码管作为显示模块。
采用LED数码管占用单片机I/O口较多,数码管显示时采用动态扫描功耗较低,显示清楚、易于辨认、程序编写简单,价格低等。缺点是显示信息量较少,不能显示符号。
综合考虑,由于LCD1602液晶显示器在显示以及方便携带等诸多方面都占有很大的优势,所以决定选择方案一。
2.6.2 1602液晶显示器的概述
液晶显示模块已作为很多电子产品的通过器件,如在计算器、万用表、电子表及很多家用电子产品中都可以看到,显示的主要是数字、专用符号和图形。1602型LCD显示模块具有体积小,功耗低,显示内容丰富等特点。1602型LCD可以显示2行16个字符,有8位数据总线D0-D7和RS,R/W,EN三个控制端口,工作电压为5V,并且具有字符对比度调节和背光功能。1602型LCD基本操作程序如表2-1所示。
表2-1 LCD1602基本操作程序
1602型LCD主要技术参数:
·显示容量:16×2个字符
·芯片工作电压:4.5—5.5V
·工作电流:2.0mA(5.0V)
·模块最佳工作电压:5.0V
·字符尺寸:2.95×4.35(W×H)mm
1602型LCD的接口信号如表2-2所示。
表2-2 LCD1602接口信号
2.7按键电路的设计
方案一:采用4个独立式按键。
如果设置过多按键,将会占用较多I/O口,而且会给布线带来不便,因此,此方案适用于按键较少的情况。如果选择此方案,由于按键较少,在修改时间或设置闹铃时间时就不能直接输入,只能通过加或减完成,稍为麻烦一些,但其程序简单。只占用4个单片机I/O口。
方案二:采用4×4矩阵式键盘。
如果选择此方案,那么在修改时钟或设置闹铃时间时就可以直接从键盘输入,方便、快捷,但程序较为复杂,且需占用8个单片机I/O口。
由于并不需要经常修改时间和设置闹铃时间,而且方案一的程序简单,按键少、成本低,因此,选择方案一。
图2-4按键电路
2.8时钟电路的设计
时钟电路是外部时钟和内部时钟组成。内部是由单片机本身及外部12MHZ的晶振和两个电容构成工作主频时钟电路,这样外电源断开时钟也不会停止。
图2-5时钟电路
2.9发声电路的设计
发音部分是通过三极管放大驱动蜂鸣器工作,再通过软件这时产生等时时间方波驱动蜂鸣器发出间断嘀声,这样就可以省去硬件振荡电路,降低成本。
图2-6 蜂鸣器驱动电路
3 软件设计
3.1软件程序内容
本系统的软件设计主要可分为主程序、里程计价中断服务程序、停车计时中断
服务程序、显示子程序和独立按键控制程序五大模块。程序是用C语言编写的。用C语言编写MCS-52单片机程序与用汇编语言编写MCS–52单片机程序不一样,用汇编语言编写MCS–52单片机程序必须要考虑其存储器结构,尤其必须考虑其片内数据存储器与特殊功能寄存器的使用以及按实际地址处理端口数据。用C语言编写的MCS–52单片机应用程序,则不用像汇编语言那样须具体组织、分配存储器资源和处理端口数据,但在C语言编程中,对数据类型与变量的定义,必须要与单片机的存储结构相关联,否则编译器不能正确地映射定位。
3.2程序流程图 3.2.1 总流程图
本次设计的出租车计价器的总流程图主要分为定时器初始化、温度调节、运行、暂停、结束时通过数据处理显示出路程和总价。
图3-1总流程框图
3.2.2 按键控制部分
单片机中应用的键盘一般是由机械触点构成。当键未被按下时,引脚输入信号为高电平;当键按下后,引脚输入信号为低电平。由于按键式机械触点,当机械触点断开、闭合时,触点将有抖动,单片机检测到按了多次键,产生非预期的结果。所以,需要用软件消抖法来避免抖动的影响,即当检测到按键按下后加一段延时后,再判断按键是否按下,如果仍为低电平即按键确实按下。
图3-2按键模块软件框图
4 系统调试
4.2 硬件调试
本设计我们通过烧写器将源程序输入到集成开发板和仿真实验仪的单片机芯片上,对系统进行硬件仿真的调试,并记录调试的结果和测试数据。此外,我们还购买了设计需要使用的元器件,在实验箱上进行电路仿真,检测设计的电路能否实现出租车计价器的功能。 4.2 程序调试
启动KEIL软件,新建一个工程文件,并保存为LED文件。新建一个NEW FILE文件保存为led_main.ASM,然后再将led_main.ASM文件添加到source group1文件上,然后单击close。最后将程序添加在编辑框里,点保存。编译程序:点击―项目/全部编译‖,如出现错误,则修改程序,再重复以上步骤,直到编译成功。将编译好的程序烧写到芯片中。接上电源,刚开始的时候除了不能显示其他的功能都能实现,经过多次修改软件最终基本能正常显示。
5.结束语
出租车计费器系统的设计已经全部完成,能按预期的效果进行模拟汽车启动,停止,暂停等功能并能够通过LCD显示车费数目。本款出租车计价器包括单价输出、路程输出、显示当前的系统时间等功能。另外,多功能出租车计价器还具有性能可靠、电路简单、成本低、实用性强等特点,加上经过优化的程序,使其有很高的智能化水平。
两个月来,经过自己努力,基本上完成了设计要求的内容,在系统可行性分析、原理图设计等方面都作了许多实际工作,取得了一些成绩,同时也遇到了一些问题,存在一些不足。经过这两个月的学习,我觉得自己不论是在理论知识方面还是在动手能力方面都有了很大的进步,自己从中受益匪浅。这次设计很好的把以前学到的理论知识应用于实践,使我认识到理论知识与实践之间有一定的差距,只有通过不断的努力学习和实践才能很好的把理论知识应用到实践当中,也只有通过不断的实践才能对理论知识的理解。
通过这次设计不仅学会了如何去查找相关资料,更重要的是通过查找资料和翻阅书籍学到了不少知识,扩大了知识面,提高了知识水平。经过单元设计和系统设计巩固了以前所学的专业知识,自己真正认识到理论联系实际的重要性,为以后的学习和工作提供了很多有价值的经验。通过这次设计不仅增强了自己的动脑能力和动手能力,也提高了我思考问题、分析问题、解决问题的能力,更重要的是学会用工程化的思想来解决问题。这在以前的学习过程中是不曾学到的。
这次设计是我认真认识到完整、严谨、科学分析问题、解决问题的思想是多么的重要,只有拥有了科学的态度才能设计出有用的产品。另外通过本次设计,是我认识到自己理论知识的应用能力有很大的欠缺,需要在以后的学习中进一步提高。
参考文献
[1]唐继贤.51单片机工程应用实例[M].北京. 北京航空航天大学出版社,2009.1 [2]王东锋,王会良,董冠强.单片机C语言应用100例[M].2009.02,254-284
[3]欧阳红,李仲秋.电子产品设计与制作知道教程[M]. 北京.清华大学出版社, 2012.3 [4]万隆.单片机原理与实例应用[M].北京.清华大学出版社, 2011.1
[5]高吉祥,库锡树.电子技术基础实验与课程设计[M].北京.电子工业出版社,2011.4 [6]楼然苗,李光飞.单片机课程设计指导[M].北京航空航天大学出版社,166-169 [7]李学海.PIC单片机实用教程:基础篇(第2版) [M].北京航空航天大学出版社,2007.02 [8]贺敬凯,刘德新等.单片机系统设计、仿真与应用[M]. 西安.西安电子科技大学出版社,2011.2
[9]肖位初,陈伟宏,杨明.基于单片机的多功能出租车计价器的设计[J].现代电子技术,2008.8.10
[10]何燕媚.出租车计价器安全计量的研究与设计[J].低碳世界,2014.6.8 [11]杨许.基于单片机控制的新型数显计价器电路设计[J].价值工程,2012.11.18
[12] 周永超,李志广,张辉,张志东.液晶显示出租车计价器设计[J].现代显示,2012.12.5 [13]王素芹.基于单片机的出租车计价器的设计[J].电子世界,2011.12.1
[14]王倩,许永生.出租车计价器的硬件设计[J].信息与电脑(理论版),2010.2.15 [15]赵建琳.简易出租车计价器的设计及实现[J].河南科技,2013.12.19
附录
1、电路原理图
2、系统仿真图
3、程序
//*******************************************
//******************************************* #include #include"temp.h" #include"ds1302.h"
#define uchar unsigned char
#define uint unsigned int
sbit rw=P2^6;//读或写 sbit rs=P2^7;//
sbit en=P2^5;//读写时能控制端 sbit b=P0^7;//液晶判断忙标志位 sbit beep=P2^2;
sbit dianji=P1^4; sbit huoer=P3^2;
void lcd_init();//
void wr_com(uchar command);//液晶写命令 void wr_data(uchar data0);//写数据 void lcd_clear();//液晶清屏
void lcd_set();//设置液晶的起始位置 void busy();//液晶判忙函数 void display();//显示
void printstring(uchar *s);//直接写字符 void display1(); void key1(); sbit K=P1^0; //sbit K1=P1^1; sbit K2=P1^1; sbit K3=P1^2; sbit K4=P1^3; sbit kt=P2^3; sbit nq=P2^4;
bit f_start;//开始标志位
bit jump_in;//跳入开始标志位 bit jump_out;//跳出标志位 void key();
uchar code table[]={0x30,0x31,0x32,0x33,0x34,0x35,0x36,0x37,0x38,0x39,0x70};//字符1,2,3,,,,,0
uchar dispbuf[]={0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}; uchar dispbuf1[]={0,0,0,0,0,0,0,0,0,0,0,0,0,0,0};
uchar v,v1;//按键次数累加变量 uchar i;
uchar hr_count=0; int temp1;
void init();//
void chuli();// void chuli1();//
void delay(uchar t);// void clear();//
void set(uchar x);// void set1(uchar y);// uchar command;//
uchar count,count1;//
uchar second,minite,second1,minite1;// unsigned int tt,tt1;// float lucheng=0.0;
unsigned char value1=90,value2=20,value3=20;//起始价,运行价,等待价 unsigned int money;//金额变量
void hr_init(void) { IT0=1;//下降沿触发 EX0=0;//打开中断0允许//EX0=1;//打开中断0允许 huoer=1;//初始化端口 }
//******************************************* void main() {
// int temp; float tp; init(); hr_init(); lcd_init(); Ds1302Init(); while(1) {
Ds1302ReadTime(); if((((TIME[2]/16*10+(TIME[2]&0x0f))>=6)&&(TIME[1]/16*10+(TIME[1]&0x0f))>0)||((TIME[2]/16*10+(TIME[2]&0x0f))
key1(); // lcd_init(); chuli(); display(); if(jump_in==1) {
jump_in=0; lcd_init(); while(1) {
key(); chuli1(); display1(); if(jump_out==1) { lcd_init(); jump_out=0; clear(); break; } // float tp; temp1=Ds18b20ReadTemp(); if(temp1
//后面的数自动去掉,不管是否大于0.5,而+0.5之后大于0.5的就是进1了,小于0.5的就 //算加上0.5,还是在小数点后面。 } if(temp1>350) { kt=0; } else { kt=1; } if(temp1
//******************************************* void clear()//跳出下一次 {
TR0=0; TR1=0; // beep=1; money=0; second=0; second1=0; minite=0; minite1=0; value1=50; value2=25; value3=15; v=0; v1=0;
for(i=0;i
dispbuf[i]=0; dispbuf1[i]=0;
} }
//******************************************* void init()//定时器初始化 {
TMOD=0x11;
TH0=(65536-50000)/256; TL0=(65536-50000)%256; TH1=(65536-50000)/256; TL1=(65536-50000)%256; ET0=1; ET1=1; EA=1; TR0=0; TR1=0; }
//******************************************* void t0_(void) interrupt 1 using 0//定时器0中断 {
count++; if(count==20) { count=0; second++; if(second==60) { second=0; minite++; if(minite==99) { minite=0; } } }
TH0=(65536-50000)/256; TL0=(65536-50000)%256; // dispbuf1[0]=minite/10; // dispbuf1[1]=minite%10; // dispbuf1[2]=second/10; // dispbuf1[3]=second%10; }
//******************************************* void t1_(void) interrupt 3 using 3//定时器1中断 {
count1++; if(count1==20) { count1=0; second1++; if(second1==60) { second1=0; minite1++; if(minite1==99) { minite1=0; } } }
TH1=(65536-50000)/256; TL1=(65536-50000)%256; dispbuf1[4]=minite1/10; dispbuf1[5]=minite1%10; dispbuf1[6]=second1/10; dispbuf1[7]=second1%10; }
//******************************************* void lcd_init()//液晶初始化 {
wr_com(0x3c); wr_com(0x06); wr_com(0x0c); wr_com(0x01); }
//******************************************* void wr_com(uchar command)//液晶写命令 {
busy(); rs=0; rw=0;
P0=command; en=1; en=0; }
//******************************************* void wr_data(uchar data0)//液晶写数据 {
busy();
rs=1; rw=0; P0=data0; en=1; en=0; }
//******************************************* void busy()//液晶判忙 {
while(1) {
en=0; rs=0; rw=1;
P0=0xff; en=1;
if(b!=1)break; } en=0; }
//******************************************* void chuli()//数值处理 {
dispbuf[0]=value1/100%10; dispbuf[1]=value1/10%10; dispbuf[2]=value1%10; dispbuf[3]=value2/100%10; dispbuf[4]=value2/10%10; dispbuf[5]=value2%10; dispbuf[6]=value3/100%10; dispbuf[7]=value3/10%10; dispbuf[8]=value3%10; }
//******************************************* void display() {
set(0);
printstring("step:");
wr_data(table[dispbuf[0]]); wr_data(table[dispbuf[1]]); printstring(".");
wr_data(table[dispbuf[2]]);
set(10);
printstring("mileage:"); set1(0);
wr_data(table[dispbuf[3]]); wr_data(table[dispbuf[4]]); printstring(".");
wr_data(table[dispbuf[5]]);
set1(5);
printstring("wait:");
wr_data(table[dispbuf[6]]); wr_data(table[dispbuf[7]]); printstring(".");
wr_data(table[dispbuf[8]]); }
//******************************************* void chuli1() {
if(f_start==1) {
lucheng=(hr_count-1)*0.12;//总时间 dispbuf1[0]=(int)lucheng/1000 ;
dispbuf1[1]=(int)lucheng%1000/100 ; dispbuf1[2]=(int)lucheng%100/10 ; dispbuf1[3]=(int)lucheng%10 ; tt1=minite1/5;//等待时间 if(lucheng
money=value1+(lucheng-300)*0.02+value3*tt1;//起始价+每公里价*时间*速度+等待价*等待时间 } }
else if(f_start==0) {
money=0; }
dispbuf1[8]=money/100%10;// dispbuf1[9]=money/10%10;// dispbuf1[10]=money%10;// }
//*******************************************
void display1() {
set1(7);
printstring("run:");
wr_data(table[dispbuf1[0]]); wr_data(table[dispbuf1[1]]); printstring(".");
wr_data(table[dispbuf1[2]]); wr_data(table[dispbuf1[3]]);
set(11);
printstring("wait:"); set1(0);
wr_data(table[dispbuf1[4]]); wr_data(table[dispbuf1[5]]); printstring(":");
wr_data(table[dispbuf1[6]]); wr_data(table[dispbuf1[7]]);
set(0);
printstring("money:");
wr_data(table[dispbuf1[8]]); wr_data(table[dispbuf1[9]]); printstring(".");
wr_data(table[dispbuf1[10]]); }
//******************************************* void printstring(uchar *s)//行字符函数 {
while(*s)
wr_data(*s++); }
//******************************************* void key() {
if(K3==0) {
delay(50); if(K3==0) {
while(K3==0); beep=1;
if(v1==4) v1=0; } }
switch(v1) {
case 1:EX0=1;f_start=1;TR0=0;TR1=0;dianji=0;break; case 2:EX0=0;TR0=0;TR1=1;dianji=1;break; case 3:EX0=0;TR0=0;TR1=0;dianji=1;break; }
if(K4==0) {
delay(50); if(K4==0) { while(K4==0); jump_out=1; beep=0; Delay1ms(1000); beep=1; hr_count=0; } } }
//******************************************* void delay(uchar t) {
while(--t); }
//******************************************* void set(uchar x) {
command=0x80+x; wr_com(command); }
//******************************************* void set1(uchar y) {
command=0xc0+y; wr_com(command); }
//******************************************* void key1() {
{
delay(100); if(K==0) { lcd_init(); set(0); printstring("Time:"); wr_data(table[TIME[2]/16]); wr_data(table[TIME[2]&0x0f]); printstring(":"); wr_data(table[TIME[1]/16]); wr_data(table[TIME[1]&0x0f]); Delay1ms(5000); lcd_init(); } }
if(K2==0) {
delay(50); if(K2==0) {
while(K2==0); jump_in=1;// beep=0; } } }
void hr_isr() interrupt 0 { hr_count++; }
#include"temp.h"
/******************************************************************************* * 函数名 : Delay1ms * 函数功能 : 延时函数 * 输入 : 无 * 输出 : 无
*******************************************************************************/
void Delay1ms(unsigned int y) { unsigned int x; for(y;y>0;y--) for(x=110;x>0;x--); }
/******************************************************************************* * 函数名 : Ds18b20Init * 函数功能 : 初始化 * 输入 : 无
* 输出 : 初始化成功返回1,失败返回0
*******************************************************************************/
unsigned char Ds18b20Init() { unsigned int i; DSPORT=0; //将总线拉低480us~960us i=70; while(i--);//延时642us DSPORT=1; //然后拉高总线,如果DS18B20做出反应会将在15us~60us后总线拉低 i=0; while(DSPORT) //等待DS18B20拉低总线 { i++; if(i>5000)//等待>5MS return 0;//初始化失败 } return 1;//初始化成功 }
/******************************************************************************* * 函数名 : Ds18b20WriteByte * 函数功能 : 向18B20写入一个字节 * 输入 : com * 输出 : 无
*******************************************************************************/
void Ds18b20WriteByte(unsigned char dat) { unsigned int i,j; for(j=0;j
i++; DSPORT=dat&0x01; //然后写入一个数据,从最低位开始 i=6; while(i--); //延时68us,持续时间最少60us DSPORT=1; //然后释放总线,至少1us给总线恢复时间才能接着写入第二个数值 dat>>=1; } }
/******************************************************************************* * 函数名 : Ds18b20ReadByte * 函数功能 : 读取一个字节 * 输入 : com * 输出 : 无
*******************************************************************************/
unsigned char Ds18b20ReadByte() { unsigned char byte,bi; unsigned int i,j; for(j=8;j>0;j--) { DSPORT=0;//先将总线拉低1us i++; DSPORT=1;//然后释放总线 i++; i++;//延时6us等待数据稳定 bi=DSPORT; //读取数据,从最低位开始读取 /*将byte左移一位,然后与上右移7位后的bi,注意移动之后移掉那位补0。*/ byte=(byte>>1)|(bi
/******************************************************************************* * 函数名 : Ds18b20ChangTemp * 函数功能 : 让18b20开始转换温度 * 输入 : com * 输出 : 无
*******************************************************************************/
void Ds18b20ChangTemp() {
Ds18b20Init(); Delay1ms(1); Ds18b20WriteByte(0xcc); //跳过ROM操作命令 Ds18b20WriteByte(0x44); //温度转换命令
// Delay1ms(100); //等待转换成功,而如果你是一直刷着的话,就不用这个延时了 }
/******************************************************************************* * 函数名 : Ds18b20ReadTempCom * 函数功能 : 发送读取温度命令 * 输入 : com * 输出 : 无
*******************************************************************************/
void Ds18b20ReadTempCom() { Ds18b20Init(); Delay1ms(1); Ds18b20WriteByte(0xcc); //跳过ROM操作命令 Ds18b20WriteByte(0xbe); //发送读取温度命令 }
/******************************************************************************* * 函数名 : Ds18b20ReadTemp * 函数功能 : 读取温度 * 输入 : com * 输出 : 无
*******************************************************************************/
int Ds18b20ReadTemp() { int temp=0; unsigned char tmh,tml; Ds18b20ChangTemp(); //先写入转换命令 Ds18b20ReadTempCom(); //然后等待转换完后发送读取温度命令 tml=Ds18b20ReadByte(); //读取温度值共16位,先读低字节 tmh=Ds18b20ReadByte(); //再读高字节 temp=tmh; temp
#include"ds1302.h"
//---DS1302写入和读取时分秒的地址命令---//
//---秒分时日月周年 最低位读写位;-------//
uchar code READ_RTC_ADDR[7] = {0x81, 0x83, 0x85, 0x87, 0x89, 0x8b, 0x8d};
uchar code WRITE_RTC_ADDR[7] = {0x80, 0x82, 0x84, 0x86, 0x88, 0x8a, 0x8c};
//---DS1302时钟初始化2013年1月1日星期二12点00分00秒。---//
//---存储顺序是秒分时日月周年,存储格式是用BCD码---//
uchar TIME[7] = {0, 0, 0x12, 0x01, 0x01, 0x02, 0x13};
/******************************************************************************* * 函 数 名 : Ds1302Write
* 函数功能 : 向DS1302命令(地址+数据)
* 输 入 : addr,dat
* 输 出 : 无
*******************************************************************************/
void Ds1302Write(uchar addr, uchar dat)
{
uchar n;
RST = 0;
_nop_();
SCLK = 0;//先将SCLK置低电平。
_nop_();
RST = 1; //然后将RST(CE)置高电平。
_nop_();
for (n=0; n
{
DSIO = addr & 0x01;//数据从低位开始传送
addr >>= 1;
SCLK = 1;//数据在上升沿时,DS1302读取数据
_nop_();
SCLK = 0;
_nop_();
}
for (n=0; n
{
DSIO = dat & 0x01;
dat >>= 1;
SCLK = 1;//数据在上升沿时,DS1302读取数据
_nop_();
SCLK = 0;
_nop_();
}
RST = 0;//传送数据结束
_nop_();
}
/******************************************************************************* * 函 数 名 : Ds1302Read
* 函数功能 : 读取一个地址的数据
* 输 入 : addr
* 输 出 : dat
*******************************************************************************/
uchar Ds1302Read(uchar addr)
{
uchar n,dat,dat1;
RST = 0;
_nop_();
SCLK = 0;//先将SCLK置低电平。
_nop_();
RST = 1;//然后将RST(CE)置高电平。
_nop_();
for(n=0; n
{
DSIO = addr & 0x01;//数据从低位开始传送
addr >>= 1;
SCLK = 1;//数据在上升沿时,DS1302读取数据
_nop_();
SCLK = 0;//DS1302下降沿时,放置数据
_nop_();
}
_nop_();
for(n=0; n
{
dat1 = DSIO;//从最低位开始接收
dat = (dat>>1) | (dat1
SCLK = 1;
_nop_();
SCLK = 0;//DS1302下降沿时,放置数据
_nop_();
}
RST = 0;
_nop_(); //以下为DS1302复位的稳定时间,必须的。
SCLK = 1;
_nop_();
DSIO = 0;
_nop_();
DSIO = 1;
_nop_();
return dat;
}
/******************************************************************************* * 函 数 名 : Ds1302Init
* 函数功能 : 初始化DS1302.
* 输 入 : 无
* 输 出 : 无
*******************************************************************************/
void Ds1302Init()
{
uchar n;
Ds1302Write(0x8E,0X00); //禁止写保护,就是关闭写保护功能
for (n=0; n
{
Ds1302Write(WRITE_RTC_ADDR[n],TIME[n]);
}
Ds1302Write(0x8E,0x80); //打开写保护功能
}
/******************************************************************************* * 函 数 名 : Ds1302ReadTime
* 函数功能 : 读取时钟信息
* 输 入 : 无
* 输 出 : 无
*******************************************************************************/
void Ds1302ReadTime()
{
uchar n;
for (n=0; n
} { } TIME[n] = Ds1302Read(READ_RTC_ADDR[n]);