作者:未知 来源:89s52.cn
;*************************************
;* *
;* 自 动 往 返 小 汽 车 *
;*************************************
;
;
;
;*************************************
;* *
;* 主程序和中断程序入口 *
;* *
;*************************************
;
ORG 0000H ;程序执行起始地址
LJMP START ;跳至START
ORG 0003H ;外中断0入口
LJMP INTEX0 ;跳至INTEX0中断服务程序
ORG 000BH ;定时器T0中断入口
RETI ;中断返回
ORG 0013H ;外中断1入口
LJMP INTEX1 ;跳至INTEX1中断服务程序
ORG 001BH ;定时器T1中断入口
LJMP INTT1 ;跳至INTT1中断服务程序
ORG 0023H ;串口中断入口
RETI ;中断返回
ORG 002BH ;定时器T2中断入口
RETI ;中断返回
;
;***************************
;* *
;* 初始化程序 *
;* *
;****************************
CLEARMEMIO: MOV R0, #70H ;清70H-76H显示单元
MOV R7, #07H ;循环次数
ML0: MOV @R0, #00H ;清0
INC R0 ;下一地址
DJNZ R7, ML0 ;未完再循环
MOV TMOD,#10H ;T1为16位定时器
MOV R4,#14H ;1秒定时用(50毫秒20次)
MOV TL1,#0B0H ;50毫秒定时用初值
MOV TH1,#3CH ;
MOV 20H,#00H ;清0操作
MOV 21H,#00H ;
MOV 22H,#00H ;
MOV 23H,#00H ;
MOV 24H,#00H ;
CLR 30H ;清停车标志
SETB ET1 ;开T1中断
SETB EX1 ;开外中断1
SETB IT1 ;外中断1采用边沿触发
SETB IT0 ;外中断0优先级为1(最高)
SETB EX0 ;开外中断0
SETB EA ;开总中断允许
SETB TR1 ;开启定时器T1
RET ;子程序返回
;
;*************************************
;* *
;* 主 程 序 *
;* *
;*************************************
;
START: LCALL CLEARMEMIO ;上电初始化
SETB P1.6 ;选择7.5V输出
CLR P1.7 ;选择7.5V输出
SETB P3.7 ;前进状态
CLR P3.6 ;前进状态
CLR P1.0 ;电机供电开始
MAIN: LCALL DISP ;LED显示一次
LJMP MAIN ;转MAIN循环
NOP ;PC值出错处理
NOP
LJMP START ;重新初始化
;
;*************************************
;* *
;*外中断0服务程序,用作跑道位置处理 *
;* 23H作跑道计数器 *
;*************************************
INTEX0: PUSH ACC ;堆栈保护
PUSH PSW ;
CLR EX0 ;关中断
LCALL DISP ;LED显示一次(延时抗干扰)
JB P3.2,IN0RET ;P3.2为1退出(干扰)
INC 23H ;跑道计数器加1
MOV A,23H ;数据入A
CJNE A,#06H,JUDGE1 ;不是第6道转JUDGE1
LCALL STOP ;是第6道,停车
LJMP IN0RET ;转中断退出
JUDGE1: CJNE A,#03H,JUDGE2 ;不是第3道转JUDGE2
LCALL STOPSLOW ;是第3道,变慢车
LJMP IN0RET ;转中断退出
JUDGE2: CJNE A,#04H,JUDGE3 ;不是第4道转JUDGE3
LCALL FAST ;是第4道,变快车
LJMP IN0RET ;转中断退出
JUDGE3: CJNE A,#05H,IN0RET ;不是第5道转INORET退出
LCALL STOPSLOW ;是第5道,变慢车
IN0RET: CLR IE0 ;清外中断0中断标志
POP PSW ;恢复现场
POP ACC ;
LCALL DL7MS ;延时7毫秒(抗干扰)
SETB EX0 ;开外中断0
RETI ;中断返回
;
;************************************
;* 慢车控制子程序 *
;************************************
STOPSLOW: CLR P1.6 ;关7.5V电源
CPL P3.6 ;反向驱动(刹车)
CPL P3.7 ;反向驱动
LCALL DS50MS ;刹车时间(可根据试车情况调整)
LCALL DS50MS ;
LCALL DS50MS ;
CPL P3.6 ;正向驱动
CPL P3.7 ;正向驱动
SETB P1.7 ;开4.3V电源
RET ;返回
;
;************************************
;* 快车控制子程序 *
;************************************
FAST: CLR P1.7 ; 关4.3V电源
SETB P1.6 ; 开7.5V电源
RET ;返回
;
;************************************
;* 停车控制程序 *
;************************************
STOP: MOV 23H,#00H ;跑道计数单元清0
CPL P3.6 ;反向驱动(刹车)
CPL P3.7 ;反向驱动(刹车)
LCALL DS50MS ;刹车时间
LCALL DS50MS ;刹车时间(可调整)
SETB P1.0 ;关电机电源
SETB PT1 ;定时器T1为高优先级
LCALL DS10S ;停车10秒
CLR PT1 ;恢复T1为低优先级
SETB P1.6 ;开7.5V电源(高速)
CLR P1.7 ;关4.3V
CLR P1.0 ;电机电源开
CPL 30H ;停车点位置判断标志取反
JB 30H,STREN ;为1(中途停车)转STREN
LCALL CLR00 ;是终点,调复0程序
STREN: RET ;返回
;
;*********************************
;* 计时清0程序 *
;*********************************
CLR00: MOV 70H,#00H ;计时单元清0
MOV 71H,#00H ;计时单元清0
MOV 72H,#00H ;计时单元清0
MOV 73H,#00H ;计时单元清0
RET ;返回
;
;*************************************
;* *
;* 外中断1程序,里程计数用 *
;* 20H、21H、22H、24H作计数器 *
;*************************************
INTEX1: PUSH ACC ;堆栈保护
PUSH PSW ;
CLR EX1 ;关外中断1
INC 20H ;圈加1
LLLL: MOV A,20H ;判断是否满6圈
CJNE A,#06H,LLL ;不满6圈转LLL退出
MOV 20H,#00H ;满6圈清0进位(6圈为1米)
INC 21H ;上位加1
MOV A,21H ;判断是否满10
CJNE A,#0AH,LLL ;不满10转LLL
MOV 21H,#00H ; 满10清0进1位
INC 22H ; 高位加1
MOV A,22H ; 判断是否满10
CJNE A,#0AH,LLL ; 不满10转LLL
MOV 22H,#00H ; 满10清0进1位
INC 24H ; 高位加1
MOV A,24H ; 判断是否满10
CJNE A,#0AH,LLL ; 不满10转LLL
MOV 24H,#00H ; 满10清0
LLL: MOV 74H,21H ; 将里程数移入显示单元(个位)
MOV 75H,22H ; 将里程数移入显示单元(十位)
MOV 76H,24H ; 将里程数移入显示单元(百位)
IN1RET: POP PSW ;恢复堆栈
POP ACC ;
SETB EX1 ;开外中断1
RETI ;中断返回
;
;*************************************
;* 时间计时器程序 *
;* (T1定时中断服务程序) *
;* *
;*************************************
INTT1: PUSH ACC ;堆栈保护
PUSH PSW ;
MOV TL1,#0B0H ;赋50毫秒定时初值
MOV TH1,#3CH ;
DEC R4 ;减1
MOV A,R4 ;
JNZ RETT0 ;不为0转RETT0
MOV R4,#14H ;为0(1秒到)重赋初值
MOV R0,#71H ;地址指向71H
ACALL ADD1 ;加1秒操作
MOV A,R3 ;
CLR C ;
CJNE A,#60H,CC ;是否为60秒?
CC: JC RETT0 ;小于60转RETT0
ACALL CLR0 ;大于或等于60清0
MOV R0,#73H ;指向分计时地址单元
ACALL ADD1 ;分加1
MOV A,R3 ;
CLR C ;
CJNE A,#60H,CCC ;是否为60分?
CCC: JC RETT0 ;小于60转RETT0
ACALL CLR0 ;大于或等于60分计时单元清0
RETT0: POP PSW ;恢复堆栈
POP ACC ;
RETI ;中断返回
;
;;;;;;;;;;;;;; ;;;;
; 加1操作程序 ;
;;;;;;;;;;;;;; ;;;;
ADD1: MOV A,@R0 ;取计数值
DEC R0 ;指向低一个地址
SWAP A ;计数值高低四位交换
ORL A,@R0 ;相或组合成一个数据
ADD A,#01H ;加1
DA A ;十进制调整
MOV R3,A ;暂存R3内
ANL A,#0FH ;高四位变0
MOV @R0,A ;放回低地址
MOV A,R3 ;取回R3内数据
INC R0 ;地址加1
SWAP A ;高低四位交换
ANL A,#0FH ;高四位为0
MOV @R0,A ;放回原地址
RET ;返回
;
;;;;;;;;;;;;;
; 清0程序 ;
;;;;;;;;;;;;;
CLR0: CLR A ;清A
MOV @R0,A ;对应地址单元清0
DEC R0 ;指向低一地址
MOV @R0,A ;清0
RET ;返回
;
;
;;;;;;;;;;;;;
; 显示程序 ;
;;;;;;;;;;;;;
DISP: MOV R1,#70H ;显示数据首址
MOV R5,#0FEH ;扫描字
PLAY: MOV A,R5 ;扫描字入A
MOV P2,A ;从P2口输出
MOV A,@R1 ;取显示数据
MOV DPTR,#TAB ;取段码表首址
MOVC A,@A+DPTR ; 查数据对应段码
MOV P0,A ;段码从P0口输出
LCALL DL1MS ;点亮1毫秒
INC R1 ;指向下显示数地址
MOV A,R5 ;扫描字入A
JNB ACC.6,ENDOUT ;ACC.6=0转ENDOUT结束
RL A ;循环左移
MOV R5,A ;放回A
AJMP PLAY ;转PLAY再显示
ENDOUT: MOV P2,#0FFH ;显示结束处理。P2口置1
RET ;子程序结束
;
;LED共阴段码表(0-9)
TAB: DB 0C0H,0F9H,0A4H,0B0H,99H,92H,82H,0F8H,80H,90H,0FFH
;
;1毫秒延时程序
DL1MS: MOV R6,#14H
DL1: MOV R7,#19H
DL2: DJNZ R7,DL2
DJNZ R6,DL1
RET
;
;延时程序,用调用显示程序实现,可使LED显示稳定
DS50MS: LCALL DISP ;(7毫秒)
LCALL DISP
LCALL DISP
DS20MS: LCALL DISP
LCALL DISP
LCALL DISP
RET
;
;10秒延时程序,用调用显示程序实现,可使LED显示不熄灭
DS10S: MOV R2,#08H ;(8*11*16*7=9956毫秒)
TI0: MOV R0,#0B0H
TI1: LCALL DISP
DJNZ R0,TI1
DJNZ R2,TI0
RET
;7毫秒延时程序,跑道计数器抗干扰用
DL7MS: SETB PX1 ;外中断1置高优先级
MOV R2,#0EH ;赋定时值
DL11: LCALL DISP ;调用显示程序
DJNZ R2,DL11 ;循环
CLR PX1 ;外中断1恢复低优先级
RET ;返回
;
END ;程序结束