DS1302关于51汇编的驱动函数

实现功能:

利用51汇编语言实现驱动DS1302芯片,并将显示的时间显示到LCD上

设计思路:

  1. 给DS1302赋初值。先在51单片机片内RAM开拓一块32字节的空间,用来存储时间数据(本程序是以起始地址60H开始,从60H开始存储秒、分、时、日、月、周、年,共七个字节,剩余字节备用),先给这些地址初值,然后再根据写命令字依次把时间数据写入到DS1302的RAM中
  2. 初始化LCD显示屏
  3. 从DS1302的RAM中,根据读命令字依次读出时间数据,存放到第一步开拓的空间
  4. 将数据显示到LCD屏上
  5. 延时,然后跳转到第三步进行循环(一定要有延时,否则出BUG)

电路图:

在这里插入图片描述


DS1302原理部分

1. 芯片引脚

在这里插入图片描述

  1. X1,X2:接外部时钟
  2. RST:芯片复位端,0–芯片禁止读写, 1–读写使能。当RST由低到高,启动数据传输。
  3. SCLK:上升沿将数据写入DS1302芯片,下降沿读出数据
  4. I/O:数据的传输,双向串行传输

2.芯片读写时序图

在这里插入图片描述

3.芯片命令字

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

4.驱动函数

1.基本宏定义
;******************* 宏定义 ************************

	LCDIO   EQU  P0	   ;LCD数据总线连接P0口
	RS      EQU  P2.0  ;Register select 连接P2.0
	RW      EQU  P2.1  ;Read/Write 连接P2.1
	E       EQU  P2.2  ;Enable 连接P2.2
	BF      EQU  P0.7  ;LCD的忙标志位
	
	CLOCKIO EQU  P1.0  ;DS1302数据IO
	SCLK    EQU  P1.1  ;DS1302时钟端口
	RST     EQU  P1.2  ;DS1302复位端口
	
	SECOND  EQU  60H   ;秒地址
	MINUTE  EQU  61H   ;分地址
	HOUR    EQU  62H   ;时地址
	YEAR    EQU  63H   ;日地址
	MOUTH   EQU  64H   ;月地址
	WEEK    EQU  65H   ;周地址
	DAY     EQU  66H   ;年地址
;***************************************************

说明:

  1. 上边是LCD引脚的宏定义
  2. 中间是DS1302引脚的宏定义
  3. 下边是定义的是初始化的时候给DS1302起始时间存放的地址,如第一个秒,表示在单片机片内RAM地址为60H的地方,存放的是DS1302启动的秒数据
2. DS1302写入字节函数
;************** DS1302写入字节函数 ******************
;将B写入DS1302  --传入参数B   --无传出参数

INPUT: 
	MOV R4, #8
INPUT_Rotate:
	MOV A, B
	RRC A
	MOV B, A
	MOV CLOCKIO, C
	
	SETB SCLK		 ;SCLK下降沿写入字节
	NOP
	CLR SCLK
	
	DJNZ R4, INPUT_Rotate
	RET
;***************************************************
3. DS1302读取字节函数
;************** DS1302读出字节函数 ******************
;将DS1302数据读出到A

OUTPUT:
	MOV R4, #8
OUTPUT_Rotate:		
	MOV C, CLOCKIO
	RRC A
	
	SETB SCLK		 ;SCLK下降沿读出字节
	NOP
	CLR SCLK
	
	DJNZ R4, OUTPUT_Rotate
	RET 
;***************************************************
4. 定义DS1302起始计时时间函数
;************* 定义DS1302起始计时时间 ***************
;写入 201219日 周6 131313秒

TIME_SET:	 
	 MOV SECOND,  #13H	  ;秒
	 MOV MINUTE,  #13H	  ;分
	 MOV HOUR,    #13H	  ;时
	 MOV DAY,     #19H	  ;日
	 MOV MOUTH,   #12H	  ;月
	 MOV WEEK,    #06H	  ;周
	 MOV YEAR,    #20H	  ;年
	 RET
