一、设计要求
- 设计一个出租车计费器程序(含原理图),要求如下:
- 用Proteus设计原理图,要求显示出里程,速度,总价
- 使用一个按钮,按下按钮开始计费,松开按钮停止计费
- 用信号发生器来产生出租车的模拟信号
- 提交实验文档和工程文件,作业提交后要找老师答辩才能评定成绩
- 出租车轮胎周长按1.83米计算。2公里以内按8元计算,超过2公里每公里按2.6元计算。不考虑其他费用
- 要求用汇编语言编程,不能用C编程
- 实验文档要写清楚算法,所用到内存的含义
二、设计思路
- 使用外部中断INT0PROC对轮胎转过圈数计数
- R3,R4分别表示轮胎转过总圈数的低字节和高字节。
- R5表示每秒轮胎转过的圈数,每次计算完速度后清零。
- 计算出租车行驶路程DISTANCE
- #circumstance内存储#183
- 双字节数R4R3乘#circumstance,得到三字节数3FH,3EH,3DH。
- 使用定时器计算出租车行驶速度SERVE,SPEED
- 使用模式1,晶振频率为22.1184MHZ,单次中断为5ms,200次中断后调用函数SPEED。
- v=R5*183*6*6/1000,
- 在程序中先进行一次单字节乘法,#circumstance乘#36,结果存储在41H,40H中。
- 再进行一次双字节乘乘单字节,41H,40H乘R5,结果存储在47H,46H,45H中。
- 计算总费用FEE
- 判断路程是否大于2km,如果不大于,就向48H,49H,4AH中分别传入#0CH,#35H,#00H。
- 如果路程大于2km,则每次调用FEE函数时计算增加的路程,增加的路程存储在4EH,4FH中。
- 增加的路程4FH,4EH乘#26,得出本次调用增加的费用,存储在4DH,4CH,4BH中。
- 由于显示程序是三字节转10进制数,而1.83m*0.001m/km*2.6元/km已经有6位小数,如果直接把结果加上原有费用,则费用最多能显示16.77元。所以需要调用DIV1函数对结果除以10。
- 得到本次调用增加的费用后,加到原有的费用上再显示数字。
- 除法函数DIV1
- DIV1是一个除法函数,用于三字节数除以#10,用循环相减法实现。
- 显示结果DISDISTANCE、DISSPEED、DISFEE
- 把结果的高位、中位、低位分别传给42H、43H、44H。
- 再调用把双字节的十六进制数转换为BCD码的函数BinDec。
- 调用BinDec后50H~53H共存放了八位数字,根据所得结果小数点的位数,取用八位中的四位数字显示。
- 其中,带小数点的数,需要加10显示小数点。
- 数码管显示函数Display
- DispTable: DB 3FH, 06H, 5BH, 4FH, 66H, 6DH, 7DH, 07H, 7FH, 6FH ,0BFH, 86H, 0DBH, 0CFH, 0E6H, 0EDH, 0FDH, 87H, 0FFH, 0EFH;分别对应0-19,其中10+i表示带有小数点的数字i。
- 延时函数DELAY
- 和Display同时调用用于显示暂停后的费用。
- MAIN函数
- 设置寄存器、定时器、外部中断和定时器中断
- M1循环调用Display; DISTANCE; DISDISTANCE; DISSPEED; FEE; DISFEE;
- M2用于暂停显示路费。
三、作品截图
四、代码与相关注释
cDisplayBuffer EQU 30H ;在显示的内容在30H-37H
cDisplayBit EQU 3CH ;当前显示的位
circumference EQU 0B7H
ORG 0000H
LJMP Main
ORG 0003H
LJMP INT0PROC
ORG 000BH
LJMP SERVE
Main:
MOV cDisplayBuffer,#0
MOV cDisplayBuffer+1,#10
MOV cDisplayBuffer+2,#0
MOV cDisplayBuffer+3,#0
MOV cDisplayBuffer+4,#0
MOV cDisplayBuffer+5,#10
MOV cDisplayBuffer+6,#0
MOV cDisplayBuffer+7,#0
MOV cDisplayBuffer+8,#0
MOV cDisplayBuffer+9,#0
MOV cDisplayBuffer+10,#10
MOV cDisplayBuffer+11,#0
;寄存器设置
MOV R3,#0 ;记录轮胎圈数低位
MOV R4,#0 ;记录轮胎圈数高位
MOV R5,#0
MOV R6,#0 ;200*5MS
;定时器设置
MOV SP,#60H ;设置堆栈指针
MOV TMOD,#01H ;设置T0工作模式1
MOV TH0,#0DCH ;装计数值高八位
MOV TL0,#000H ;装计数值低八位;5MS
;外部中断
SETB EX0 ;外部0中断允许位
SETB IT0 ;
;定时器中断
SETB TR0 ;启动定时
SETB ET0 ;T0开中断
SETB EA ;CPU开中断
M1:
LCALL Display
LCALL DISTANCE ;计算距离
LCALL DISDISTANCE ;显示距离
LCALL DISSPEED ;显示速度
LCALL FEE ;计算费用
LCALL DISFEE ;显示费用
JNB P3.7,M1
M2:
LCALL Display
LCALL DELAY
JNB P3.7,Main
SJMP M2
;外部中断程序
INT0PROC:
PUSH PSW
PUSH ACC
JB P3.2,INT2
LCALL COUNT ;记录轮胎转过圈数
INT2:
POP ACC
POP PSW
RETI
;定时器中断程序
SERVE:
PUSH PSW
PUSH ACC
MOV TH0,#0DCH
MOV TL0,#000H
CPL P3.0
INC R6
MOV A,R6
CJNE A,#200,EXIT0
LCALL SPEED
MOV R6,#0
EXIT0:
POP ACC
POP PSW
RETI
;记录轮胎转过圈数
COUNT:
PUSH PSW
PUSH ACC
INC R5
INC R3
MOV A,R3
JNZ COUNT1
INC R4
COUNT1:
POP ACC
POP PSW
RET
;计算距离
DISTANCE:
MOV A,R3
MOV B,#circumference
MUL AB
MOV 3DH,A
MOV 3EH,B
MOV A,R4
MOV B,#circumference
MUL AB
ADD A,3EH
MOV 3EH,A
MOV A,B
ADDC A,#0
MOV 3FH,A
RET
;计算速度
SPEED:
PUSH ACC
MOV A,#36
MOV B,#circumference
MUL AB
MOV 40H,A
MOV 41H,B
MOV A,40H
MOV B,R5
MUL AB
MOV 45H,A
MOV 46H,B
MOV A,41H
MOV B,R5
MUL AB
ADD A,46H
MOV 46H,A
MOV A,B
ADDC A,#0
MOV 47H,A
MOV R5,#0
POP ACC
RET
;计算费用
FEE:
;R4R3=#1093=#445H
CLR C
MOV A,R3
SUBB A,#45H
MOV A,R4
SUBB A,#04H
JNC MULFEE
MOV 48H,#00H
MOV 49H,#35H
MOV 4AH,#0CH
MOV 4EH,3DH
MOV 4FH,3EH
JMP EXIT2
MULFEE:
CLR C
MOV A,3DH
SUBB A,4EH
MOV 4EH,A
MOV A,3EH
SUBB A,4FH
MOV 4FH,A
CLR C
MOV A,4EH
MOV B,#26
MUL AB
MOV 4BH,A
MOV 4CH,B
MOV A,4FH
MOV B,#26
MUL AB
ADD A,4CH
MOV 4CH,A
MOV A,B
ADDC A,#0
MOV 4DH,A
LCALL DIV1
;+8
MOV 4EH,3DH
MOV 4FH,3EH
CLR C
MOV A,4BH
ADDC A,48H
MOV 48H,A
MOV A,4CH
ADDC A,49H
MOV 49H,A
MOV A,4DH
ADDC A,4AH
MOV 4AH,A
EXIT2:
RET
DIV1:
PUSH 0
PUSH 1
PUSH 2
MOV R0,4BH
MOV R1,4CH
MOV R2,4DH
MOV 4BH,#0
MOV 4CH,#0
MOV 4DH,#0
LOOP:
CLR C
MOV A,R0
SUBB A,#10
MOV R0,A
MOV A,R1
SUBB A,#0
MOV R1,A
MOV A,R2
SUBB A,#0
MOV R2,A
JC EXIT3 ;C=1跳转
CLR C
MOV A,4BH
ADDC A,#1
MOV 4BH,A
MOV A,4CH
ADDC A,#0
MOV 4CH,A
MOV A,4DH
ADDC A,#0
MOV 4DH,A
SJMP LOOP
EXIT3:
POP 2
POP 1
POP 0
RET
;延时程序
DELAY:
MOV R0,#100
MOV R1,#10
DJNZ R1,$
DJNZ R0,$-4
RET
;显示费用
DISFEE:
MOV 42H,4AH ;高位字节
MOV 43H,49H ;中位
MOV 44H,48H ;低位
MOV R0,#42H
MOV R1,#50H
LCALL BinDec
MOV A,52H ;
SWAP A
ANL A,#0FH
MOV 33H,A ;千位
MOV A,51H ;
ANL A,#0FH
MOV 32H,A ;万位
MOV A,51H
SWAP A
ANL A,#0FH
ADD A,#10
MOV 31H,A ;十万位
MOV A,50H ;
ANL A,#0FH
MOV 30H,A ;百万位
RET
DISSPEED:
MOV 42H,47H ;高位字节
MOV 43H,46H
MOV 44H,45H ;低位字节
MOV R0,#42H
MOV R1,#50H
LCALL BinDec
MOV A,52H ;
ANL A,#0FH
MOV 3BH,A ;百位
MOV A,52H ;
SWAP A
ANL A,#0FH
ADD A,#10
MOV 3AH,A ;千位
MOV A,51H ;
ANL A,#0FH
MOV 39H,A ;万位
MOV A,51H
SWAP A
ANL A,#0FH
MOV 38H,A ;十万位
RET
DISDISTANCE:
MOV 42H,3FH ;高位字节
MOV 43H,3EH
MOV 44H,3DH ;低位字节
MOV R0,#42H
MOV R1,#50H
LCALL BinDec
MOV A,52H ;
SWAP A
ANL A,#0FH
MOV 37H,A ;千位
MOV A,51H ;
ANL A,#0FH
MOV 36H,A ;万位
MOV A,51H
SWAP A
ANL A,#0FH
ADD A,#10
MOV 35H,A ;十万位
MOV A,50H ;
ANL A,#0FH
MOV 34H,A ;百万位
MOV A,50H ;
RET
;---------------BinDec---------------------------
; 把双字节的十六进制数转换为BCD码
; 输入: R0 - 十六进制数的高字节地址
; R1 - 转换后BCD码的高位地址
BinDec:
CLR A
MOV @R1,A
INC R1
MOV @R1,A
INC R1
MOV @R1,A
INC R1
MOV @R1,A
PUSH 7
MOV R7,#24
BD1:
CLR C
INC R0
INC R0
MOV A,@R0
RLC A
MOV @R0,A
DEC R0
MOV A,@R0
RLC A
MOV @R0,A
DEC R0
MOV A,@R0
RLC A
MOV @R0,A
PUSH 1
MOV A,@R1
ADDC A,@R1
DA A
MOV @R1,A
DEC R1
MOV A,@R1
ADDC A,@R1
DA A
MOV @R1,A
DEC R1
MOV A,@R1
ADDC A,@R1
DA A
MOV @R1,A
DEC R1
MOV A,@R1
ADDC A,@R1
DA A
MOV @R1,A
POP 1
DJNZ R7,BD1
POP 7
RET
;---------------BinDec---------------------------
DispTable: DB 3FH, 06H, 5BH, 4FH, 66H, 6DH, 7DH, 07H, 7FH, 6FH ,0BFH, 86H, 0DBH, 0CFH, 0E6H, 0EDH, 0FDH, 87H, 0FFH, 0EFH
Display:
MOV A,cDisplayBit
MOV P2,A
MOV DPTR,#DispTable
MOV A,#cDisplayBuffer
ADD A,cDisplayBit
MOV R0,A
MOV A,@R0
MOVC A,@A+DPTR
MOV P1,A
INC cDisplayBit
ANL cDisplayBit,#15 ;12个数
RET
END
Post Views: 1,530
请问设计思路中,“判断路程是否大于 2km,如果不大于,就向 48H,49H,4AH 中分别传入 #0CH,#35H,#00H。”是什么意思呢,为什么要放这三个立即数。
不好意思,历史过于久远了。。。
我已经忘得一干二净了,我现在也不做这方面。
好的,还是很感谢,看了很有启发!