《微机实验及课程设计》课程设计报告出租车自动计价器Word文档格式.docx
《《微机实验及课程设计》课程设计报告出租车自动计价器Word文档格式.docx》由会员分享,可在线阅读,更多相关《《微机实验及课程设计》课程设计报告出租车自动计价器Word文档格式.docx(34页珍藏版)》请在冰点文库上搜索。
(3)判断数码管显示内容
(4)判断系统是否开始行驶
具体的规划如下:
以8255芯片为例,将A口定义为方式0输入,A0连接8253定时器的OUT1输出,以便用来检测是否存在1s定时。
后面相继的1-5分别接到逻辑电平开关K1-K5,K6接某个与门右引脚控制直流电机的开关。
而K7开关接到一个LED灯上,检验判断是处于开始计价还是空车状态。
开关名称
K1
K2
K3
K4
K5
K6
K7
对应口
PA1
PA2
PA3
PA4
PA5
与门右引脚
PA7
功能
K=0
停止状态
单程
显示功能
关闭直流电机
空车状态
K=1
计费状态
双程
1
X
时间
打开直流电机
开始计价
里程
费用低位
费用高位
2、计数模块
计算路程、计算时间两个,通过计数模块可以获得出租车目前行驶的路程以及已经行驶的时间,该模块的数据应用到计费模块可以行驶及等待过程的总费用。
其原理是根据直流电机每秒中输出的脉冲数分情况,预先设定好一个脉冲阈值(本实验用的是10),当直流电机每秒输出的脉冲数大于10时,出租车处于行车状态,此时里程=历史里程+脉冲数/100。
当直流电机每秒输出的脉冲数小于10时,出租车处于等待状态,此时等待时间加1。
8253定时器功能分配如下:
计数器0设置成方式3,计数器1设置成方式0,计数器0、1的计数初值均设置为1000,然后将两个计数器级联,计数器0输入1MHz的时钟信号,利用out1产生的1S的周期信号来产生1S的定时中断。
计数器2设置成方式0,将直流电机的脉冲输入到CLK2,用来计数直流电机的脉冲数。
3、计费模块
计费模块利用计数模块提供的时间以及路程等信息,通过条件等操作针对不同的情况采用不同的计费方式,最终得到总费用。
计费公式如下:
4、显示模块
根据设计要求我们可以将显示模块主要分为屏幕显示和数码管显示两个部分。
第一部分是屏幕显示,在屏幕上显示里程数、等待时间和总费用,最近5次费用等等,可以通过调用DOS中断显示数据;
第二部分是通过数码管显示,由于数码管只有两个,我们组合使用K3、K4、K5选择显示当前里程数、等待时间和总费用的高低位,数码管位选和段选分别用8255芯片的C口PC0和PC1、B口PB0~PB7控制。
而空车信号由LED灯显示,只需将K7连接LED灯上即可显示空车状态。
其中8255B口设置成方式0输出,用于控制八位数码管的段选。
8255C口设置为方式0输出方式。
三.实验流程与测试结果
判断单双程
从8255A口读入开关
开始
数值显示更新
初始化程序
数码管显示
N
PA1=1?
Y
PA0=1?
系统启动
调用显示模块
PA7=1?
计价更新模块
DJ
直流电机
5
4.分析与总结
按照题目的实验要求,我一共完成了5个基本要求和提高要求的
(1)、
(2)两部分。
通过机械开关控制出租车的状态,LED灯L7显示行车状态:
L7灭表示空车,L7亮表示车里有人且自动计价器在计价。
可以通过调节控制直流电机的电位器来切换出租车的行驶状态。
在屏幕上将动态显示出当前的路程、等待时间和费用,数码管的显示数据则可以通过开关来切换。
经过多次检验和验证,本项目能正确地计算出租车行驶的费用,实现了出租车自动计价器的基本功能和部分扩展功能。
在实验中我熟悉了8253、8255的操作过程和原理,了解了直流电机、数码管的使用方法,对汇编语言的书写、编辑能力有了进一步提高。
事实上我的设计过程并不是一帆风顺。
一开始在查找资料后我发现了一个比较简单的思路,即把汽车实时数据预先存储在数据段的字符串里面,通过8253定时得到的时间、8253获得的直流电机脉冲数目,计算出等待时间、行驶路程等重要参数,间接的从预存数据中取得费用等,显示在屏幕和数码管上。
由于现实行车中不会出现太长的等待时间,出租车也不可能每客都行驶数十公里,所以我觉得可行性还是相当高的。
但是后来因为其中的几个问题一直得不到解决,且这些问题由很重要,所以不得不放弃原来的思路,参考去往届学长成熟的经验方法,最终比较成功的实现了各功能。
老师提出了等待脉冲阈值设定的问题,原来的脉冲阈值设定为50,太高不符合现实情况,后来进行了更改,改为10。
除此之外直流电机转速过快会使屏来不及更新数据,在咨询学长后在调整速度又恢复正常。
在测试代码时,调试数码管相对来说比较麻烦,程序中的算法存在一点点漏洞,会对显示造成很多影响,最终我们也发现数码管显示值会比屏幕显示出来的值小数个采样,通过调整代码也没有解决它。
这次实验让我对微机系统各组成部分的工作原理有了更加清晰的认识,了解了微机乃至以后单片机的一些设计和应用的方法。
这是很宝贵的收获。
5.附录
cursormacrorow,clm;
***********移动光标位置到(row,clm)*******************io8255c第三口接LED灯用来表示行车等待
pushax
pushbx
pushdx
movah,2;
INT10功能号为2时,置光标位置
movbh,0;
页号为0
movdh,row
movdl,clm
int10h
popdx
popbx
popax
endm
datasegment
ioportequ0ec00h-0280h
io8253aequioport+280h;
8253计数器0地址
io8253bequioport+281h;
8253计数器1地址
io8253cequioport+282h;
8253计数器2地址
io8253dequioport+283h;
8253控制寄存器地址
io8255aequioport+288h;
8255A口地址
io8255cequioport+28ah;
8255C口地址
io8255bequioport+289h;
8255B口地址
io8255dequioport+28bh;
8255控制寄存器地址
onekmequ100;
一公里对应的脉冲数
waitnumequ10;
参考脉冲数,小于此值即为等待
startpequ80;
起步价8元
pricedb12;
行车计费,1.2元/公里
waitpequ2;
等待计费,0.2元/分钟
str0db'
'
0dh,0ah,'
$'
str1db'
****************Taxicalculatingfeemachine**************'
str6db'
*********************08013226**************************'
str2db'
*********PRICE:
1.80yuan/km0.2yuan/min***************'
str12db'
1.20yuan/km0.2yuan/min***************'
str3db'
TIME:
0(M)'
str4db'
DIST:
0(KM)'
str5db'
COST:
0(YUAN)'
str7db'
Fivecost:
'
str11db'
GETOFFTHETAXIend_time:
00:
00'
str14db'
start_time:
pnumdw0;
总脉冲数
distdb0;
总里程
timedb0;
等待时间
totaldw0000h;
总费用
flagdb11h
xdkdb0
feeBufferdw0000h,0000h,0000h,0000h,0000h;
五次费用
feeCountdb0
leddb3fh,06h,5bh,4fh,66h,6dh,7dh,07h,7fh,6fh;
段码
buffer1db6,5h;
存放要显示的个位和十位
bzdw?
;
位码
dataends
stackssegmentstack
db100dup(?
)
stacksends
codesegment
assumecs:
code,ds:
data,ss:
stacks
mainproc
start:
movax,data
movds,ax
movax,stacks
movss,ax
movdx,io8255a
inal,dx
testal,04h;
0代表单程,1代表双程
jzbb
movbl,55h;
作为单程还是双程的标志,等于55h则为双程
movflag,bl
movbl,12;
十进制,表示往返双程则为1.2元/公里
movprice,bl
bb:
callini;
调用初始化子程序
calldisp;
调用数值更新程序
begin1:
movdi,offsetbuffer1;
设di为显示缓冲区
calllll;
调用数码管显示程序
inal,dx
testal,02h;
0代表计费状态,1代表结束
jnzexit
testal,01h;
判断是否有1秒钟定时中断信号,1为start启动
jzbegin1;
为0则重新调用数码管显示程序
callbegin;
启动计费
movbx,total
moval,bl
callextendBcd;
调用二进制转换为BCD码程序,输入为八位的al,返回值为16位的ax
movwordptr[buffer1],ax;
将低位价格BCD码存入要显示的数字的内存区
movdx,io8255a
testal,00001000b
jzshowl1;
K3=0,不显示里程数
moval,dist
callextendBcd
将里程数对应的BCD码存入要显示的数字的内存区
jmpshowl3
showl1:
movdx,io8255a
testal,00010000b
jzshowl2;
K4=0,不显示等待时间
moval,time
callextendBcd
movwordptr[buffer1],ax;
将等待时间对应的BCD码存入要显示的数字的内存区
showl2:
testal,00100000b
jzshowl3;
K5=0,不显示价格高两位
movbx,total
moval,bh
将高位价格BCD码存入要显示的数字的内存区
showl3:
inal,dx
jzbegin1;
每过一秒钟则判断一下是否停止等等
callgains;
每过一秒钟则调用一次计费模块
movbl,feeCount
cmpbl,9
jaaboveCount
jmpbelowCount
aboveCount:
movbl,0;
五个一循环
belowCount:
movax,total
movbh,0
movfeeBuffer[bx],ax
incbl
movfeeCount,bl
jmpbegin1
exit:
calloff_texi
cursor11,0
movah,4ch;
退出程序
int21h
mainendp
;
*********************扩展BCD码***************************
extendBcdproc
pushcx
movbl,al
movcl,4
shral,cl;
取高四位
movah,al
andbl,00001111b
moval,bl;
取低四位
popcx
ret
extendBcdendp
*********************数码管显示程序***************************
lllproc
pushdi
pushsi
movbh,2
ll:
movbyteptrbz,bh
pushdi
decdi
adddi,bz
movbl,[di];
bl为要显示的数
popdi
moval,0
movdx,io8255c;
消隐,全部关闭
outdx,al
movsi,offsetled;
置led数码表偏移地址为SI
addsi,bx;
求出对应的led数码地址
moval,byteptr[si]
movdx,io8255b;
自8255B口输出段码
moval,byteptrbz;
使相应的数码管亮
oral,xdk
movdx,io8255c
outdx,al;
自8255C口输出位码
movcx,3000
delay:
loopdelay;
延时
movbh,byteptrbz
shrbh,1
jnzll;
右移一位判断显示的高地位,若为高位,回ll继续显示低位
popsi
lllendp
*********************计价更新程序***************************
gainsproc
movax,total
andax,ax
jzreturn2;
总价是0,则返回主程序
movdx,io8253c;
读取脉冲数
inal,dx;
将直流电机的脉冲输入到CLK2,用来计数直流电机的脉冲数
movdx,io8253a;
计数器0重新计数
movax,1000
moval,ah
outdx,al
movdx,io8253b
movax,1000;
计数器1重新计数
moval,0
计数器2重新计数
moval,0ffh;
计算脉冲数
subal,bl
incal
cmpal,waitnum;
脉冲数小于参考值则为等待状态,否则为行车状态
jbwgain
movah,00000100b
movxdk,ah
movah,0
addpnum,ax;
计算总的脉冲数
movax,pnum
movbl,100
divbl
callnum2bcds;
计算行驶里程数并转化为2位压缩BCD码
movdist,al
jmpnewcost;
更新总费用
wgain:
moval,0
movxdk,al
moval,time;
判断为等待状态,等待时间加1
callbcd2num;
将2位压缩BCD码转换成十进制数字
再将二进制转换为压缩BCD码,方便数码管显示
movtime,al
jmpnewcost
return2:
jmpreturn
newcost:
moval,dist;
计算当前总金额
BCD转换为10进制
movtotal,startp
cmpal,3
jbecost2;
路程小于三公里
subal,3
movah,0
movbl,price
mulbl
addtotal,ax;
cost2:
moval,time;
开始等待计费
callbcd2num
movbl,waitp
addax,total;
ax中等待费用加上total中路程费用
callnum2bcdl;
转换为4位压缩BCD格式
movtotal,ax
数值更新显示程序
return:
popcx
popbx
popax
ret
gainsendp
*********************2位压缩BCD码转换为十进制数***************************
bcd2numproc
pushbx
pushcx
movbh,al
movcl,4
shral,cl
movbl,10
andbh,00001111b
addal,bh
ret
bcd2numendp
**********************************小数点显示程序*********************
commaproc
pushax
pushdx
movah,2
movdl,'
.'
int21h
popdx
ret
commaendp
*********************************显示程序*******************************
showproc
callshow1
cmpdl,1;
是否显示小数点的标志
jnzdown
callcomma
down:
callshow11
showendp
****************************显示子程序1*************************************
show1proc
movdl,al;
显示程序用的是al寄存器
shrdl,cl;
保留高四位,清除低四位
adddl,30h;
dl存的是所显示字符的ASCII码,若显示数字,则需将其数值加上30h
movah,02h
show1endp
**************************显示子程序2***********************************
show11proc
movdl,al
anddl,00001111b;