;***************************************************
5. DS1302初始化函数
;****************** 初始化DS1302 ********************
CLOCK_INIT:
;32字节存储从DS1302读取的数据	
	MOV R0, #60H  ;60H开始,依次增加
	MOV R1, #32H  ;作为索引,索引32个连续字节
	MOV A, #00H	  ;A起到中间变量,暂时存储00H
CLR_BUF:
	MOV @R0, A	  ;间接寻址,把00H依次写入60H开始的32个字节中
	INC R0		  ;地址增1
	DJNZ R1, CLR_BUF   ;跳转,依次赋值
;写入命令字进行初始化	
	CLR RST		   ;模拟RST上升沿,启动数据传输(说明启动传输不是代表传输,还需要SCLK的上升沿
	CLR SCLK
	NOP									 ; 还需要SCLK的上升沿才能把数据按位依次传输过去)
	SETB RST
	
	MOV B, #8EH    ;命令字,写保护寄存器,此时不能对寄存器进行写操作了
	LCALL INPUT	 ;把命令字写如DS1302
	
	MOV B, #00H    ;WP清零,现在允许外部写入DS1302中数据
	LCALL INPUT	 ;把命令字写如DS1302
	
	LCALL TIME_SET	;设定初始化时间
	
	MOV R0, #SECOND	;把在RAM中地址为60H(存储数据为秒)数据给R0
	MOV R7, #7		;索引,秒、分......送七次
	MOV R1, #80H	;命令字。表示写入秒数据,当R2依次增二,表明开始进行写如分,时等数据.(这是规定,写如数据前先给命令字)

WRITE:
	CLR RST		 ;模拟RST上升沿,启动数据传输
	CLR SCLK
	NOP  
	SETB RST
	
	MOV B, R1		;将命令字80H写入DS1302
	LCALL INPUT
	MOV A,@R0	    ;R0存储的秒地址,间接寻址将数据给A
	MOV B, A		;必须把数据传给B,因为写入函数(INPUT)传入参数是B
	LCALL INPUT
	INC R0		;R0增1表示由秒向分过渡,或者由分向时过渡,依次类推
	INC R1		;R1增2,表示由秒向分的命令字过渡,或者由分向时的命令字过渡,依次类推
	INC R1
	
	SETB SCLK
	CLR RST
	DJNZ R7, WRITE  ;循环7次,将秒,分,时,星期,天,月,年都写入
	
	MOV B, #8EH    ;写保护寄存器
	LCALL INPUT
	
	MOV B, #80H    ;WP置1,写保护
	LCALL INPUT		
	
	SETB SCLK
	CLR RST
;***************************************************
6.获取时间函数
;***************** 获取时间函数 *********************

GET_TIME:
	MOV R0, #SECOND		;把秒的地址给R0,以便依次读出数据
	MOV R7, #7		    ;用来循环
	MOV R1, #81H		;命令字。表示读出秒数据,当R2依次增二,表明开始进行写如分,时等数据.
GET_TIME_Rotato:
	CLR RST				;模拟RST上升沿,表示启动数据传输
	CLR SCLK
	NOP
	SETB RST

	MOV B, R1		 	;把命令字给B,由B写如DS1302中
	LCALL INPUT			;写入命令字
	LCALL OUTPUT		;读出数据,读出的数据是保存到A中的
	MOV @R0, A			;现在将读出来的值放到秒或者分等的地址中
	INC R0				;地址加1,从而过渡到分,时等
	INC R1				;命令字需要加2才能进行读取
	INC R1
	SETB SCLK
	CLR RST
	DJNZ R7, GET_TIME_Rotato	;循环读取
	RET	   
;***************************************************
7.将时间显示再LCD函数
;***************** 显示时间函数 *********************

SHOW_TIME:
;显示小时
	MOV A, #84H
	LCALL W_CMD
	MOV A, HOUR
	PUSH Acc
	SWAP A
	ANL A, #0FH
	ORL A, #30H
	LCALL W_DAT  ;显示小时高位
	
	MOV A, #85H
	LCALL W_CMD
	
	POP Acc
	ANL A, #0FH
	ORL A, #30H
	LCALL W_DAT ;显示小时低位

