单片机大作业:出租车计费器
目录
一、设计要求
- 设计一个出租车计费器程序(含原理图),要求如下:
- 用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