ORG 0000H
LJMP MAIN
ORG 0003H ;定时器中断0
AJMP WAITKEYBEGIN
ORG 001BH ;定时器中断1
AJMP T1INT
ORG 0100H
;*********************************************************************************************************************************************************************
S1 EQU 30H
S2 EQU 31H
S3 EQU 32H
S4 EQU 33H
S5 EQU 34H
S6 EQU 35H
SS1 EQU 40H
SS2 EQU 41H
SS3 EQU 42H
SS4 EQU 43H
SS5 EQU 44H
SS6 EQU 45H
MAIN:
SETB IT0
SETB EX0
SETB EA
MOV SP, #60H
MOV A, #4
ACALL SENDNUM
LJMP WAITPEOPLE
;独立键盘检测********************************************************************************************设置倒计时初值*********************KEYTEST******************************************
WAITKEYBEGIN:
CJNE R7, #01H, KEYTEST
SETB P1.5
AJMP NEXTSTEP
KEYTEST:
MOV A, #0FFH
MOV P3, A
WAITKEY:
MOV A, P3 ;读键盘状态
XRL A, #0FFH ;REVERSE
ANL A, #0F0H
CJNE A, #00H, TESTAGAIN ;不全为0时,有键按下
SJMP WAITKEYBEGIN
TESTAGAIN:
ACALL DELAY_10MS ;延时10ms
MOV A, P3 ;读键盘状态
XRL A, #0FFH ;REVERSE
ANL A, #0F0H ;再次读键盘状态
CJNE A, #00H, RUNKEY ;确实有键按下
SJMP WAITKEY
RUNKEY:
JNB P3.7, K4
JNB P3.6, K3
JNB P3.5, K2
SJMP WAITKEY
K1:
MOV A, #20
AJMP WAITPEOPLE
K2:
MOV R7, #01H
CLR P1.5
SJMP WAITKEYBEGIN
K3:
ACALL ADDNUM
ACALL SHOWNUM
SJMP WAITKEYBEGIN
K4:
ACALL SUBNUM
ACALL SHOWNUM
SJMP WAITKEYBEGIN
NEXTSTEP:
RETI
;***************************************************************************************************检测外界信号*******************WAITPEOPLE*****************************************
WAITPEOPLE:
SETB IT1 ;人体感应对应接入的外部中断,设置下降沿触发中断
WAITCOME:
JNB P2.1, WAITCOME ;白天输出低电平0,则一直等待,直到输出高电平
MOV C, P2.2 ;有声音时P3.2是低电平
CPL C
JC WAITUP ;C等于1的时候,外部声音输入为0,已经检测到声音,等于一跳转,等待声音结束
MOV C, P3.3
CPL C
JNC WAITDOWN ;C等于0的时候,外部感应输入为1,已经检测到人体,跳转,等待下降沿到来
SJMP WAITPEOPLE
WAITDOWN:
CLR P1.1 ;点亮P1.1指示灯
CLR P1.7 ;点亮P1.7模拟光
JNB IE1, WAITDOWN ;IE1=0,下降沿还未到来,继续等待下降沿,等于零转移
CLR IE1 ;清除人体感应中断请求
SJMP SETLIGHT ;跳转设置开灯
WAITUP:
CLR P1.3 ;点亮P1.0指示灯
CLR P1.7 ;点亮P1.7模拟光
SJMP SETLIGHT ;IE0=1,声音感应信号低电平出现,跳转设置开灯
SETLIGHT:
ACALL INT133
LJMP WAITPEOPLE
;数码管倒计时显示子程序******************************************************************在调用前往30H,31H送好倒计时初值***************DISPLAYBEGIN*************************
DISPLAYBEGIN:
MOV 40H, 30H
MOV 41H, 31H
MOV 42H, 32H
MOV 43H, 33H
MOV 44H, 34H
MOV 45H, 35H
DISPBEGIN:
MOV R6, #20 ;;;;;;;;;;R6 R6 R6 R6 R6
DISPBEGIN1:
MOV TMOD, #01H ;T0工作在定时工作方式1
MOV TH0, #4CH ;定时0.05s
MOV TL0, #00H
SETB TR0 ;开启定时器开始定时
DISP:
MOV R0, #40H ;要显示的数字存储首地址 ;;;;;;;;;;;;;;;R0 R0 R0 R0 R0
MOV R2, #0DFH ;11011111 ;;;;;;;;;;;;;;;;;R2 R2 R2 R2 R2
MOV R7, #2 ;控制循环次数 控制显示的位数;;;;;;;;;;;;;;;;R7 R7 R7 R7 R7
DISPLAY:
MOV A, R2 ;选择要亮的数码管 R2
SETB P2.7 ;开锁存器
MOV P0, A ;为0时选定对应数码管
CLR P2.7 ;关锁存器
MOV A, @R0 ;R0存的为要显示的数值 R0
MOV DPTR, #SEGTAB ;查表获得显示特定数值需要的码
MOVC A, @A+DPTR ;设置要显示的数字
SETB P2.6 ;开锁存器
MOV P0, A ;为1时选定对应段
ACALL DELAY_1MS ;延时1ms
CLR P2.6 ;关锁存器
DJNZ R7, DISPLOOP ;扫描完一个,显示下一个,扫描完六个(R7=0),重新扫描 R7
LJMP NEXT
RET
DISPLOOP:
INC R0 ;取下一个数码管要显示的数字 R0
MOV A, R2 ;下一个要亮的数码管 R2
RR A
MOV R2, A
LJMP DISPLAY
NEXT:
JNB TF0, DISP ;;;;;;有没有过0.05s
CPL TF0
DEC R6
CJNE R6, #00H, DISPBEGIN1 ;R6不等于零时转移,说明还没到一秒
MOV A, 40H
CJNE A, #00H, RUNS1 ;个位还没有减为零跳转
MOV A, 41H ;个位为零时,判断十位是不是零
CJNE A, #00H, RUNS2 ;十位不为零跳转
MOV A, #0FFH ;关闭数码管
SETB P2.7 ;开锁存器
MOV P0, A ;关掉所有数码管
CLR P2.7 ;关锁存器
RET
RUNS1:
DEC 40H
LJMP DISPBEGIN
RUNS2:
DEC 41H
MOV 40H, #9
LJMP DISPBEGIN
;显示键盘对应数字***************************************************************在调用前往30H,31H送好倒计时初值**************************SHOWNUM**********************************************
SHOWNUM:
MOV 40H, 30H
MOV 41H, 31H
MOV 42H, 32H
MOV 43H, 33H
MOV 44H, 34H
MOV 45H, 35H
DISPNUMBEGIN:
MOV R6, #10 ;;;;;;;;;;R6 R6 R6 R6 R6
DISPNUMBEGIN1:
MOV TMOD, #01H ;T0工作在定时工作方式1
MOV TH0, #4CH ;定时0.05s
MOV TL0, #00H
SETB TR0 ;开启定时器开始定时
DISPNUM:
MOV R0, #40H ;要显示的数字存储首地址 ;;;;;;;;;;;;;;;R0 R0 R0 R0 R0
MOV R2, #0DFH ;11011111 ;;;;;;;;;;;;;;;R2 R2 R2 R2 R2
MOV R7, #2 ;控制循环次数 控制显示的位数 ;;;;;;;;;;;;;;;R7 R7 R7 R7 R7
DISPLAYNUM:
MOV A, R2 ;选择要亮的数码管 R2
SETB P2.7 ;开锁存器
MOV P0, A ;为0时选定对应数码管
CLR P2.7 ;关锁存器
MOV A, @R0 ;R0存的为要显示的数值 R0
MOV DPTR, #SEGTAB ;查表获得显示特定数值需要的码
MOVC A, @A+DPTR ;设置要显示的数字
SETB P2.6 ;开锁存器
MOV P0, A ;为1时选定对应段
ACALL DELAY_1MS ;延时1ms
CLR P2.6 ;关锁存器
DJNZ R7, DISPNUMLOOP ;扫描完一个,显示下一个,扫描完六个(R7=0),重新扫描 R7
LJMP NEXTNUM
RET
DISPNUMLOOP:
INC R0 ;取下一个数码管要显示的数字 R0
MOV A, R2 ;下一个要亮的数码管 R2
RR A
MOV R2, A
LJMP DISPLAYNUM
NEXTNUM:
JNB TF0, DISPNUM ;有没有过0.05s
CPL TF0
DEC R6
CJNE R6, #00H, DISPNUMBEGIN1 ;R6不等于零时转移,说明还没到一秒
MOV A, #0FFH ;关闭数码管
SETB P2.7 ;开锁存器
MOV P0, A ;关掉所有数码管
CLR P2.7 ;关锁存器
RET
;延时子程序**********************************************************************延时一毫秒,调用前无需操作******************************DELAY_1MS******************************************
DELAY_1MS:
MOV R3, #180 ;1ms ;;;;;;;;;;;;;;;;;;;;;;;;;;R3 R3 R3 R3 R3
LOOP_1MS:
MOV R4, #1 ;;;;;;;;;;;;;;;;;;;;;;;;;R4 R4 R4 R4 R4
DJNZ R4, $ ;R4
DJNZ R3, LOOP_1MS ;R3
RET
;延时子程序**********************************************************************延时10毫秒,调用前无需操作*****************************DELAY_10MS*******************************************
DELAY_10MS:
MOV R3, #180 ;1ms ;;;;;;;;;;;;;;;;;;;;;;;;;;R3 R3 R3 R3 R3
LOOP_10MS:
MOV R4, #24 ;;;;;;;;;;;;;;;;;;;;;;;;;R4 R4 R4 R4 R4
DJNZ R4, $ ;R4
DJNZ R3, LOOP_10MS ;R3
RET
;定时器1中断******************************************************************中断计时50ms,中断前需设置好R5的值**************************T1INT**********************************************
T1INT:
MOV TH1, #4CH ;定时R5个0.05s
MOV TL1, #00H
DJNZ R5, T1INTLOOP ;R5
;MOV P1, #44H
CLR TR1
T1INTLOOP:
RETI
;根据按键值,设置显示缓冲区中的数字***************************************************调用前需要设置好A的值*******************************SENDNUM*****************************************
SENDNUM:
MOV B, #10
DIV AB ;当前值除以10
MOV 31H, A ;得出的商送给十位
MOV 30H, B ;得出的余数送给个位
RET
;控制关灯子程序****************************************************************************************************************************INT133*******************
INT133:
SETB P1.3 ;关指示灯
SETB P1.1 ;关指示灯
ACALL DISPLAYBEGIN ;延时,同时数码管显示倒计时
SETB P1.7 ;关模拟灯
RET
;************************************************************************************************************************************************************
ADDNUM: ;加一
MOV R6, 30H ;个位
MOV R7, 31H ;十位
CJNE R6, #09, ADDONE ;不等于9的时候直接加一
CJNE R7, #09, ADDONEONE ;十位不是9的时候加一 不相等跳转
SJMP ASENDBACK ;十位是9,返回
ADDONEONE:
INC R7 ;个位等于9的时候给十位加一
MOV R6, #00H
SJMP ASENDBACK
ADDONE:
INC R6
ASENDBACK:
MOV 30H, R6
MOV 31H, R7
RET
;*************************************************************************************************************************************************************
SUBNUM:
MOV R6, 30H ;个位
MOV R7, 31H ;十位
CJNE R6, #00, SUBONE ;不等于0的时候直接减一
CJNE R7, #00, SUBONEONE ;十位不等于零的时候,给十位减一
SJMP SSENDBACK
SUBONEONE:
DEC R7 ;等于0的时候给十位减一
MOV R6, #09H
SJMP SSENDBACK
SUBONE:
DEC R6
SSENDBACK:
MOV 30H, R6
MOV 31H, R7
RET
;数码管显示数字表*************************************************************************数字对应的BCD码表**********************************SEGTAB**************************************
SEGTAB:
DB 3FH,06H,5BH,4FH,66H ;0,1,2,3,4
DB 6DH,7DH,07H,7FH,6FH ;5,6,7,8,9
END