DS1302 简介:
DS1302 芯片是 三线制SPI接口
内含有一个实时时钟/日 历和 31 字节静态 RAM,通过简单的串行接口与单片机进行通信;
AM/PM 指示决定采用 24 或 12 小时格式。
DS1302 与 单片机之间能简单地采用同步串行的方式进行通信,仅需用到三根通信线:
①RES 复位
②I/O 数据线
③SCLK 串行时钟。
DS1302 管脚图:
DS1302里有什么?
有一个控制寄存器,12个日历,时钟寄存器,31个RAM
(1)控制寄存器
控制寄存器存放DS1302的控制命令,DS1302de RST高电平后写入第一个字节为控制命令
1、第 7 位永远都是 1;2、第 6 位,1 表示 RAM,寻址内部存储器地址;0 表示 CK,寻址内部寄存器;3、第 5 到第 1 位,为 RAM 或者寄存器的地址;4、最低位,高电平表示 RD,即下一步操作将要“读”;低电平表示 W,即下一步操作将要“写”。
(2)日历/时钟寄存器
(3)DS1302读写时序
控制命令输入后,下一个SCLK时钟的上升沿时,数据被写入DS1302,数据从低位(位0)开始;
同样在紧跟8位的控制命令字后的下一个SCLK脉冲的下降沿独处DS1302的数据,读出数据时从低位0位到高位7;
日历、时钟寄存器都是以BCD码存放数据,BCD码是通过4位二进制码 来表示1位十进制的0~9这10个数。
注意事项:
单字节写时序: 两个字节的数据配合 16 个上升沿将数据写入即可。★要记得在操作 DS1302 之前关闭写保护;★注意用延时来降低单片机的速度以配合器件时序;★DS1302 读出来的数据是 BCD 码形式,要转换成我们习惯的 10 进制,转换 方法在源程序里;★读取字节之前,将 IO 设置为输入口,读取完之后,要将其改回输出口;★在写程序的时候,建议实现开辟数组(内存空间)来集中放置 DS1302 的一系列数据,方便以后扩展键盘输入。
软件编码:
// DS1302 写单字节
void ds1302_write_byte(u8 addr,u8 dat)
{
u8 i=0;
DS1302_RST=0;
_nop_();
DS1302_CLK=0;//CLK 低电平
_nop_();
DS1302_RST=1;//RST 由低到高变化
_nop_();
for(i=0;i<8;i++)//循环 8 次,每次写 1 位,先写低位再写高位
{
DS1302_IO=addr&0x01;
addr>>=1;
DS1302_CLK=1;
_nop_();
DS1302_CLK=0;//CLK 由低到高产生一个上升沿,从而写入数据
_nop_();
}
for(i=0;i<8;i++)//循环 8 次,每次写 1 位,先写低位再写高位
{
DS1302_IO=dat&0x01;
dat>>=1;
DS1302_CLK=1;
_nop_();
DS1302_CLK=0;
_nop_();
}
DS1302_RST=0;//RST 拉低
_nop_();
}
// DS1302 读单字节
u8 ds1302_read_byte(u8 addr)
{
u8 i=0;
u8 temp=0;
u8 value=0;
DS1302_RST=0;
_nop_();
DS1302_CLK=0;//CLK 低电平
_nop_();
DS1302_RST=1;//RST 由低到高变化
_nop_();
for(i=0;i<8;i++) //循环 8 次,每次写 1 位,先写低位再写高位
{
DS1302_IO=addr&0x01;
addr>>=1;
DS1302_CLK=1;
_nop_();
DS1302_CLK=0; //CLK 由低到高产生一个上升沿,从而写入数据
_nop_();
}
for(i=0;i<8;i++) //循环 8 次,每次读 1 位,先读低位再读高位
{
temp=DS1302_IO;
value=(temp<<7)|(value>>1);//先将 value 右移 1 位,然后 temp 左移 7 位,最后或运算
DS1302_CLK=1;
_nop_();
DS1302_CLK=0;
_nop_();
}
DS1302_RST=0;//RST 拉低
_nop_();
DS1302_CLK=1;//对于实物中,P3.4 口没有外接上拉电阻的,此处代码需要添加,使数据口有一个上
//升沿脉冲。
_nop_();
DS1302_IO = 0;
_nop_();
DS1302_IO = 1;
_nop_();
return value;
}
// ds1302 初始化时间void ds1302_init ( void ){u8 i = 0 ;ds1302_write_byte ( 0x8E , 0X00 );for ( i = 0 ; i < 7 ; i ++){ds1302_write_byte ( gWRITE_RTC_ADDR [ i ], gDS1302_TIME [ i ]);}ds1302_write_byte ( 0x8E , 0X80 );}
// ds1302读取时间void ds1302_read_time ( void ){u8 i = 0 ;for ( i = 0 ; i < 7 ; i ++){gDS1302_TIME [ i ]= ds1302_read_byte ( gREAD_RTC_ADDR [ i ]);}}