;显示符号-
	MOV A, #86H
	LCALL W_CMD
	MOV A, #2DH
	LCALL W_DAT

;显示分钟
	MOV A, #87H
	LCALL W_CMD
	MOV A, MINUTE
	PUSH Acc
	SWAP A
	ANL A, #0FH
	ORL A, #30H
	LCALL W_DAT  ;显示分钟高位
	
	MOV A, #88H
	LCALL W_CMD
	
	POP Acc
	ANL A, #0FH
	ORL A, #30H
	LCALL W_DAT ;显示分钟低位

;显示符号-
	MOV A, #89H
	LCALL W_CMD
	MOV A, #2DH
	LCALL W_DAT

;显示秒
	MOV A, #8AH
	LCALL W_CMD
	MOV A, SECOND
	PUSH Acc
	SWAP A
	ANL A, #0FH
	ORL A, #30H
	LCALL W_DAT  ;显示秒高位
	
	MOV A, #8BH
	LCALL W_CMD
	
	POP Acc
	ANL A, #0FH
	ORL A, #30H
	LCALL W_DAT ;显示秒低位

;显示年
	MOV A, #0C3H
	LCALL W_CMD
	MOV A, YEAR
	PUSH Acc
	SWAP A
	ANL A, #0FH
	ORL A, #30H
	LCALL W_DAT  ;显示年高位
	
	MOV A, #0C4H
	LCALL W_CMD
	
	POP Acc
	ANL A, #0FH
	ORL A, #30H
	LCALL W_DAT ;显示年低位

;显示符号-
	MOV A, #0C5H
	LCALL W_CMD
	MOV A, #2DH
	LCALL W_DAT

;显示月
	MOV A, #0C6H
	LCALL W_CMD
	MOV A, MOUTH
	PUSH Acc
	SWAP A
	ANL A, #0FH
	ORL A, #30H
	LCALL W_DAT  ;显示月高位
	
	MOV A, #0C7H
	LCALL W_CMD
	
	POP Acc
	ANL A, #0FH
	ORL A, #30H
	LCALL W_DAT ;显示月低位

;显示符号-
	MOV A, #0C8H
	LCALL W_CMD
	MOV A, #2DH
	LCALL W_DAT

;显示日
	MOV A, #0C9H
	LCALL W_CMD
	MOV A, DAY
	PUSH Acc
	SWAP A
	ANL A, #0FH
	ORL A, #30H
	LCALL W_DAT  ;显示日高位
	
	MOV A, #0CAH
	LCALL W_CMD
	
	POP Acc
	ANL A, #0FH
	ORL A, #30H
	LCALL W_DAT ;显示日低位

;显示符号-
	MOV A, #0CBH
	LCALL W_CMD
	MOV A, #2DH
	LCALL W_DAT

;显示周
	MOV A, #0CCH
	LCALL W_CMD
	MOV A, WEEK
	
	ANL A, #0FH
	ORL A, #30H
	LCALL W_DAT ;显示周
	
	RET
;***************************************************
8.延时函数
;****************** T0延时函数 *******************

T0_DELAY:
	PUSH Acc
	LCALL T0_WAIT
	POP Acc
	DEC A
	JNZ T0_DELAY
	RET
T0_WAIT:
	XRL DPL, #0FFH
	XRL DPH, #0FFH
	INC DPTR
T0_1:
	MOV TL0, #09CH
	MOV TH0, #0FFH
	MOV TMOD, #1
	SETB TCON.4
T0_2:
	JNB TCON.5, T0_2
	CLR TCON.4
	CLR TCON.5
	INC DPTR
	MOV A, DPL
	MOV A, DPH
	JNZ T0_1
	RET
;***************************************************

整体程序设计

