;******************************************************
;*标题: 单片机遥控电子钟程序
;*文件:
;*版本: 1.0
;*作者: 东哥
;*邮箱: picavr@163.com QQ: 279068079
;*******************************************************
K1 BIT P3.2 ;切换当前时间,开机时间,关机时间(P3.2口定义为K1)
K2 BIT P3.4 ;调时键K2(P3.4 口定义为K2)
K3 BIT P3.5 ;调分键K3(P3.5 口定义为K3)
K4 BIT P3.6 ;启动键K4(P3.6 口定义为K4)
SI BIT P3.3 ;遥控輸入口定义为SI
C_HOUR EQU 24H ;当前时的地址定义
C_MINUTE EQU 25H ;当前分的地址定义
C_SECOND EQU 26H ;当前秒的地址定义
ON_HOUR EQU 27H ;开机时的地址定义
ON_MINUTE EQU 28H ;开机分的地址定义
OFF_HOUR EQU 29H ;关机时的地址定义
OFF_MINUTE EQU 30H ;关机分的地址定义
WORK_MODE EQU 34H ;当前时间,开机时间,关机时间选择
USE_CODE EQU 35H ;用戶數據代碼地址定义
DATA_CODE EQU 36H ;數據代碼地址定义
COUNT EQU 50H ;計數地址定义
;******************************************************************************
ORG 0000H ;主程序入口地址
AJMP MAIN ;转主程序
ORG 0003H ;外中断0中断入口
AJMP INTEX0 ;跳至INTEX0执行中断服务程序
ORG 000BH ;定时器T0中断入口地址
AJMP WTO ;跳至定时器T0执行中断服务程序
ORG 0013H ;外中断1中断入口
LJMP INTEX1 ;跳至INTEX1执行中断服务程序
ORG 001BH ;定时器T1中断入口地址
RETI ;中断返回(不开中断)
ORG 0023H ;串行口中断入口地址
RETI ;中断返回(不开中断)
ORG 002BH ;定时器T2中断入口地址
RETI ;中断返回(不开中断)
;******************************************************************************
;* 主程序 *
;******************************************************************************
ORG 0030H
MAIN: MOV SP,#50H ;堆栈指针入口地址
CLR 00H ;清开始调整标志
CLR 01H ;清当前时间标志
CLR 02H ;清开机时间标志
CLR 03H ;清关机时间标志
CLR 04H ;遥控用戶識別标志
MOV 21H,#0 ;10MS定时中断计数器初值
MOV 22H,#0 ;500MS定时中断计数器初值
MOV C_HOUR,#0
MOV C_MINUTE,#0
MOV C_SECOND,#0 ;置当前时间为00:00:00
MOV ON_HOUR,#06H
MOV ON_MINUTE,#00H ;置开机时间为06:00
MOV OFF_HOUR,#12H
MOV OFF_MINUTE,#00H ;置关机时间为12:00
MOV WORK_MODE,#0 ;
MOV USE_CODE,#00H ;用戶數據代碼為00
MOV DATA_CODE,#00H ;數據代碼為00
MOV R6,#8 ;數據為8位
MOV TH0,#0D8H ;T0 10ms定时初值
MOV TL0,#0F0H ;T0 10ms定时初值
MOV TH1,#00H ;T1 定时初值為00
MOV TL1,#00H ;T1 定时初值為00
MOV TMOD,#11H ;T0 方式1设定
MOV IE,#00H ;关所有中断
CLR A ;
DEC A ;A为#0FFH
MOV P0,A ;P1-P3口置1
MOV P1,A ;
MOV P2,A ;
MOV P3,A ;
SETB EA ;开CPU中断
SETB EX1 ;开外中断
SETB EX0 ;开INT0中断请求
CLR ET0 ;禁止T0中断
CLR TR0 ;禁止T0计数
CLR IT0 ;置INT0为电平触发
SETB IT1 ;置INT1为邊沿触发
SETB PX1 ;置INT1为最高级中断
SETB P3.7 ;置开关输出控制端口P3.7为"1"
M: MOV A,C_HOUR
CJNE A,ON_HOUR,OFF_TIME
MOV A,C_MINUTE ;判断当前时间是否等於开机时间
CJNE A,ON_MINUTE,OFF_TIME
CLR P3.7 ;置开关输出控制端口P3.7为"0"
AJMP NEXT
OFF_TIME: MOV A,C_HOUR
CJNE A,OFF_HOUR,NEXT
MOV A,C_MINUTE
CJNE A,OFF_MINUTE,NEXT;判断当前时间是否等於关机时间
SETB P3.7 ;置开关输出控制端口P3.7为"1"
NEXT: JNB 01H,ONDISP
ACALL DISP1 ;调当前时间显示子程序
ONDISP: JNB 02H,OFFDISP
ACALL DISP2 ;调开机时间显示子程序
OFFDISP: JNB 03H,M
ACALL DISP3 ;调关机时间显示子程序
AJMP M ;转 M 循环
NOP ;PC值出错处理
NOP
NOP
AJMP MAIN ;重新初始化
TAB: DB 0C0H,0F9H,0A4H,0B0H,99H ;显示代码数据
DB 92H,82H,0F8H,80H,90H
;*******************************************************************************************************
;* 当前时间显示子程序 *
;*******************************************************************************************************
DISP1: MOV R0,C_HOUR
MOV DPTR,#TAB ;笔划段码表指针
MOV A,R0
SWAP A
ANL A,#0FH
MOVC A,@A+DPTR
MOV P1,A
CLR P2.0
ACALL DL ;送显时高位
SETB P2.0
MOV A,R0
ANL A,#0FH
MOVC A,@A+DPTR
MOV P1,A
CLR P2.1
ACALL DL
SETB P2.1 ;送显时低位
MOV R1,C_MINUTE
MOV A,R1
SWAP A
ANL A,#0FH
MOVC A,@A+DPTR
MOV P1,A
CLR P2.2
ACALL DL
SETB P2.2 ;送显分高位
MOV A,R1
ANL A,#0FH
MOVC A,@A+DPTR
MOV P1,A
CLR P2.3
ACALL DL
SETB P2.3 ;送显分低位
MOV R2,C_SECOND
MOV A,R2
SWAP A
ANL A,#0FH
MOVC A,@A+DPTR
MOV P1,A
CLR P2.4
ACALL DL
SETB P2.4 ;送显秒高位
MOV A,R2
ANL A,#0FH
MOVC A,@A+DPTR
MOV P1,A
CLR P2.5
ACALL DL
SETB P2.5 ;送显秒低位
RET
;*************************************************************************************************************
;* 定时器T0中断服务子程序 *
;*************************************************************************************************************
WTO: PUSH ACC ;保护现场
PUSH PSW
MOV A,#0B7H ;中断响应时间同步修正
ADD A,TL0 ;低8位初值修正
MOV TL0,A ;重装初值(低8位修正值)
MOV A,#0F0H ;高8位初值修正
ADDC A,TH0 ;
MOV TH0,A ;重装初值(高8位修正值)
INC 21H
MOV A,21H
CJNE A,#50,TORETI ;10mS * 50mS=0.5S
MOV 21H,#0
INC 22H
MOV A,22H
CJNE A,#2,TORETI ;0.5S * 2 =1S
MOV 22H,#0
CPL P0.0 ;秒指示
CPL P0.1
MOV A,#01H
ADD A,C_SECOND
DA A
MOV C_SECOND,A ;当前秒加1
CJNE A,#60H,TORETI ;为60吗(是秒清0,否返回)
MOV C_SECOND,#0
MOV A,#01H
ADD A,C_MINUTE
DA A
MOV C_MINUTE,A ;当前分加1
CJNE A,#60H,TORETI ;为60吗(是分清0,否返回)
MOV C_MINUTE,#0
MOV A,#01H
ADD A,C_HOUR
DA A
MOV C_HOUR,A ;当前时加1
CJNE A,#24H,TORETI ;为24吗(是时清0,否返回)
MOV C_HOUR,#0
TORETI: POP PSW ;恢复现场
POP ACC
RETI
;**************************************************************************************************
; 开机时间显示子程序 *
;**************************************************************************************************
DISP2: MOV R0,ON_HOUR
MOV DPTR,#TAB ;笔划段码表指针
MOV A,R0
SWAP A
ANL A,#0FH
MOVC A,@A+DPTR
MOV P1,A
CLR P2.0
ACALL DL ;送显时高位
SETB P2.0
MOV A,R0
ANL A,#0FH
MOVC A,@A+DPTR
MOV P1,A
CLR P2.1
ACALL DL ;送显时低位
SETB P2.1
MOV R1,ON_MINUTE
MOV A,R1
SWAP A
ANL A,#0FH
MOVC A,@A+DPTR
MOV P1,A
CLR P2.2
ACALL DL ;送显分高位
SETB P2.2
MOV A,R1
ANL A,#0FH
MOVC A,@A+DPTR
MOV P1,A
CLR P2.3
ACALL DL ;送显分低位
SETB P2.3
RET
;*************************************************************************************************
; 关机时间显示子程序 *
;*************************************************************************************************
DISP3: MOV R0,OFF_HOUR
MOV DPTR,#TAB ;笔划段码表指针
MOV A,R0
SWAP A
ANL A,#0FH
MOVC A,@A+DPTR
MOV P1,A
CLR P2.0
ACALL DL ;送显时高位
SETB P2.0
MOV A,R0
ANL A,#0FH
MOVC A,@A+DPTR
MOV P1,A
CLR P2.1
ACALL DL ;送显时低位
SETB P2.1
MOV R1,OFF_MINUTE
MOV A,R1
SWAP A
ANL A,#0FH
MOVC A,@A+DPTR
MOV P1,A
CLR P2.2
ACALL DL ;送显分高位
SETB P2.2
MOV A,R1
ANL A,#0FH
MOVC A,@A+DPTR
MOV P1,A
CLR P2.3
ACALL DL ;送显分低位
SETB P2.3
RET
;************************************************************************************************************
; 延时0.16ms子程序 *
;************************************************************************************************************
DL: MOV 31H,#80
DL2: DJNZ 31H,DL2
RET
;****************************************************************************************************
; 延时10MS子程序,用於消除按键抖动而产生误动作 *
;****************************************************************************************************
DEL: MOV 32H,#200
DEL1: MOV 33H,#250
DEL2: DJNZ 33H,DEL2
DJNZ 32H,DEL1
RET
;*************************************************************************************************************
; 按键中断处理子程序 *
;*************************************************************************************************************
INTEX0: PUSH ACC ;保护现场
PUSH PSW
CLR EX0 ;关外部中断INT0
JB K1,$ ;判断K1按下否,未按则等待,K1按下
;LED1亮, LED2熄灭
DISP1_0: ACALL DISP1 ;
JNB K1,DISP1_0 ;等待K1释放
ACALL DEL ;K1按下开机指示LED1亮,LED2熄灭
PH4: CLR P3.1 ;LED1亮
SETB P3.0 ;LED2熄灭
PH0: ACALL DISP1 ;调当前时间显示子程
JB K2,PH01 ;判K2按下否,未按则转到判K3
DISP1_1: ACALL DISP1 ;
JNB K2,DISP1_1 ;等待K2释放
ACALL DEL
MOV R0,C_HOUR
MOV A,#01H
ADD A,R0
DA A
MOV C_HOUR,A ;当前时间时加1
CJNE A,#24H,PH0 ;超过24吗(超过清0)
MOV C_HOUR,#0
PH01: JB K3,PH1 ;判K3按下否,未按则转判K4
DISP1_2: ACALL DISP1 ;
JNB K3,DISP1_2 ;等待K3释放
ACALL DEL
MOV R0,C_MINUTE
MOV A,#01H
ADD A,R0
DA A
MOV C_MINUTE,A ;当前时间分加1
CJNE A,#60H,PH0 ;超过60吗(超过清0)
MOV C_MINUTE,#0
PH1: JB K4,PH10 ;判K4按下否,未按则转到判K1
DISP1_3: ACALL DISP1 ;
JNB K4,$ ;等待K4释放
ACALL DEL
AJMP TEND ;K4按下,转启动
PH10: JB K1,PH0 ;判K1按下否,未按则再
DISP1_4: ACALL DISP1 ;
JNB K1,DISP1_4 ;等待K1释放
ACALL DEL ;K1按下开机指示LED1熄灭,LED2亮
SETB P3.1 ;LED1熄灭
CLR P3.0 ;LED2亮
PH2: ACALL DISP2 ;调开机时间显示子程序
JB K2,PH201 ;判K2按下否,未按则转到判K3
DISP2_1: ACALL DISP2 ;
JNB K2,DISP2_1 ;等待K2释放
MOV R0,ON_HOUR
MOV A,#01H
ADD A,R0
DA A
MOV ON_HOUR,A ;开机时间时加1
CJNE A,#24H,PH2 ;超过24吗(超过清0)
MOV ON_HOUR,#0
PH201: JB K3,PH210 ;判K3按下否,未按则转判K4
DISP2_2: ACALL DISP2 ;
JNB K3,DISP2_2 ;等待K3释放
ACALL DEL
MOV R0,ON_MINUTE
MOV A,#01H
ADD A,R0
DA A
MOV ON_MINUTE,A ;开机时间分加1
CJNE A,#60H,PH2 ;超过60吗(超过清0)
MOV ON_MINUTE,#0
PH210: JB K1,PH2 ;判K1按下否,未按则再
DISP2_3: ACALL DISP2 ;
JNB K1,DISP2_3 ;等待K1释放
ACALL DEL ;K1按下关机指示LED1. LED2亮
CLR P3.0 ;LED1亮
CLR P3.1 ;LED2亮
PH3: ACALL DISP3 ;调关机时间显示子程序
JB K2,PH301 ;判K2按下否,未按则转到判K3
DISP3_1: ACALL DISP3 ;
JNB K2,DISP3_1 ;等待K2释放
ACALL DEL
MOV R0,OFF_HOUR
MOV A,#01H
ADD A,R0
DA A
MOV OFF_HOUR,A ;关机时间时加1
CJNE A,#24H,PH3 ;超过24吗(超过清0)
MOV OFF_HOUR,#0
PH301: JB K3,PH310 ;判K3按下否,未按则转判K4
DISP3_2: ACALL DISP3 ;
JNB K3,DISP3_2 ;等待K3释放
ACALL DEL
MOV R0,OFF_MINUTE
MOV A,#01H
ADD A,R0
DA A
MOV OFF_MINUTE,A ;关机时间分加1
CJNE A,#60H,PH3 ;超过60吗(超过清0)
MOV OFF_MINUTE,#0
PH310: JB K1,PH3 ;判K1按下否,未按则再
DISP3_3: ACALL DISP3 ;
JNB K1,DISP3_3 ;等待K1释放
ACALL DEL
AJMP PH4 ;转当前时间调整
TEND: SETB EX0 ;开INT0中断
SETB TR0 ;允许T0计数
SETB 01H ;置00H为1,启动计数
SETB ET0 ;允许T0中断
SETB P3.7 ;置P3.7口为1
POP PSW ;恢复现场
POP ACC
RETI ;中断返回
;**********************************************************************
;;;;;;;;;;;;;;;;;;;;;;;;; 遥控接收程序 ;;;;;;;;;;;;;;;;;;;;;;;
;**********************************************************************
;采用中断接收
INTEX1:
CLR EA ;
CLR TR1 ;
JNB SI,$ ;
NOP
NOP
JNB SI,$
SETB TR1 ;
MOV R2,TH1 ;取T0计数次数
MOV R3,TL1
MOV R4,#00H ;0096H~03B6H为数据窗口0
MOV R5,#96H ;窗口0的下限
LCALL SUB0 ;计数值小于00FAH吗?
JC ERROUT ;<0096H,作废
MOV R4,#03H ;窗口0的上限
MOV R5,#0B6H
MOV R2,TH1 ;取T0计数次数
MOV R3,TL1
LCALL SUB0 ;计数值大于03B6H吗?
JNC X1_01 ;>03B6,去看是否在1的窗口
CLR C ;在窗口0中,清C,移位时移入0
LJMP SET_CODE_0 ;去移位处理
X1_01: MOV R4,#04H ;窗口1的下限
MOV R5,#4CH ;044CH~073AH为窗口1
MOV R2,TH1 ;取T0计数次数
MOV R3,TL1
LCALL SUB0 ;计数值小于044CH吗?
JC ERROUT ;<044CH,作废
MOV R4,#07H ;窗口1的上限
MOV R5,#3AH ;#073A
MOV R2,TH1 ;取T1计数次数
MOV R3,TL1
LCALL SUB0 ;计数值大于#073AH吗?
JNC ERROUT ;>073AH,作废
SETB C ;在窗口1中,将C置1
SET_CODE_0:
JB 04H,NEXT ;
MOV A,USE_CODE ;
RLC A ;
MOV USE_CODE,A ;
DJNZ COUNT,ERROUT ;
MOV COUNT,#8 ;
MOV A,USE_CODE ;
CJNE A,#0E2H,ERROUT ;
SETB 04H ;
;**********************************************
ERROUT:
MOV TH1,#00H ;
MOV TL1,#00H ;
SETB TR1 ;
SETB EA ;
RETI ;
;*********************************************
NEXT:
MOV A,DATA_CODE ;
RLC A ;
MOV DATA_CODE,A ;
DJNZ R6,ERROUT ;
MOV R6,#8 ;
CLR 04H ;
;*********************************************
MOV A,DATA_CODE ;
CJNE A,#00H,CH1 ;
AJMP FUN1 ;
CH1: CJNE A,#10H,CH2 ;
AJMP FUN2 ;
CH2: CJNE A,#08H,CH3 ;
AJMP FUN3 ;
CH3: CJNE A,#80H,CH4 ;
AJMP FUN4 ;
CH4: CJNE A,#90H,CH5 ;
AJMP ERROUT ;
CH5: CJNE A,#88H,CH6 ;
AJMP ERROUT ;
CH6: CJNE A,#4H,CH7 ;
AJMP ERROUT ;
CH7: CJNE A,#50H,CH8 ;
CH8: AJMP ERROUT ;
;********************************************************
SUB0: CLR C ;减法子程序
MOV A,R3 ;被减数低位送A
SUBB A,R5 ;低位减
JNC X1_S1 ;没进位,去处理高位减法
DEC R2 ;有进位,被减数高位减1
X1_S1: CLR C ;清C
MOV A,R2 ;被减数高位
SUBB A,R4 ;减被减数高位
RET ;返回
;*********************************************************************
;* 遥控切换当前时间,开机时间,关机时间调整程序 *
;*********************************************************************
FUN1: CLR TR0 ;禁止T0计数
CLR ET0 ;禁止T0中断
INC WORK_MODE ;时间选择寄存器加"1"
MOV A,WORK_MODE
CJNE A,#01H,ONHOUR ;选择寄存器为"1",转开机调整标志
SETB 00H ;置开始调整标志为"1"
SETB 01H ;置当前时间标志为"1"
CLR 02H ;清开机时间标志
CLR 03H ;清关机时间标志
CLR P3.0 ;LED1亮
SETB P3.1 ;LED2灭
AJMP EXIT ;转中断退出
ONHOUR: CJNE A,#02H,OFFHOUR ;选择寄存器为"2",转关机调整标志
CLR 01H ;清当前时间标志
SETB 02H ;置开机时间标志为"1"
CLR 03H ;清关机时间标志
CLR P3.1 ;LED2亮
SETB P3.0 ;LED1灭
AJMP EXIT ;转中断退出
OFFHOUR: CJNE A,#03H,EXIT ;选择寄存器为"3",不为3转中断退出
MOV WORK_MODE,#0 ;时间选择寄存器清0
CLR 01H ;清当前时间标志
CLR 02H ;清开机时间标志
SETB 03H ;置关机时间标志为"1"
CLR P3.0 ;LED1亮
CLR P3.1 ;LED2亮
;*******************************************************************
EXIT: LJMP ERROUT ;转中断退出
;*******************************************************************
; * 遥控调时程序 *
;*******************************************************************
FUN2: JNB 00H,EXIT ;(00H)等于0,转中断退出
;(00H)等于1,转判(01)
JNB 01H,ONHOURADJ ;(01H)等于0,转开机 "时" 调整;
;(01H)等于1,当前 "时" 调整
MOV R0,C_HOUR
MOV A,#01H
ADD A,R0
DA A
MOV C_HOUR,A ;当前时间"时"加1
CJNE A,#24H,EXIT ;超过24吗(超过清0),不为0中断退出
MOV C_HOUR,#0
AJMP EXIT ;转中断退出
ONHOURADJ: JNB 02H,OFFHOURADJ ;(02H)等于0,转关机 "时" 调整;
;(02H)等于1,开机 "时" 调整
MOV R0,ON_HOUR
MOV A,#01H
ADD A,R0
DA A
MOV ON_HOUR,A ;开机时间"时"加1
CJNE A,#24H,EXIT ;超过24吗(超过清0),不为0中断退出
MOV ON_HOUR,#0
AJMP EXIT ;转中断退出
OFFHOURADJ: JNB 03H,EXIT ;(03H)等于0,转中断退出
;(03H)等于1,关机 "时" 调整
MOV R0,OFF_HOUR
MOV A,#01H
ADD A,R0
DA A
MOV OFF_HOUR,A ;关机时间"时"加1
CJNE A,#24H,EXIT ;超过24吗(超过清0),不为0中断退出
MOV OFF_HOUR,#0
AJMP EXIT ;转中断退出
;*******************************************************************
; * 遥控调分程序 *
;*******************************************************************
FUN3: JNB 00H,EXIT ;(00H)等于0,转中断退出
;(00H)等于1,转判(01)
JNB 01H,ONMINUTEADJ ;(01H)等于0,转开机 "分" 调整;
;(01H)等于1,当前 "分" 调整
MOV R0,C_MINUTE
MOV A,#01H
ADD A,R0
DA A
MOV C_MINUTE,A ;当前时间"分"加1
CJNE A,#60H,EXIT ;超过60吗(超过清0),不为0中断退出
MOV C_MINUTE,#0
AJMP EXIT ;转中断退出
ONMINUTEADJ: JNB 02H,OFFMINUTEADJ;(02H)等于0,转关机 "分" 调整;
;(02H)等于1,开机 "分" 调整
MOV R0,ON_MINUTE
MOV A,#01H
ADD A,R0
DA A
MOV ON_MINUTE,A ;开机时间"分"加1
CJNE A,#60H,EXIT ;超过60吗(超过清0),不为0中断退出
MOV ON_MINUTE,#0
AJMP EXIT ;转中断退出
OFFMINUTEADJ: JNB 03H,EXIT ;(03H)等于0,转中断退出
;(03H)等于1,关机 "分" 调整
MOV R0,OFF_MINUTE
MOV A,#01H
ADD A,R0
DA A
MOV OFF_MINUTE,A ;关机时间"分"加1
CJNE A,#60H,EXIT ;超过60吗(超过清0),不为0中断退出
MOV OFF_MINUTE,#0
AJMP EXIT ;转中断退出
;*******************************************************************
; * 遥控启动程序 *
;*******************************************************************
FUN4: SETB EX0 ;开INT0中断
SETB TR0 ;允许T0计数
SETB ET0 ;允许T0中断
SETB P3.7 ;置P3.7口为"1"
CLR 00H ;清开始调整标志
SETB 01H ;置当前时间标志为"1"
CLR 02H ;清开机时间标志
CLR 03H ;清关机时间标志
MOV C_SECOND,#00H ;秒清0
MOV WORK_MODE,#00H ;时间选择寄存器清0
LJMP EXIT ;转中断退出
;*******************************************************************
DELAY: MOV R0,#0FFH
DELAY1: DJNZ R0,DELAY1
RET ;返回
END ;程序结束