出租车计价器.docx
《出租车计价器.docx》由会员分享,可在线阅读,更多相关《出租车计价器.docx(15页珍藏版)》请在冰豆网上搜索。
![出租车计价器.docx](https://file1.bdocx.com/fileroot1/2023-1/26/d24ecb1b-96c4-45aa-a863-6ca41af38742/d24ecb1b-96c4-45aa-a863-6ca41af387421.gif)
出租车计价器
1设计的任务与要求
1.1设计任务
出租车计价器是乘客与司机双方的交易准则,它是出租车行业发展的重要标志,是出租车中最重要的工具。
它关系着交易双方的利益。
具有良好性能的计价器无论是对广大出租车司机朋友还是乘客来说都是很必要的。
出租车计价器的主要功能是计价显示、时钟显示、根据白天、黑夜、途中等待来调节营运参数、计量数据查询等。
要求用Protel画出系统的电路原理图(要求以最少组件,实现系统设计所要求的功能),印刷电路板(要求布局合理,线路清晰),绘出程序流程图,并给出程序清单(要求思路清晰,尽量简洁,主程序和子程序分开,使程序有较强的可读性)。
1.2设计要求
本题目设计一台出租车计价器。
调试时采用20Hz方波信号模拟,每个方波代表10m。
1、基本要求:
数码管显示:
1、2位显示单价;4、5位显示路程;7、8位显示总价格;
指示灯:
绿灯显示为正在计价;红灯显示为停止并清零计价;
按键控制:
KEY1为计价开始键;KEY2为计价清零键;KEY3为白天/晚上转换键
2、详细叙述单片机系统的接口设计与程序设计方案。
3、按要求编写课程设计报告书,正确、完整的阐述设计和结果。
4、在报告中绘制程序的流程图,并文字说明。
2总体设计方案
2.1设计方案
出租车计价器基本功能部分是根据里程数来完成总金额的输出。
实现方法有两种。
方案一:
采用数字电路控制。
其原理方框图如图2.1所示。
采用传感器件,输出脉冲信号,经过放大整形作为移位寄存器的脉冲,实现计价,但是考虑到这种电路过于简单,性能不够稳定,而且不能调节单价,也不能根据天气调节计费标准,电路不够实用。
图2-1数字电路实现框图
方案二:
采用单片机控制。
利用单片机丰富的IO端口,及其控制的灵活性,实现基本的里程计价功能和价格调节、时钟显示功能。
本方案有较大的活动空间,不但能实现所要求的功能而且能在很大的程度上扩展功能,而且还可以方便的对系统进行升级,所以我们采用后一种方案。
通过分析,需要实现四个主要的功能模块,分别为脉冲计数模块、定时器计时模块、按键的处理以及数码管动态扫描等功能。
主程序完成键盘的扫描和按键的处理,查询脉冲产生的中断,并完成脉冲的计数。
每个脉冲代表10米,则当计数到100时表示1千米的距离,相应的总金额要按照收费标准计价。
系统框图如图2-2所示。
图2-2系统框图
2.2设计思路
程序设计的思路:
使用中断方式对定时器的溢出进行计数实现30秒的计时。
主程序采用查询外部中断标志实现脉冲的计数,由于每个脉冲代表10m,因此,当脉冲计数超过100时,计价器按照收费标准计价。
主程序在初始化变量和定时器参数设置之后,进入一个循环结构,循环扫描键盘、查询脉冲的中断、数码管的动态扫描等功能,当脉冲的中断标志被查询到,若路途等待时间未超30秒时,要及时将路途等待时间的值清除为零。
2.3硬件电路原理图
采用MCS51系列单片机At89S52作为主控制器,外围电路器件包括数码管驱动、独立式键盘、复位电路等。
硬件电路原理图如图2-3所示。
图2-3出租车计价器的硬件电路原理图
数码管驱动采用2个四联共阴极数码管显示,由于单片机驱动能力有限,采用74HC244作为数码管的驱动。
在74HC244的7段码输出线上串联100欧姆电阻起限流作用。
独立式按键使用上提拉电路连接,在没有键按下时,输出高电平。
P0口用于输出7段LED共阴极显示代码,P2口用于输出低电平有效的位选码。
0~9的7段LED共阴极显示代码:
3FH,06H,5BH,4FH,66H,6DH,7DH,07H,7FH,6FH。
2.4调试方案
设计系统软件调试方案:
伟福软件中,在“文件\新建文件”中,新建C语言源程序文件,编写相应的程序。
在“文件\新建项目”的菜单中,新建项目并将C语言源程序文件包括在项目文件中。
在“项目\编译”菜单中将C源文件编译,检查语法错误及逻辑错误。
在编译成功后,产生以“*.hex”和“*.bin”后缀的目标文件。
硬件调试方案:
在设计平台中,将单片机的P1.0-P1.2分别与3个独立式键盘通过插线连接起来,将P3.2与脉冲信号源连接起来。
在伟福中将程序文件编译成目标文件后,将下载线安装在实验平台上,运行“MCU下载程序”,选择相应的flash数据文件,点击“编程”按钮,将程序文件下载到单片机的Flash中。
然后,上电重新启动单片机,检查所编写的程序是否达到题目的要求,是否全面完整地完成试题的内容。
3硬件设计
3.1单片机开发板
如图3-1所示。
采用MCS51系列单片机AT89S52为核心,扩展了常用的经典电路模块。
单片机与各模块之间需要用插针线手动连接实现单片机应用模块的扩展。
主要模块包括:
电源模块、单片机最小系统、数码管显示模块、开关量输入模块、发光二极管显示模块、独立式键盘模块、行列式键盘模块、I2C总线、A/D转换模块、D/A转换模块、点阵式液晶显示模块、逻辑笔模块、继电器/蜂鸣器输出模块和脉冲信号源模块等。
图3-1单片机实验开发平台
3.2电源模块
开发鉴定平台采用外部直流9V电源适配器提供电源,通过LM7805稳压芯片为平台各模块提供+5V电源。
另外采用7660S提供-5V电源(仅为点阵液晶准备,不常用)。
同时平台将+5V、Gnd通过插针座可以外接出来,方便面包板上的电路扩展与调试。
电路原理图如图3-2所示。
图3-2电源模块
3.3数码管显示模块
提供8个共阴极的数码管。
设计平台的P0口用于输出7段LED共阴极显示代码,P2口用于输出低电平有效的位选码。
0~9的7段LED共阴极显示代码:
3FH,06H,5BH,4FH,66H,6DH,7DH,07H,7FH,6FH。
图3-3数码管显示模块
3.4单片机最小系统
单片机最小系统包括复位电路、时钟电路、RS232串口通信模块以及下载线接口等,电路原理图如图3-4所示。
复位电路采用上电复位和手动按键复位两种。
时钟电路的晶振采用11.0592M和12MHz两种,通过跳线短路环完成二选一,为单片机提供时钟,其中接通跳线P1和P2选择11.0592M的晶振,接通跳线P3和P4选择12M的晶振。
单片机的I/O口(P1,P2,P3,P4)分别通过圆形插针座可以外接出来,方便外围电路的扩展。
图3-4单片机最小系统
4软件设计
4.1系统总程序设计
软件的任务要求包括定时器的设置、按键的扫描、按键的功能处理、脉冲的计数、路途等待超30秒的计时以及总金额的计算等。
图4-1出租车计价器的主程序流程图
主程序流程图如图4-1所示,在主程序模块中,需要完成对各接口芯片的初始化、出租车起价和单价的初始化、中断向量的设计以及开中断、循环等待等工作。
另外,在主程序模块中还需要设置启动/清除标志寄存器、里程寄存器和价格寄存器,并对它们进行初始化。
然后,主程序将根据各标志寄存器的内容,分别完成启动、清除、计程和计价等不同的操作。
4.2中断程序设计
中断服务程序主要实现计时功能,当启动键按下之后,定时器开始工作,用一个变量对定时器溢出中断的次数进行计数,达到计时功能,该变量在每次脉冲到来时被清零(在主程序中清零),当脉冲长时间没有来,则当该变量计数超过30秒时,总金额按照途中等待计费标准进行计价。
中断程序的流程图如图4-2所示。
图4-2出租车计价器的中断服务程序流程图
4.3计算程序
计算程序根据行车时间分别进入不同的计算公式。
执行公式:
总金额=单价*里程+等待时间*等待单价。
4.4定时器程序
定时器计时模块主要完成途中等待(即没有脉冲来时)30秒的计时。
在启动键按下后,定时器就不停的计时,只要有脉冲来就将计时的值清除为零。
如果没有脉冲来,当计时超过30秒时,相应的总金额要按照收费标准计价。
启动键触发定时器开始工作,而定时器的运行可以作为脉冲计数的标志,只要定时器计时在运行,每来一个中断都应该计数。
4.5显示程序
显示程序利用定时器每1ms产生一次中断,相应变量置位,点亮一个数码管,显示一位数据,利用主函数内的循环,实现动态扫描显示,同时根据数码管余辉和人眼暂留现象,即可实现显示。
数码管显示:
1、2位显示单价;4、5位显示路程;7、8位显示总价格;
指示灯:
绿灯显示为正在计价;红灯显示为停止并清零计价。
5设计思考及体会
经过这些天有关于出租车计价器的课程设计,使我对单片机的应用有了更深的了解。
在课程设计的过程中,还是碰到了许多的问题。
比如,对于数码管动态扫描显示和键盘的延时防抖的综合编程不能较好地解决;对于代码的前后顺序及调用掌握得还不够好;对于一些相关的应用软件没能熟练掌握。
通过这几天晚上的苦想和反复调试,以及参考网上的程序,最终还是把问题解决了。
通过这次课程设计,我最大的收获就是自己的动手能力和独立解决问题的能力得到了很大的提高,也充分体会到了自己设计东西的乐趣、学会查阅资料和对别人的东西融会变通的重要性,也明白了很多知识光靠趴在书本上学是学不到其中的精髓的,必须亲自去试着实践,亲自去经历才能对它们真正的掌握,凡事都要自己去动下手,去实践一下,遇到困难,永远不要沮丧气馁。
在动手的过程中,不仅能增强实践能力,而且在理论上可以有更深的认识;这次设计给了我极大的鼓舞和信心,相信在以后的学习中可以通过不断的摸索和实践来提高其他方面的知识。
学习的过程是相互讨论,共同进步的,多多讨论课题中遇到的问题,可以巩固我们的知识掌握能力,增加熟练运用度。
同时,通过本次课程设计,锻炼了我的动手能力,和提高了我分析问题,解决问题的能力。
参考文献
[1]李鸿等.单片机原理及应用[M].湖南大学出版社,2005.
[2]何立民.单片机高级教程---应用与设计[M].北京航空航天大学出版社,2000,8.
[3]戴佳.51单片机C语言应用程序设计实例精讲[M].北京:
电子工业出版社,2006.
[4]于京. 51系列单片机C程序设计与应用案例[M].北京:
中国电力出版社,2006.
[5]孙育才. ATMEL新型AT89S52系列单片机及其应用[M].北京:
清华大学出版社,2005.
[6]李华.MCS-51系列单片机实用接口技术[M].北京:
北京航空航天大学出版社,2000.
附录
使用的子函数:
voiddelayms(uintz)为1ms延时子函数;
voiddisplay(ucharprice,uchardistance,ucharcost)为数码管显示子函数;
ucharkey_scan()为键盘扫描函数,为松手检测;
voidinit()全局变量初始化子函数;
voidinit_reg()单片机内部寄存器初始化子函数;
voidtimer1()interrupt3计时中断子函数;
#include
#defineucharunsignedchar
#defineuintunsignedint
sbitdis_start=P3^7;
sbitdis_clear=P3^6;
sbitbuzzer=P3^3;
charcodeshuma_code[]={0x3f,0x06,0x05b,0x04f,0x66,0x6d,0x7d,0x07,0x7f,0x6f};
ucharcount_30,wait_number,distance,cost,distance_count,key,key_flag;
ucharprice=1;
uintcount;
voiddelayms(uintz)
{
uintx,y;
for(x=z;x>0;x--)
for(y=110;y>0;y--);
}
voiddisplay(ucharprice,uchardistance,ucharcost)
{unsignedcharx,y,k,m;
P0=shuma_code[price];
P2=0xbf;
delayms
(1);
P0=shuma_code[0];
P2=0x7f;
delayms
(1);
x=distance%10;
P0=shuma_code[x];
P2=0xf7;
delayms
(1);
y=distance%100/10;
P0=shuma_code[y];
P2=0xef;
delayms
(1);
k=cost%10;
P0=shuma_code[k];
P2=0xfe;
delayms
(1);
m=cost%100/10;
P0=shuma_code[m];
P2=0xfd;
delayms
(1);
}
ucharkey_scan()
{
if(P1!
=0xff)
{
delayms(10);
if(P1!
=0xff)
{
switch(P1)
{
case0xfe:
{
key=0;
while(P1!
=0xff);
delayms(10);
while(P1!
=0xff);
break;
}
case0xfd:
{
key=1;
while(P1!
=0xff);
delayms(10);
while(P1!
=0xff);
break;
}
case0xfb:
{
key=2;
while(P1!
=0xff);
delayms(10);
while(P1!
=0xff);
break;
}
}
}
}
returnkey;
}
voidinit()
{
count=0;
count_30=0;
wait_number=0;
distance=0;
cost=0;
key=8;
key_flag=8;
}
voidinit_reg()
{
TMOD=0x20;
TH1=0x19;
TL1=0x19;
EA=1;
ET1=1;
TR1=0;
TCON=0x01;
}
voidtimer1()interrupt3
{
count++;
if(count>3999)
{
count=0;
if(count_30<30)
{count_30++;}
else
{count_30=0;
wait_number++;}
}
}
voidmain()
{
init();
init_reg();
while
(1)
{
key=key_scan();
if(key!
=8)
{
switch(key)
{
case0:
{
TR1=1;
key_flag=0;
dis_start=0;
dis_clear=1;
key=8;
break;
}
case1:
{
TR1=0;
init();
init_reg();
key_flag=1;
dis_start=1;
dis_clear=0;
key=8;
break;
}
case2:
{
price++;
if(price==3)
price=1;
key=8;
break;
}
}
}
if(IE0==1&&key_flag==0)
{
key=8;
IE0=0;
count_30=0;
if(distance_count<100)
{
distance_count++;
}
else
{
distance_count=0;
distance++;
}
}
cost=distance*price+wait_number;
display(price,distance,cost);
}
}