;******************* 宏定义 ************************

	LCDIO   EQU  P0	   ;LCD数据总线连接P0口
	RS      EQU  P2.0  ;Register select 连接P2.0
	RW      EQU  P2.1  ;Read/Write 连接P2.1
	E       EQU  P2.2  ;Enable 连接P2.2
	BF      EQU  P0.7  ;LCD的忙标志位
	
	CLOCKIO EQU  P1.0  ;DS1302数据IO
	SCLK    EQU  P1.1  ;DS1302时钟端口
	RST     EQU  P1.2  ;DS1302复位端口
	
	SECOND  EQU  60H   ;秒地址
	MINUTE  EQU  61H   ;分地址
	HOUR    EQU  62H   ;时地址
	YEAR    EQU  63H   ;日地址
	MOUTH   EQU  64H   ;月地址
	WEEK    EQU  65H   ;周地址
	DAY     EQU  66H   ;年地址
;***************************************************
	
	ORG 0000H
	AJMP MAIN
	ORG 0100H
;******************** 主函数 ************************

MAIN: 
	LCALL CLOCK_INIT ;调用DS1602初始化函数
	LCALL LCD_INIT	 ;调用LCD1602初始化函数
LOOP:
	LCALL GET_TIME	 ;调用获取时间函数,存储起始地址60H
	LCALL SHOW_TIME	 ;调用LCD显示时间函数
	MOV DPTR, #800   ;调用延时函数
	MOV A, #1
	LCALL T0_DELAY
	
	AJMP LOOP 
;***************************************************

;**************** LCD1602初始化 *********************
LCD_INIT:
	MOV A, #01H  ;写入清屏命令 
	ACALL W_CMD
	MOV A, #38H  ;设置显示模式16*2显示
	ACALL W_CMD
	MOV A, #0CH  ;设置屏幕显示,无光标
	ACALL W_CMD
	MOV A, #14   ;设置右移
	ACALL W_CMD
	RET
;***************************************************
	  
;**************** LCD1602忙标志 *********************      
	  
WAIT_BUSY: 
	MOV LCDIO,#0FFH
	CLR RS
	SETB RW
	CLR E
	NOP
	SETB E
	JB BF, WAIT_BUSY
	RET
;***************************************************

;*************** LCD1602写入命令函数 ****************

W_CMD:
	LCALL WAIT_BUSY 
	MOV LCDIO, A ;把命令写到IO口处
	CLR RS	   ;0,选择命令寄存器
	CLR RW
	SETB E	   ;模拟下降沿,命令写入LCD中
	NOP
	CLR E
	RET
;***************************************************

;*************** LCD1602写入数据函数 ****************

W_DAT:
	LCALL WAIT_BUSY 
	MOV LCDIO, A
	SETB RS	   ;1,选择数据寄存器
	CLR RW	   ;0,为写入,置1,为读取
	SETB E	   ;模拟下降沿
	NOP 
	CLR E
	RET
;***************************************************

;************** DS1302写入字节函数 ******************
;将B写入DS1302  --传入参数B   --无传出参数

INPUT: 
	MOV R4, #8
INPUT_Rotate:
	MOV A, B
	RRC A
	MOV B, A
	MOV CLOCKIO, C
	
	SETB SCLK		 ;SCLK下降沿写入字节
	NOP
	CLR SCLK
	
	DJNZ R4, INPUT_Rotate
	RET
;***************************************************

;************** DS1302读出字节函数 ******************
;将DS1302数据读出到A

OUTPUT:
	MOV R4, #8
OUTPUT_Rotate:		
	MOV C, CLOCKIO
	RRC A
	
	SETB SCLK		 ;SCLK下降沿读出字节
	NOP
	CLR SCLK
	
	DJNZ R4, OUTPUT_Rotate
	RET 
;***************************************************

;************* 定义DS1302启示计时时间 ***************
;写入 201219日 周6 131313秒

TIME_SET:	 
	 MOV SECOND,  #13H	  ;秒
	 MOV MINUTE,  #13H	  ;分
	 MOV HOUR,    #13H	  ;时
	 MOV DAY,     #19H	  ;日
	 MOV MOUTH,   #12H	  ;月
	 MOV WEEK,    #06H	  ;周
	 MOV YEAR,    #20H	  ;年
	 RET
