1. DS1302简介
1.1 特点
(1)可对秒,分,时,日,周,月,和年进行计数,对于小于 31 天的月,月末的日期自动进行调整,还具有闰年校正的功能;
(2)用于高速数据暂存的 31 字节的非易失性静态 RAM;
(3)时钟可以采用 24 小时格式或带 AM(上 午)/PM(下午)的 12 小时格式;
(4)宽工作电压:2.0V~5.5V;
(5)2.5V时耗小于300nA;
(6)用于时钟或RAM数据读/写的单字节或多字节数据传输方式;
(7)简单的3线接口与单片机通信;
与时钟/RAM 通信仅需 3 根线:
RST(复位)
I/O(数据线)
SCLK(串行时钟)
(8)TTL兼容(Vcc=5V);
(9)可选地工业温度范围-40℃至85℃;
(10)封装:DIP8和SOP8。
1.2 引脚
1.3 工作原理
如下图,RST 信号有效后,移位寄存器单元会在 SCLK 同步脉冲信号的控制下从 I/O 上串行接收 8 位指令字节,然后将 8 位指令字节进行串并转换并送至 ROM 指令译码单元。由 ROM 指令译码单元对 8 位指令字节进行译码,以决定内部寄存器的地址以及读写状态。然后在接下来的 SCLK 同步脉冲信号的控制下将 8 位数据写进或者读出相应的寄存器。数据传送也可以采用多字节方式,先将 8 位相应的指令字节写入,然后在连续的 SCLK 的脉冲信号同步下,将数据字节连续写入或读出日历/时钟寄存器(或者RAM 单元)。SCLK 脉冲的个数在单字节方式下为 8 加 8,在多字节方式下为 8 加最大可达到 248 的数。
1.4 硬件电路
1.5 时序图
1.5.1 读数据
1.5.2 写数据
2. DS1302使用
每一数据传送由命令字节初始化:
命令字节总是从最低有效LSB位0开始输入。
通过把 RST 输入驱动至高电平来启动所有的数据传送。
RST 输入有两种功能:
接通控制逻辑:当RST信号被接通时,控制逻辑被激活,允许地址和命令序列被送入移位寄存器。
中止数据传送:RST信号可以在任何时刻中止正在进行的数据传送。
寄存器 0:最高位 CH 是一个时钟停止标志位。停止后为1,正常工作为0。如果 Vcc1 悬空或者是电池没电了,当我们下次重新上电时,读取这一位,那这一位就是 1,我们可以通过这一位判断时钟在单片机系统掉电后是否还正常运行。剩下的 7 位高 3 位是秒的十位,低 4 位是秒的个位。
寄存器 1:最高位未使用,剩下的 7 位中高 3 位是分钟的十位,低 4 位是分钟的个位。
寄存器 2:bit7 是 1 的话代表是 12 小时制,0 代表是 24 小时制;bit6 固定是 0,bit5 在 12 小时制下 0 代表的是上午,1 代表的是下午,在 24 小时制下和 bit4 一起代表了小时的十 位,低 4 位代表的是小时的个位。
寄存器 3:高 2 位固定是 0,bit5 和 bit4 是日期的十位,低 4 位是日期的个位。
寄存器 4:高 3 位固定是 0,bit4 是月的十位,低 4 位是月的个位。
寄存器 5:高 5 位固定是 0,低 3 位代表了星期。
寄存器 6:高 4 位代表了年的十位,低 4 位代表了年的个位。请特别注意,这里的 00~ 99 指的是 2000 年~2099 年。
寄存器 7:最高位一个写保护位,如果这一位是 1,那么是禁止给任何其它寄存器或者 那 31 个字节的 RAM 写数据的。因此在写数据之前,这一位必须先写成 0。
3. 代码编写
3.1 时钟初始化
DS1302写入和读取时分秒的地址命令“秒分时日月周年”,最低位读写位:
uint8_t READ_RTC_ADDR[7] = {0x81, 0x83, 0x85, 0x87, 0x89, 0x8b, 0x8d};
uint8_t WRITE_RTC_ADDR[7] = {0x80, 0x82, 0x84, 0x86, 0x88, 0x8a, 0x8c};
DS1302时钟初始化2013年1月1日星期二12点00分00秒,存储顺序“秒分时日月周年”,存储格式为BCD码:
uint8_t TIME[7] = {0x00, 0x47, 0x21, 0x29, 0x3, 0x03, 0x23};
3.2 单片机引脚配置
配置成推挽输出模式:
void DS1302_OUT_GPIO_INIT(void)
{
GPIO_InitTypeDef GPIO_InitStructure;
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA,ENABLE);
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0 | GPIO_Pin_1| GPIO_Pin_2;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;//
GPIO_Init(GPIOA, &GPIO_InitStructure);
}
数据引脚配置成上拉输入模式:
void DS1302_IN_GPIO_INIT(void)
{
GPIO_InitTypeDef GPIO_InitStructure;
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA,ENABLE);
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0 ;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU;//
GPIO_Init(GPIOA, &GPIO_InitStructure);
}
引脚宏定义:
#define DSIO_H GPIO_SetBits(GPIOA,GPIO_Pin_0)
#define DSIO_L GPIO_ResetBits(GPIOA,GPIO_Pin_0)
#define RST_H GPIO_SetBits(GPIOA,GPIO_Pin_1)
#define RST_L GPIO_ResetBits(GPIOA,GPIO_Pin_1)
#define SCLK_H GPIO_SetBits(GPIOA,GPIO_Pin_2)
#define SCLK_L GPIO_ResetBits(GPIOA,GPIO_Pin_2)
#define GET_DSIO GPIO_ReadInputDataBit(GPIOA,GPIO_Pin_0)
3.3 DS1302写操作配置
void Ds1302Write(uint8_t addr, uint8_t dat)
{
uint8_t n;
DS1302_OUT_GPIO_INIT();
RST_L;
Delay1us();//加个1us的延时
SCLK_L;//先将SCLK置低电平。
Delay1us();
RST_H; //然后将RST(CE)置高电平。
Delay1us();
for (n=0; n<8; n++)//开始传送八位地址命令
{
if(addr & 0x01)
{
DSIO_H;//数据从低位开始传送
}
else
{
DSIO_L;
}
addr >>= 1;
SCLK_H;//数据在上升沿时,DS1302读取数据
Delay1us();
SCLK_L;
Delay1us();
}
for (n=0; n<8; n++)//写入8位数据
{
if(dat & 0x01)
{
DSIO_H;//数据从低位开始传送
}
else
{
DSIO_L;
}
dat >>= 1;
SCLK_H;//数据在上升沿时,DS1302读取数据
Delay1us();
SCLK_L;
Delay1us();
}
RST_L;//传送数据结束
Delay1us();
}
3.4 DS1302读操作配置
uint8_t Ds1302Read(uint8_t addr)
{
uint8_t n,dat,dat1;
RST_L;
Delay1us();
SCLK_L;//先将SCLK置低电平。
Delay1us();
RST_H;//然后将RST(CE)置高电平。
Delay1us();
for(n=0; n<8; n++)//开始传送八位地址命令
{
if(addr & 0x01)
{
DSIO_H;//数据从低位开始传送
}
else
{
DSIO_L;
}
addr >>= 1;
SCLK_H;//数据在上升沿时,DS1302读取数据
Delay1us();
SCLK_L;//DS1302下降沿时,放置数据
Delay1us();
}
Delay1us();
DS1302_IN_GPIO_INIT();
for(n=0; n<8; n++)//读取8位数据
{
dat1 = GET_DSIO;//从最低位开始接收
dat = (dat>>1) | (dat1<<7);
SCLK_H;
Delay1us();
SCLK_L;//DS1302下降沿时,放置数据
Delay1us();
}
DS1302_OUT_GPIO_INIT();
RST_L;
Delay1us(); //以下为DS1302复位的稳定时间,必须的。
SCLK_H;
Delay1us();
DSIO_L;
Delay1us();
DSIO_H;
Delay1us();
return dat;
}
3.5 初始化DS1302
void Ds1302Init(void)
{
uint8_t n;
Ds1302Write(0x8E,0X00); //禁止写保护,就是关闭写保护功能
for (n=0; n<7; n++)//写入7个字节的时钟信号:分秒时日月周年
{
Ds1302Write(WRITE_RTC_ADDR[n],TIME[n]);
}
Ds1302Write(0x8E,0x80); //打开写保护功能
}
3.6 读取时钟信息
void Ds1302ReadTime(void)
{
uint8_t n;
for (n=0; n<7; n++)//读取7个字节的时钟信号:分秒时日月周年
{
TIME[n] = Ds1302Read(READ_RTC_ADDR[n]);
}
}
————————————————
版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
原文链接:https://blog.csdn.net/MANONGDKY/article/details/143248212
|