;先设置时间和日期为:秒(08),分(58),时(05),日(13),月(01),年(55)
;六位数码观显示时间和日期,默认显示的是时间,通过小数点区分时与分、分与秒
;按下RB1键不放,显示切换到日期显示。
#INCLUDE<p16f877a.inc> ;包含头文件
__CONFIG _DEBUG_OFF&_CP_ALL&_WRT_HALF&_CPD_ON&_LVP_OFF&_BODEN_OFF&_PWRTE_ON&_WDT_OFF&_HS_OSC
;**********************引脚定义****************************
#DEFINE I_O PORTB,4 ;1302I_O
#DEFINE SCLK PORTB,0 ;1302时钟
#DEFINE RST PORTB,5 ;1302使能位
;*********************寄存器定义***************************
TIME_TX_ADD EQU 20H ;连续发送8个数据起始地址
TIME_RX_ADD EQU 20H ;连续接收7个数据起始地址
ERRORLEVEL -302
CBLOCK 20H
SEC ;秒
MIN ;分
HOU ;小时
DATE ;日期
MON ;月
DAY ;日
YERR ;年
TIME_TX ;1302发送寄存器
TIME_RX ;1302接收寄存器
COUNT1 ;循环次数计数器
COUNT2 ;
ENDC
;*******************宏定义*********************************
BANK1 MACRO ;体1
BSF STATUS,RP0
ENDM
BANK0 MACRO ;体0
BCF STATUS,RP0
ENDM ORG 000H ;复位入口地址
NOP ;ICD所需要的空指令
GOTO MAIN ;跳转到主程序 ;********************查表程序*****************************
TABLE
ADDWF PCL,1
RETLW 0C0H ;0的编码(公阳极数码管)
RETLW 0F9H ;1的编码
RETLW 0A4H ;2的编码
RETLW 0B0H ;3的编码
RETLW 99H ;4的编码
RETLW 92H ;5的编码
RETLW 082H ;6
RETLW 0F8H ;7
RETLW 080H ;8
RETLW 090H ;9 ;**********************主程序*****************************
MAIN
CALL PORT_INI ;端口定义
CALL DS1302_INI ;1302初始化程序
CALL SET_TIME ;一次写入7个时间数据
CALL GET_TIME ;一次读回7个时间数据
CALL DISPLAY ;调用显示程序
GOTO $-2 ;循环读取时间 ;**********************DS1302初始化程序******************
; DS1302_INI
; 作用:初始化1302,写使能寄存器
;********************************************************
;入口参数:无
;出口参数:TIME_TX
DS1302_INI
BCF SCLK
BCF RST ;先禁止
MOV LW B’10001110’ ;写使能寄存器
MOV WF TIME_TX
BSF RST ;允许1302工作
CALL TIME_WRITE_1 ;调用写一个数据程序
MOV LW 0H ;允许写使能
MOV WF TIME_TX
CALL TIME_WRITE_1 ;发送一个字节的数据
BCF RST
RETURN ;***********************写时间程序*************************
; SET_TIME
; 作用:一次输入7个数据来一次性的设定时间,同时使能写寄存器
; 突发模式写入,必须写入8个数据,不是7个
; INPUT:要设定的8个数据已经写入到TIME_TX_ADD开始的8个字节里面
;********************************************************
;入口参数:20H--27H的8个RAM单元
SET_TIME
MOV LW B’10111110’ ;多字节写方式
MOV WF TIME_TX
BSF RST
CALL TIME_WRITE_1
MOV LW TIME_TX_ADD ;发送数据的起始地址
MOV WF FSR
MOV LW D’8’ ;一起发送8个数据
MOV WF COUNT2
TW1
MOV F INDF,W
MOV WF TIME_TX
CALL TIME_WRITE_1
INCF FSR,F
DECFSZ COUNT2,F
GOTO TW1
BCF RST
RETURN ;**********************读时间程序*************************
; GET_TIME
; 作用:一次接受7个字节的时间数据,突发模式读取
; INPUT:NONE
; OUTPUT:把7个时间数据保存在TIME_RX_ADD开始的7个寄存器里面
;*********************************************************
;入口参数:无
;出口参数:20H--26H的7个RAM单元
GET_TIME
MOV LW B’10111111’ ;多字接读取方式
MOV WF TIME_TX
BSF RST
CALL TIME_WRITE_1
MOV LW TIME_RX_ADD ;保存数据的起始地址
MOV WF FSR
MOV LW D’7’ ;连续读取7个数据
MOV WF COUNT2
TR2
CALL TIME_READ_1
MOV F TIME_RX,W
MOV WF INDF
INCF FSR,F
DECFSZ COUNT2,F
GOTO TR2
BCF RST
RETURN ;**********************写一个字节程序*****************
; TIME_WRITE_1
; 作用:一次发送一个字节的数据,用于发送1302的
; 控制字或者发送一个数据
;************************************************
;入口参数:TIME_TX
;出口参数:无
TIME_WRITE_1
MOV LW D’8’ ;8位
MOV WF COUNT1
TLOP
BCF I_O ;初始值是低电平
BCF SCLK
BTFSC TIME_TX,0
BSF I_O
RRF TIME_TX,F
BSF SCLK ;上升沿发送数据
DECFSZ COUNT1,F
GOTO TLOP
BCF SCLK ;恢复
RETURN ;******************读取一字节程序*********************
; TIME_READ_1
; 作用:读取1302一个字节的数据
; 原理:在SCLK下降沿接收数据,低字节在前,根据I_O的
; 的电平的高低,采取带进位和不带进位右移.
;***********************************************
;入口参数:无
;出口参数:TIME_RX
TIME_READ_1
BANK1
BSF TRISB,4 ; I_O 设置为输入
BANK0
MOV LW D’8’
MOV WF COUNT1 ;读取8位
TR1
BCF SCLK ;下降沿读取
BCF STATUS,C
BTFSC I_O
BSF STATUS,C
RRF TIME_RX,F
BSF SCLK ;恢复高电平
DECFSZ COUNT1,F
GOTO TR1
BANK1
BCF TRISB,4 ;I_O恢复为输出
BANK0
BCF SCLK
RETURN
NOP ;******************端口/寄存器设置********************
PORT_INI
BANK1
MOV LW B’00000000’
MOV WF TRISA ;A口输出
MOV WF TRISD ;D口输出
MOV LW 06H
MOV WF ADCON1 ;A口配置为普通数字I/O
MOV LW B’00000010’
MOV WF TRISB ;RB1口为输入,其他口为输出
CLRF OPTION_REG ;开启B口的弱上拉
BANK0
MOV LW 0FFH
MOV WF PORTA
MOV WF PORTD ;熄灭所有显示
MOV LW 08H
MOV WF 20H ;秒,允许晶振起振
MOV LW 58H ;分
MOV WF 21H
MOV LW 05H ;时
MOV WF 22H
MOV LW 13H ;日
MOV WF 23H
MOV LW 10H ;月
MOV WF 24H
MOV LW 06H ;星期
MOV WF 25H
MOV LW 55H ;年
MOV WF 26H
RETURN ;******************************显示程序*************************
DISPLAY
BTFSS PORTB,1 ;是否有按键按下
GOTO DISPLAY_DATE ;按键按下,显示日期,否则显示时间
MOV FW 20H
MOV WF 30H
MOV FW 21H
MOV WF 31H
MOV FW 22H
MOV WF 32H ;将20H--22H的数据复制到30H--32H(秒、分、时)
GOTO DISPLAY1 ;送显示
DISPLAY_DATE ;显示日期
MOV FW 23H
MOV WF 30H
MOV FW 24H
MOV WF 31H
MOV FW 26H
MOV WF 32H ;将23H、24H,26H的数据复制到30H--32H(日、月、年)
DISPLAY1
SWAPF 32H,0 ;显示时/年的高位
ANDLW 0FH
CALL TABLE
MOV WF PORTD
BCF PORTA,0
CALL DELAY
BSF PORTA,0
MOV FW 32H ;显示时/年的低位
ANDLW 0FH
CALL TABLE
MOV WF PORTD
BCF PORTD,7 ;点亮数码管上的小点,做为两位之间的分隔
BCF PORTA,1
CALL DELAY
BSF PORTA,1 SWAPF 31H,0 ;显示分/月的高位
ANDLW 0FH
CALL TABLE
MOV WF PORTD
BCF PORTA,2
CALL DELAY
BSF PORTA,2
MOV FW 31H ;显示分/月的低位
ANDLW 0FH
CALL TABLE
MOV WF PORTD
BCF PORTD,7
BCF PORTA,3
CALL DELAY
BSF PORTA,3 SWAPF 30H,0 ;显示秒/日的高位
ANDLW 0FH
CALL TABLE
MOV WF PORTD
BCF PORTA,4
CALL DELAY
BSF PORTA,4
MOV FW 30H ;显示秒/日的低位
ANDLW 0FH
CALL TABLE
MOV WF PORTD
BCF PORTA,5
CALL DELAY
BSF PORTA,5
;*************************延时程序*****************************
DELAY
MOV LW 3FH
MOV WF 40H
DECFSZ 40H,1
GOTO $-1
RETURN ;**************************************************************
END ;程序结束