单片机实现的多功能智能钟源代码 程序清单如下: ;******************************************************************* ;写字节子程序WMAX ;占用寄存器ACC ;******************************************************************* DIN EQU P1.6 CLK EQU P1.4 WMAX: JB E7,W7 ;判是否为1 LCALL WM0 ;不是,则调用写“0”子程序 LJMP N7 W7: LCALL WM1 ;是,则调用写“1”子程序 N7: JB E6, W6 LCALL WM0 LJMP N6 W6: LCALL WM1 N6: JB E5, W5 LCALL WM0 LJMP N5 W5: LCALL WM1 N5: JB E4, W4 LCALL WM0 LJMP N4 W4: LCALL WM1 N4: JB E3, W3 LCALL WM0 LJMP N3 W3: LCALL WM1 N3: JB E2, W2 LCALL WM0 LJMP N2 W2: LCALL WM1 N2: JB E1, W1 LCALL WM0 LJMP N1 W1: LCALL WM1 N1: JB E0, W0 LCALL WM0 LJMP N0 W0: LCALL WM1 N0: CLR CLK CLR DIN RET ;******************************************************************* ;写“1”子程序 ;******************************************************************* WM1: CLR CLK SETB DIN ;送出“1” NOP SETB CLK ;产生 CLK的上升沿 NOP NOP CLR CLK ;产生 CLK的下降沿 RET ;******************************************************************* ;写“0”子程序 ;******************************************************************* WM0: CLR CLK CLR DIN ;送出“0” NOP SETB CLK ;产生 CLK的上升沿 NOP NOP CLR CLK ;产生 CLK的下降沿 RET 2.X25045的初始化及读写子程序 ;X25045引脚定义如下 SCK EQU P2.3 ;串行时钟输入 SI EQU P2.4 ;串行数据输入 SO EQU P2.6 ;串行数据输出 CS EQU P2.7 ;片选输入 ;其中写保护输入WP始终接高电平 ;状态寄存器及各命令字节定义 STATUS_REG EQU #00010000B ;上述状态寄存器中的WD1=0,WD0=1,即看门狗周期为600ms ;另外,BL1=0,BL0=0 READ_INST EQU #00000011B WRITE_INST EQU #00000010B RDSR_INST EQU #00000101B WREN_INST EQU #00000110B WRSR_INST EQU #00000001B WRDI_INST EQU #00000100B ;******************************************************************* ;写 1字节数据到 X25045中的子程序WRONE ;数据在 A中,地址在 DPTR中 ;占用寄存器:ACC,DPTR ;******************************************************************* WRONE: PUSH ACC ;待写数据保护 LCALL WREN ;WRITE ENABLE. CLR SCK ;X25045的 SCK置低 CLR CS ;片选 CS置低,选中 MOV A, WRITE_INST MOV B, DPH MOV C, B.0 MOV ACC.3, C ;DPH的最低位 (A8)送 ACC.3 LCALL OUTBYT ;送含地址高位的写命令 MOV A, DPL LCALL OUTBYT ;送低 8位地址 POP ACC LCALL OUTBYT ;写一字节数据 CLR SCK ;X25045的 SCK置低 STEB CS ;片选 CS置高 ,无效 RET ;******************************************************************* ;设置写使能锁存器WREN子程序( 即允许写操作) ;******************************************************************* WREN: CLR CS CLR SCK MOV A,WREN_INST LCALL OUTBYT ;送写使能命令 WREN SETB CS CLR SCK RET ;******************************************************************* ;给 X25045写入 1字节地址或数据子程序OUTBYT ;欲写内容在 A中 ;占用寄存器:ACC,B ;******************************************************************* OUTBYT: MOV B,#08H ;置循环次数 8 OUTBYT1: CLR SCK RLC A ;Acc的最高位送 Cy MOV SI, C ;Cy送 X25045的 SI SETB SCK DJNZ B,OUTBYT1 ;循环 8次,8bits CLR SI ;X25045的 SI置低 CLR SCK RET
;******************************************************************* ;功能:读X25045状态寄存器,等待内部写 ;入口条件:R6的数据是等待延时时间 ;出口信息:WIP=1,正在写,WIP=0写完成 ;占用资源:R6、A、B、PSW ;******************************************************************* RDS045: MOV R6,0FFH ;循环次数送入R6 RDS01: CLR SCK NOP CLR CS ;选中X25045 NOP MOV A,RDSR_INST ;05H,读X25045状态寄存器命令送A LCALL OUTBYT ;调用X25045写入1个字节子程序 LCALL INBYT ;调用X25045读出1个字节子程序 SETB CS ;不选中X25045 JNB ACC.0,DS02 ;WIP=1, 正在写, WIP=0写完成 DJNZ R6,DS01 RDS02: RET ;******************************************************************* ;功 能: 向X25045写入一批数据子程序W045 ;入口条件: R0的内容为CPU内存的地址 ; R1的内容是X25045的待写地址,R3是待写数据的长度 ; R4的内容是02H或0AH,表示写命令的执行区域 ;出口信息: R3的内容为0 ;占用资源:A、B、PSW、R0、R1、R2、R3、R4 ;******************************************************************* W045: CLR SCK NOP CLR CS NOP MOV A,WREN_INST ;#06H,写允许命令送入A LCALL OUTBYT ;调用向X25045写入1个字节子程序 SETB CS NOP CLR CS MOV A,R4 ;命令送入A LCALL OUTBYT ;调用X25045写入1个字节子程序 MOV A,R1 ;X25045的首地址送入A LCALL OUTBYT ;调用25045 写入1个字节子程序 W0450: MOV A,@R0 ;待写数据送入A LCALL OUTBYT ;调用X25045写入1个字节子程序 INC R0 ;调整CPU内数据存储区的位置 DJNZ R3,W0450 ;判断这批数据是否写完 SETB CS ;批量数据写完,不选中X25045 RET ;******************************************************************* ;功 能: 向X25045读出一批数据子程序 ;入口条件: R0的内容为CPU内存的地址 R1的内容是X25045的待写地址,R3是待写数据的长度 R4的内容是03H或0BH,表示写命令的执行区域 ;出口信息: R3的内容为0 ;占用资源: A、B、PSW、R0、R1、R2、R3、R4 ;******************************************************************* R045: CLR SCK NOP CLR CS NOP MOV A,R4 ;命令送入A LCALL OUTBYT ;25045写入8个字节子程序 MOV A,R1 ;对X25045的操作首地址送入 A LCALL OUTBYT ;25045写入8个字节子程序 R0451: LCALL INBYT ;调用读出8位数据子程序 MOV @R0,A ;读出的数据送入CPU内存 INC R0 ;调整CPU内部存放数据的位置 DJNZ R3,R0451 ;数据未读完,跳转 SETB CS ;数据读完,不选中X25045 RET ;******************************************************************* ;功能: 从X25045中读出8位数据子程序 ;出口信息:A的内容为读出的8位数据 ;占用资源:B、PSW ;******************************************************************* INBYT: MOV B,#08H INBYT: CLR SCK NOP MOV C,SO NOP SETB SCK RLC A NOP DJNZ B,INBYT CLR SCK RET
3.DS1302的初始化及读写子程序 ;********************************************************* T_CLK EQU P3.3 ;实时时钟时钟线引脚T_IO EQU P3.4 ;实时时钟数据线引脚T_RST EQU P3.2 ;实时时钟复位线引脚;******************************************************************* ;子程序名:Set1302 ;功 能:设置DS1302 初始时间,并启动计时。 ;说 明: ;调 用: RTInputByte ;入口参数:初始时间在:Second,Minute,Hour,Day,Month,Week,YearL ; (地址连续) ;返 回 值:无 ;影响资源:A B R0 R1 R4 R7 ;******************************************************************* Set1302: CLR T_RST CLR T_CLK SETB T_RST MOV B,#8EH ;控制寄存器 LCALL RTInputByte MOV B,#00H ;写操作前WP=0 LCALL RTInputByte SETB T_CLK CLR T_RST MOV R0,#Second; MOV R7,#7 ;秒 分 时 日 月 星期 年 MOV R1,#80H ;秒写地址 Set13021: CLR T_RST CLR T_CLK SETB T_RST MOV B,R1 ;写秒 分 时 日 月 星期 年 地址 LCALL RTInputByte MOV A,@R0 ;写秒数据 MOV B,A LCALL RTInputByte INC R0 INC R1 INC R1 SETB T_CLK CLR T_RST DJNZ R7,Set13021 CLR T_RST CLR T_CLK SETB T_RST MOV B,#8EH ;控制寄存器 LCALL RTInputByte MOV B,#80H ;控制,WP=1,写保护 LCALL RTInputByte SETB T_CLK CLR T_RST RET ;******************************************************************* ;子程序名:Get1302 ;功 能:从DS1302 读时间 ;说 明: ;调 用:RTInputByte,RTOutputByte ;入口参数:时间保存在:Second,Minute,Hour,Day,Month,Week,YearL ;返 回 值:无 ;影响资源:A B R0 R1 R4 R7 ;******************************************************************* Get1302: MOV R0, #Second MOV R7, #7 MOV R1, #81H ;秒地址 Get13021: CLR T_RST CLR T_CLK SETB T_RST MOV B, R1 ;秒 分 时 日 月 星期 年 地址 LCALL RTInputByte LCALL RTOutputByte MOV @R0, A ;秒 INC R0 INC R1 INC R1 SETB T_CLK CLR T_RST DJNZ R7, Get13021 RET ;******************************************************************* ;写1302一字节子程序 ;******************************************************************* RTInputByte: MOV R4, #8 Inbit1: MOV A, B RRC A MOV B, A MOV T_IO, C SETB T_CLK CLR T_CLK DJNZ R4, Inbit1 RET ;******************************************************************* ;读1302一字节 子程序 ;******************************************************************* RTOutputByte: MOV R4, #8 Outbit1: MOV C, T_IO RRC A SETB T_CLK CLR T_CLK DJNZ R4, Outbit1 RET
;******************************************************************* ;发送接收控制信号 SFCTRL EQU P1.7 ;本通信节点地址定义 ADDRESS EQU 01H ;通信所需变量定义 ;******************************************************************* ;主程序串行通信的初始化 MAIN: MOV SP, #60H MOV PCON, #00H ;SMODE=0 MOV TMOD, #20H ;定时器1设为模式2(波特率发生器) CLR EA MOV TH1, #0F3H ;定时起始值,6MHz晶振时波特率1200bps MOV TL1, #0F3H MOV SCON, #0D8H ;串行口模式3,TB8=1发送地址呼叫 SETB TR1 ;启动定时器1 SETB EA (其他初始化) (其他处理程序) ; TX: SETB RS0 ;选择1组工作寄存器 PUSH ACC CLR RI ;清接收标志 CLR ES ;关闭串行口中断 CLR SFCTRL ;使485处于接收方式 MOV A,SBUF ;接收数据 MOV B,A ;数据暂存 XRL A,#0FFH ;判是否是复位命令(字节0FFH) JNZ TX_1 ;不是,则转 SETB SM2 ;是,则进行软复位处理 SETB ES (设置系统软复位标志以便系统进行软复位处理) POP ACC ;恢复现场 CLR RS0 RETI TX_1: MOV A,B ;取出数据以判是否呼叫本机 CJNE A,#ADDRESS,TX_2 SJMP TX_3 TX_2: SETB ES ;不是,则中断返回 POP ACC ;恢复现场 CLR RS0 RETI TX_3: CLR SM2 SETB SFCTRL ;使485处于发送状态 MOV A,#ADDRESS ;用本机地址作为应答 MOV SBUF,A TX_4: JNB TI,TX_4 ;等待发送完成 CLR TI CLR SFCTRL ;使485恢复接收状态 (下面开始接收并进行相应处理) ... SETB ES POP ACC ;恢复现场 CLR RS0 RETI