打印
[应用相关]

实时时钟芯片DS1302在STM32系列使用详解

[复制链接]
96|0
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主
tpgf|  楼主 | 2024-10-30 11:51 | 只看该作者 |只看大图 回帖奖励 |倒序浏览 |阅读模式
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

使用特权

评论回复
发新帖 我要提问
您需要登录后才可以回帖 登录 | 注册

本版积分规则

1931

主题

15614

帖子

12

粉丝