;***************************************************

;****************** 初始化DS1302 ********************
CLOCK_INIT:
;32字节存储从DS1302读取的数据	
	MOV R0, #60H  ;60H开始,依次增加
	MOV R1, #32H  ;作为索引,索引32个连续字节
	MOV A, #00H	  ;A起到中间变量,暂时存储00H
CLR_BUF:
	MOV @R0, A	  ;间接寻址,把00H依次写入60H开始的32个字节中
	INC R0		  ;地址增1
	DJNZ R1, CLR_BUF   ;跳转,依次赋值
;写入命令字进行初始化	
	CLR RST		   ;模拟RST上升沿,启动数据传输(说明启动传输不是代表传输,还需要SCLK的上升沿
	CLR SCLK
	NOP									 ; 还需要SCLK的上升沿才能把数据按位依次传输过去)
	SETB RST
	
	MOV B, #8EH    ;命令字,写保护寄存器,此时不能对寄存器进行写操作了
	LCALL INPUT	 ;把命令字写如DS1302
	
	MOV B, #00H    ;WP清零,现在允许外部写入DS1302中数据
	LCALL INPUT	 ;把命令字写如DS1302
	
	LCALL TIME_SET	;设定初始化时间
	
	MOV R0, #SECOND	;把在RAM中地址为60H(存储数据为秒)数据给R0
	MOV R7, #7		;索引,秒、分......送七次
	MOV R1, #80H	;命令字。表示写入秒数据,当R2依次增二,表明开始进行写如分,时等数据.(这是规定,写如数据前先给命令字)

WRITE:
	CLR RST		 ;模拟RST上升沿,启动数据传输
	CLR SCLK
	NOP  
	SETB RST
	
	MOV B, R1		;将命令字80H写入DS1302
	LCALL INPUT
	MOV A,@R0	    ;R0存储的秒地址,间接寻址将数据给A
	MOV B, A		;必须把数据传给B,因为写入函数(INPUT)传入参数是B
	LCALL INPUT
	INC R0		;R0增1表示由秒向分过渡,或者由分向时过渡,依次类推
	INC R1		;R1增2,表示由秒向分的命令字过渡,或者由分向时的命令字过渡,依次类推
	INC R1
	
	SETB SCLK
	CLR RST
	DJNZ R7, WRITE  ;循环7次,将秒,分,时,星期,天,月,年都写入
	
	MOV B, #8EH    ;写保护寄存器
	LCALL INPUT
	
	MOV B, #80H    ;WP置1,写保护
	LCALL INPUT		
	
	SETB SCLK
	CLR RST
;***************************************************

;***************** 获取时间函数 *********************

GET_TIME:
	MOV R0, #SECOND		;把秒的地址给R0,以便依次读出数据
	MOV R7, #7		    ;用来循环
	MOV R1, #81H		;命令字。表示读出秒数据,当R2依次增二,表明开始进行写如分,时等数据.
GET_TIME_Rotato:
	CLR RST				;模拟RST上升沿,表示启动数据传输
	CLR SCLK
	NOP
	SETB RST

	MOV B, R1		 	;把命令字给B,由B写如DS1302中
	LCALL INPUT			;写入命令字
	LCALL OUTPUT		;读出数据,读出的数据是保存到A中的
	MOV @R0, A			;现在将读出来的值放到秒或者分等的地址中
	INC R0				;地址加1,从而过渡到分,时等
	INC R1				;命令字需要加2才能进行读取
	INC R1
	SETB SCLK
	CLR RST
	DJNZ R7, GET_TIME_Rotato	;循环读取
	RET	   
;***************************************************

;***************** 显示时间函数 *********************

SHOW_TIME:
;显示小时
	MOV A, #84H
	LCALL W_CMD
	MOV A, HOUR
	PUSH Acc
	SWAP A
	ANL A, #0FH
	ORL A, #30H
	LCALL W_DAT  ;显示小时高位
	
	MOV A, #85H
	LCALL W_CMD
	
	POP Acc
	ANL A, #0FH
	ORL A, #30H
	LCALL W_DAT ;显示小时低位

