51单片机智能时控开关
;系统晶振是 11.0592 MHz
Z8279 EQU 0FF82H ;8279 状态/命令口地址
D8279 EQU 0FF80H ;8279 数据口地址
LEDMOD EQU 00H ;左边输入 八位字符显示
;外部译码键扫描方式,双键互锁
LEDFEQ EQU 2FH ;扫描速率
LEDCLS EQU 0C1H ;清除显示 RAM
LEDWR0 EQU 80H ;设定的将要写入的显示RAM地址
READKB EQU 40H ;读 FIFO RAM 地址 0 的命令字
SIGN EQU 08H ;00H设置为输入合法标志位
FLAG EQU 09H
KEY0 EQU 00H ;开关1状态
KEY1 EQU 01H ;开关2状态
KEY2 EQU 02H ;开关3状态
KEY3 EQU 03H ;开关4状态
KEY4 EQU 04H ;开关5状态
ORG 0000H
AJMP START
ORG 000BH ;T0中断程序入口地址
LJMP INT_T0
ORG 001BH ;T1 中断程序入口地址
LJMP INT_T1
ORG 0040H
START:
MOV SP,#60H
LCALL INIT8279 ;初始化8279
MOV R4,#12H ;时
MOV R3,#33H ;分
MOV R2,#54H ;秒
MOV R1,#20 ;秒
MOV R0 ,#30H ;开关定时时间存储器其始地址
MOV R7 ,#10
CLR KEY0 ;清楚开关状态标志
CLR KEY1
CLR KEY2
CLR KEY3
CLR KEY4
LOOP: MOV @R0,#0FFH
INC R0
DJNZ R7 ,LOOP
MOV P1,#00H
SETB SIGN ;标志
MOV TMOD,#11H
MOV TL1,#00H
MOV TH1,#4CH
MOV TL0,#8FH
MOV TH0,#0FCH
SETB ET0 ;中断允许
SETB PT1
SETB ET1
SETB EA ;允许断
WAIT: LCALL GETKEY ;读键盘
CJNE A,#0FFH,CONT ;判断是否有键输入
MOV A,B ;有键输入
CJNE A,#3CH,KEY_A ;输入键是'C',转CLEAR_T
LCALL CLEAR_T
KEY_A: CJNE A,#3AH,KEY_D ;输入键是'A',转START_T
LCALL START_T
KEY_D: CJNE A,#3DH,KEY_B ;输入键是'D',转STOP_T
LCALL STOP_T
KEY_B: CJNE A,#3BH,KEY_F ;输入键是'B',转SET_T
LCALL SET_T
KEY_F: CJNE A,#3FH,KEY_E ;输入键是'F',转DINGSHI_T
LCALL DINGSHI_T
KEY_E: CJNE A,#3EH,CONT ;输入键是'E',转MONITOR
LCALL MONITOR
CONT: JNB SIGN,WAIT ;若无秒标志则循环
LCALL DISPLAY ;显示时间
CLR SIGN ;清标志
SJMP WAIT ;循环
;实现外部干预子程序
MONITOR:NOP
JNB KEY0,L77
CLR P1.0
CLR KEY0
L77: JNB KEY1,L80
CLR P1.1
CLR KEY1
L80: JNB KEY2,L83
CLR P1.2
CLR KEY2
L83: JNB KEY3,L86
CLR P1.3
CLR KEY3
L86: JNB KEY4,L91
CLR P1.4
CLR KEY4
L91: CLR TR0
CLR P1.5
RET
SJMP $
;时间清零子程序
CLEAR_T:CLR TR1 ;关计数器
MOV R4,#0H ;小时清零
MOV R3,#0H ;分钟清零
MOV R2,#0H ;秒清零
SETB SIGN ;置秒标志
RET
;电子钟计时子程序
START_T:SETB TR1 ;开计时中断
RET
;电子钟停止计时子程序
STOP_T: CLR TR1 ;关计时中断
RET
;设置初值子程序
SET_T: CLR TR1 ;关计数器
MOV R5,#7
LCALL GETWORD ;读小时数
CJNE A,#0FFH,INVALID ;判断输入合法性
MOV A,B
ADD A,#232
JC INVALID ;判断输入小时值 < 24
MOV A,B
MOV B,#10
div AB
SWAP A
ADD A,B
MOV R4,A ;保存输入的值
MOV R5,#4 ;读分钟数
LCALL GETWORD
CJNE A,#0FFH,INVALID ;判断输入合法性
MOV A,B
ADD A,#196
JC INVALID ;判断输入分钟数 < 60
MOV A,B
MOV B,#10
div AB
SWAP A
ADD A,B
MOV R3,A ;保存输入的值
MOV R5,#1 ;读秒数
LCALL GETWORD
CJNE A,#0FFH,INVALID ;判断输入合法性
MOV A,B
ADD A,#196
JC INVALID ;判断输入分钟值 < 60
MOV A,B
MOV B,#10
div AB
SWAP A
ADD A,B
MOV R2,A ;保存输入的值
MOV R5,#1 ;读秒数
AJMP SET_TOK
INVALID:LCALL CLEAR_T ;不合法则时间清零
SET_TOK:LCALL DISPLAY ;显示时间
SETB TR1
RET
;设置定时时间子程序
DINGSHI_T:
SETBFLAG
MOV R0,#30H
MOV DPTR ,#Z8279
MOV A,#LEDCLS ;清除 LED 显示
MOVX @DPTR,A
MOV R5,#1
LCALL GETWORD ;选择设置定时开关通道
CJNE A,#0FFH,DINGSHI_T ;判断输入合法性
MOV A,B
ADD A,#251
JC DINGSHI_T ;判断输入小时值 < 5
MOV A,B
MOV B,#10
div AB
SWAP A
ADD A,B
MOV B,#2
MUL AB
ADD A,R0
MOV R0,A
MOV R5,#7
LCALL GETWORD
CJNE A,#0FFH,DINGSHI_T ;判断输入合法性
MOV A,B
ADD A,#232
JC DINGSHI_T ;判断输入分钟数 < 24
MOV A,B
MOV B,#10
div AB
SWAP A
ADD A,B
MOV @R0,A ;保存输入的值
INC R0
MOV R5,#4 ;读秒数
LCALL GETWORD
CJNE A,#0FFH,DINGSHI_T ;判断输入合法性
MOV A,B
ADD A,#196
JC DINGSHI_T ;判断输入分钟值 < 60
MOV A,B
MOV B,#10
div AB
SWAP A
ADD A,B
MOV @R0,A ;当通道选中时,LED亮提示通道被
;中
MOV A,30H
CJNE A,#0FFH,L196
CLR P1.0 ;如果开关0选中则LED0亮
AJMP L198
L196: SETB P1.0
L198: MOV A,32H
CJNE A,#0FFH,L199
CLR P1.1
AJMP L203
L199: SETB P1.1 ; 如果开关1选中则LED1亮
L203: MOV A,34H
CJNE A,#0FFH,L202
CLR P1.2
AJMP L207
L202: SETB P1.2 ;如果开关2选中则LED2亮
L207: MOV A,36H
CJNE A,#0FFH,L205
CLR P1.3
AJMP L213
L205: SETB P1.3 ;如果开关3选中则LED3亮
L213: MOV A,38H
CJNE A,#0FFH,L208
CLR P1.4
AJMP SET_TOKD
L208: SETB P1.4 ;如果开关4选中则LED4亮
SET_TOKD:
CLR FLAG
RET
;读数子程序
GETWORD:
WKEY1: LCALL GETKEY ;读键盘
CJNE A,#0FFH,WKEY1 ;无键输入,则再读
MOV A,B
ADD A,#0C6H
JC ERROR1 ;判断输入是否大于9
MOV A,B
SUBB A,#30H
JC ERROR1 ;判断输入是否小于0
MOV R6,A
LCALL DISLED ;显示输入的字符
MOV B,#10
MUL AB
PUSH ACC ;保存输入的值
WKEY2: LCALL GETKEY ;读键盘
CJNE A,#0FFH,WKEY2 ;无键输入则再读
MOV A,B
ADD A,#0C6H ;判断输入是否大于9
JC ERROR2
MOV A,B
SUBB A,#30H ;判断输入是否小于0
JC ERROR2
DEC R5
MOV R6,A
LCALL DISLED ;显示输入的字符
MOV B,A
POP ACC
ADD A,B
MOV B,A ;把得到的值存在B
MOV A,#0FFH ;置合法输入标志
AJMP KEYOK
ERROR2: POP ACC
ERROR1: MOV A,#0 ;置非法输入标志
KEYOK: RET
;8279初始化子程序
INIT8279:
PUSH DPH ;保存现场
PUSH DPL
PUSH ACC
LCALL DELAY ;延时
MOV DPTR ,#Z8279
MOV A,#LEDMOD ;置8279工作方式
MOVX @DPTR,A
MOV A,#LEDFEQ ;置键盘扫描速率
MOVX @DPTR,A
MOV A,#LEDCLS ;清除 LED 显示
MOVX @DPTR,A
POP ACC ;恢复现场
POP DPL
POP DPH
RET
;读取键盘子程序
;有输入则输出: B: 读到的键码 A: 按键的标志0FFH
GETKEY:PUSH DPH ;保存现场
PUSH DPL
PUSH PSW
MOV DPTR,#Z8279
MOVX A,@DPTR ;读8279状态
ANL A,#07H ;屏蔽D7-D3
JNZ GETVAL ;判断是否有键输入
MOV A,#0H ;置标志(无键输入)
SJMP NKBHIT
GETVAL: MOV A,#READKB ;读 FIFO RAM 命令
MOVX @DPTR,A
MOV DPTR,#D8279
MOVX A,@DPTR ;读键
ANL A,#3FH ;屏蔽 SHIFT 和 CTRL 键
MOV DPTR,#KEYCODE ;键码表起始地址
MOVC A,@A+DPTR ;查表
MOV B,A ;置返回键值
MOV A,#0FFH ;置标志(有键输入)
NKBHIT: POP PSW ;恢复现场
POP DPL
POP DPH
RET
;显示字符子程序
;输入: R5,位置 R6,值
DISLED: PUSH DPH ;保存现场
PUSH DPL
PUSH ACC
MOV A,#LEDWR0 ;置显示起始地址
ADD A,R5 ;加位置偏移量
MOV DPTR,#Z8279
MOVX @DPTR,A ;设定显示位置
MOV DPTR,#LEDSEG ;置显示常数表起始位置
MOV A,R6
MOVC A,@A+DPTR ;查表
MOV DPTR,#D8279
MOVX @DPTR,A ;显示数据
POP ACC ;恢复现场
POP DPL
POP DPH
RET
;延时子程序
DELAY: PUSH 7 ;保存现场
PUSH 1
MOV R7,#0H
DELAY1: MOV R1,#0H
DJNZ R1,$
DJNZ R7,DELAY1
POP 1 ;恢复现场
POP 7
RET
;定时器中断服务子程序
INT_T1:
;保护现场
PUSH PSW
PUSH ACC
PUSH DPL
PUSH DPH
CLR TR1 ;关中断
MOV TMOD,#11H
MOV TL1,#00H ;50ms毫秒定时常数
MOV TH1,#4CH
DJNZ R1,JUDGE
MOV R1,#20
CJNE R2,#59H,SEC
CJNE R3,#59H,MIN
CJNE R4,#23H,HOUR
MOV R2,#00
MOV R3,#00
MOV R4,#00
AJMP JUDGE
SEC: MOV A,R2
ADD A,#1
DA A
MOV R2,A
AJMP JUDGE
MIN: MOV A,R3
ADD A,#1
DA A
MOV R3,A
MOV R2,#00
AJMP JUDGE
HOUR: MOV A,R4
ADDA,#1
DA A
MOV R4,A
MOV R2,#00
MOV R3,#00
;判断定时是否到
JUDGE: ;判断开关1
MOV A,R4
CJNE A,30H,JUDGE_KEY1
MOV A,R3
CJNE A,31H,JUDGE_KEY1
SETB KEY0
MOV 30H,#0FFH
MOV 31H,#0FFH
SETB TR0
JUDGE_KEY1: MOV A,R4 ;判断开关2
CJNE A,32H,JUDGE_KEY2
MOV A,R3
CJNE A,33H,JUDGE_KEY2
SETB KEY1
MOV 32H,#0FFH
MOV 33H,#0FFH
SETB TR0
JUDGE_KEY2: MOV A,R4 ;判断开关3
CJNE A,34H,JUDGE_KEY3
MOV A,R3
CJNE A,35H,JUDGE_KEY3
SETB KEY2
MOV 34H,#0FFH
MOV 35H,#0FFH
SETB TR0
JUDGE_KEY3:MOVA,R4 ;判断开关4
CJNE A,36H,JUDGE_KEY4
MOV A,R3
CJNE A,37H,JUDGE_KEY4
SETB KEY3
MOV 36H,#0FFH
MOV 37H,#0FFH
SETB TR0
JUDGE_KEY4: MOV A,R4 ;判断开关5
CJNE A,38H,EXIT_INT
MOV A,R3
CJNE A,39H,EXIT_INT
SETB KEY4
MOV 38H,#0FFH
MOV 39H,#0FFH
SETB TR0
RET
;显示时间
EXIT_INT:
JB FLAG ,L431
LCALL DISPLAY
;恢复现场
L431:
SETB TR1
POP DPH
POP DPL
POP ACC
POP PSW
RETI ;中断返回
;定时器0产生蜂鸣器的频率
INT_T0:
CLR TR0
MOV TMOD ,#11H
MOV TL0,#67H
MOV TH0,#0FCH
SETB TR0
CPL P1.5 ;
RETI
;显示时分秒
DISPLAY:
MOV A,R4
ANL A,#0FH
MOV R6,A
MOV R5,#6
LCALL DISLED ;显示小时低位
MOV A,R4
SWAP A
ANL A,#0FH
MOV R6,A
MOV R5,#7
LCALL DISLED ;显示小时高位
MOV A,R3
ANL A,#0FH
MOV R6,A
MOV R5,#3
LCALL DISLED ;显示分钟低位
MOV A,R3
SWAP A
ANL A,#0FH
MOV R6,A
MOV R5,#4
LCALL DISLED ;显示分钟高位
MOV A,R2
ANL A,#0FH
MOV R6,A
MOV R5,#0
LCALL DISLED ;显示秒低位
MOV A,R2
SWAP A
ANL A,#0FH
MOV R6,A
MOV R5,#1
LCALL DISLED ;显示秒高位
JNB KEY0,L478
CPL P1.0 ;如果开关0的定时时间到,
;50ms是p1.0的电压反转
L478: JNB KEY1,L480
CPL P1.1
L480: JNB KEY2,L482
CPL P1.2
L482: JNB KEY3,L484
CPL P1.3
L484: JNB KEY4,L486
CPL P1.4
L486: RET
;LED显示常数表
LEDSEG: DB 3FH,06H,5BH,4FH,66H,6DH,7DH,07H;'0,1,2,3,4,5,6,7'
DB 7FH,6FH,77H,7CH,39H,5EH,79H,71H ;'8,9,A,B,C,D,E,F'
DB 0BFH,86H,0DBH,0CFH,0E6H,0EDH,0FDH,087H ;'0.,1.,2.,3.,4.,5.,6.,7.'
DB 0FFH,0EFH,0F7H,0FCH,0B9H,0DEH,0F9H,0F1H ;'8.,9.,A.,B.,C.,D.,E.,F.'
DB 6DH,02H,08H,00H,59H,0FH,76H ;'U,-,_, ,I,O,P, '
;键盘键码表
KEYCODE:DB 30H,31H,32H,33H,34H,35H,36H,37H;'1,2,Q,W,A,S,+,Z'
DB 38H,39H,3AH,3BH,3CH,3DH,3EH,3FH ;'3,4,E,R,D,F,X,C'
END
看见源码就头疼 还是汇编。
实验课的综合设计
用C语言好多年,汇编忘得差不多了~~~~汗颜~~~~~