微波EDA网,见证研发工程师的成长!
首页 > 硬件设计 > 嵌入式设计 > 单片机·实时时钟DS1302

单片机·实时时钟DS1302

时间:11-24 来源:互联网 点击:
一、实时时钟DS1302的简介

DS1302的在实时显示时间中的应用。它可以对年、月、日、周、时、分、秒进行计时,且具有闰年补偿等多种功能。

Vcc2:电源

Vcc1:后备电源,断电后可以继续工作

GND:电源地

X1,X2:振荡源,外接32.768kHz晶振

RST:片选信号

SCLK:读写控制字节

I/O:串行数据输入输出

2. DS1302的控制字节

bit7:必须是1,否则不能写入数据 (可以类比LCD1602检测忙闲)

bit6:0,存储时钟数据;1,存储RAM数据

bit1-5:指示操作单元的地址

bit0:0,表示写;1,表示读

控制字节从低位开始输出


写保护 8EH 8FH

下面附一张英文表,感觉比中文的全面一点,就是难看


3.数据流(可参照时序)

1)RST=1时,DS1302才可被写入数据,才可被操作;RST=0时,DS1302会终止数据传输,变为高阻状态;

2)SCK上升沿读地址,SCK下降沿读数据;

3)控制字节输入后下一个SCLK时钟的上升沿时,数据被写入DS1302,从低位开始。

控制字节输入后下一个SCLK时钟的下降沿时,数据被读出DS1302,从低位开始。

二、实验

程序1:用DS1302实现时钟计时

main.h

# ifndef _MAIN_H_

# define _MAIN_H_

# include

# include

sbit SCK = P3^5 ;

sbit SDA = P3^4 ;

sbit RST = P1^7 ;

typedef unsigned char uint8 ;

typedef unsigned int uint16 ;

uint8 time[7]={50,59,23,15,8,7,10} ;

# define ds1302_w_addr 0x80

# define ds1302_r_addr 0x81

# endif

main.c

# include "main.h"

void delay(uint16 n)

{

while(n--) ;

}

void reset_ds1302(void)

{

RST = 0 ;

SCK = 0 ;

RST = 1 ;

}

void write_ds1302_byte(uint8 dat)

{

uint8 i ;

for(i=0; i<8; i++)

{

SDA = dat&0x01 ;

dat>>=1 ;

SCK = 1 ;

SCK = 0 ;

}

}

uint8 read_ds1302_byte(void)

{

uint8 i,dat=0 ;

for(i=0; i<8; i++)

{

dat>>=1 ;

if(SDA)

dat |= 0x80 ;

SCK = 1 ; //这里注意SCK = 1 ,SCK = 0必须连写,不然会导致输出出错,不知原因

SCK = 0 ;

}

return dat ;

}

void clear_ds1302_wp(void)

{

reset_ds1302() ;

RST = 1 ;

write_ds1302_byte(0x8E) ;

write_ds1302_byte(0) ;

SDA = 0 ;

RST = 0 ;

}

void set_ds1302_wp(void)

{

reset_ds1302() ;

RST = 1 ;

write_ds1302_byte(0x8E) ;

write_ds1302_byte(0x80) ;

SDA = 0 ;

RST = 0 ;

}

void write_ds1302(uint8 addr, uint8 dat)

{

reset_ds1302() ;

RST = 1 ;

write_ds1302_byte(addr) ;

write_ds1302_byte(dat) ;

SDA = 0 ;

RST = 0 ;

}

uint8 read_ds1302(uint8 addr)

{

uint8 temp=0 ;

reset_ds1302() ;

RST = 1 ;

write_ds1302_byte(addr) ;

temp = read_ds1302_byte() ;

SDA = 0 ;

RST = 0 ;

return temp ;

}

void set_time(uint8 *timedata)

{

uint8 i, tmp ;

for(i=0; i<7; i++)

{

tmp = timedata[i]/10 ; //转为BCD码,这里注意对于DS1302数据的读取,必

timedata[i] = timedata[i] % 10 ; // 须转换成BCD的格式

timedata[i] = tmp*16 + timedata[i] ;

}

clear_ds1302_wp() ;

tmp = ds1302_w_addr ;

for(i=0; i<7; i++)

{

write_ds1302(tmp,timedata[i]) ;

tmp+=2 ;

}

set_ds1302_wp() ;

}

void read_time(uint8 *timedata)

{

uint8 i, tmp ;

tmp = ds1302_r_addr ; //写地址,读数据

for(i=0; i<7; i++)

{

timedata[i] = read_ds1302(tmp) ;

tmp+=2 ;

}

}

void uart_init()

{

SCON = 0x50 ;

TMOD = 0x21 ; //这里我原本设置了timer0的方式2,但是无效;

TH1 = 0xFD ; //可能我个人的单片机出了点问题,改成timer1就可以了

TL1 = 0xFD ;

TR1 = 1 ;

}

void UART_send_byte(uint8 byte)

{

SBUF = byte ;

while(!TI) ;

TI = 0 ;

}

void UART_send_dat(uint8 dat)

{

UART_send_byte(dat/16 + 0) ;

UART_send_byte(dat + 0) ;

}

void main(void)

{

uart_init() ;

set_time(&time) ;

while(1)

{

read_time(&time) ; //指针的概念,这里必须使用&time,因为指针不能做加法

//可以传输地址*timedata,让timedata去运算

UART_send_dat(time[6]) ;

UART_send_byte(-) ;

UART_send_dat(time[4]) ;

UART_send_byte(-) ;

UART_send_dat(time[3]) ;

UART_send_byte( ) ;

UART_send_dat(time[2]) ;

UART_send_byte(:) ;

UART_send_dat(time[1]) ;

UART_send_byte(:) ;

UART_send_dat(time[0]) ;

UART_send_byte() ;

UART_send_byte() ;

delay(10000) ;

}

}


实验二:将实验一的时钟程序,在LCD1602上显示

程序:

main.h

# ifndef _MAIN_H_

# define _MAIN_H_

# include

# include

sbit SCK = P3^5 ;

sbit SDA = P3^4 ;

sbit RST = P1^7 ;

sbit RS = P1^0 ;

sbit RW = P1^1 ;

sbit EN = P1^5 ;

sbit BUSY = P0^7 ;

typedef unsigned char uint8 ;

typedef unsigned int uint16 ;

uint8 time[7]={50,59,

Copyright © 2017-2020 微波EDA网 版权所有

网站地图

Top