;显示符号-
	MOV A, #86H
	LCALL W_CMD
	MOV A, #2DH
	LCALL W_DAT

;显示分钟
	MOV A, #87H
	LCALL W_CMD
	MOV A, MINUTE
	PUSH Acc
	SWAP A
	ANL A, #0FH
	ORL A, #30H
	LCALL W_DAT  ;显示分钟高位
	
	MOV A, #88H
	LCALL W_CMD
	
	POP Acc
	ANL A, #0FH
	ORL A, #30H
	LCALL W_DAT ;显示分钟低位

;显示符号-
	MOV A, #89H
	LCALL W_CMD
	MOV A, #2DH
	LCALL W_DAT

;显示秒
	MOV A, #8AH
	LCALL W_CMD
	MOV A, SECOND
	PUSH Acc
	SWAP A
	ANL A, #0FH
	ORL A, #30H
	LCALL W_DAT  ;显示秒高位
	
	MOV A, #8BH
	LCALL W_CMD
	
	POP Acc
	ANL A, #0FH
	ORL A, #30H
	LCALL W_DAT ;显示秒低位

;显示年
	MOV A, #0C3H
	LCALL W_CMD
	MOV A, YEAR
	PUSH Acc
	SWAP A
	ANL A, #0FH
	ORL A, #30H
	LCALL W_DAT  ;显示年高位
	
	MOV A, #0C4H
	LCALL W_CMD
	
	POP Acc
	ANL A, #0FH
	ORL A, #30H
	LCALL W_DAT ;显示年低位

;显示符号-
	MOV A, #0C5H
	LCALL W_CMD
	MOV A, #2DH
	LCALL W_DAT

;显示月
	MOV A, #0C6H
	LCALL W_CMD
	MOV A, MOUTH
	PUSH Acc
	SWAP A
	ANL A, #0FH
	ORL A, #30H
	LCALL W_DAT  ;显示月高位
	
	MOV A, #0C7H
	LCALL W_CMD
	
	POP Acc
	ANL A, #0FH
	ORL A, #30H
	LCALL W_DAT ;显示月低位

;显示符号-
	MOV A, #0C8H
	LCALL W_CMD
	MOV A, #2DH
	LCALL W_DAT

;显示日
	MOV A, #0C9H
	LCALL W_CMD
	MOV A, DAY
	PUSH Acc
	SWAP A
	ANL A, #0FH
	ORL A, #30H
	LCALL W_DAT  ;显示日高位
	
	MOV A, #0CAH
	LCALL W_CMD
	
	POP Acc
	ANL A, #0FH
	ORL A, #30H
	LCALL W_DAT ;显示日低位

;显示符号-
	MOV A, #0CBH
	LCALL W_CMD
	MOV A, #2DH
	LCALL W_DAT

;显示周
	MOV A, #0CCH
	LCALL W_CMD
	MOV A, WEEK
	
	ANL A, #0FH
	ORL A, #30H
	LCALL W_DAT ;显示周
	
	RET
;****************** T0延时函数 *******************

T0_DELAY:
	PUSH Acc
	LCALL T0_WAIT
	POP Acc
	DEC A
	JNZ T0_DELAY
	RET
T0_WAIT:
	XRL DPL, #0FFH
	XRL DPH, #0FFH
	INC DPTR
T0_1:
	MOV TL0, #09CH
	MOV TH0, #0FFH
	MOV TMOD, #1
	SETB TCON.4
T0_2:
	JNB TCON.5, T0_2
	CLR TCON.4
	CLR TCON.5
	INC DPTR
	MOV A, DPL
	MOV A, DPH
	JNZ T0_1
	RET
;***************************************************
	END

运行结果

在这里插入图片描述

说明:

更全面的程序设计:基于51+DS1302智能时钟设计

  • 10
    点赞
  • 40
    收藏
    觉得还不错? 一键收藏
  • 10
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 10
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值