zoukankan      html  css  js  c++  java
  • stm32驱动DS1302芯片

    DS1302是美国DALLAS公司推出的一种高性能、低功耗的实时时钟芯片,附加31字节静态RAM,采用三线接口与CPU进行同步通信,并可采用突发方式一次传送多个字节的时钟信号和RAM数据。实时时钟可提供秒、分、时、日、星期、月和年,一个月小与31天时可以自动调整,且具有闰年补偿功能。工作电压宽达2.55.5V。采用双电源供电(主电源和备用电源),可设置备用电源充电方式,提供了对后背电源进行涓细电流充电的能力。DS1302的外部引脚分配如下图所示。DS1302用于数据记录,特别是对某些具有特殊意义的数据点的记录上,能实现数据与出现该数据的时间同时记录,因此广泛应用于测量系统中


    各引脚的功能为:

    Vcc1:主电源;

    Vcc2:备份电源。当Vcc2>Vcc1+0.2V时,由Vcc2DS1302供电,当Vcc2< Vcc1时,由Vcc1DS1302供电。

    SCLK:串行时钟,输入,控制数据的输入与输出;

    I/O:三线接口时的双向数据线;

    CE:输入信号,在读、写数据期间,必须为高。

     

    外部MCUDS1302通讯时序如下所示



    1.       读取写入操作CE必须为高,写入时,应该在SCLK低电平时完成,SCLK上升沿芯片采样data引脚上的数据,读取时,芯片在下降沿之后将数据写入dat总线上,高电平是数据不变

    由此,写入超过过程

       SCLK低电平à延时等待电平稳定à写入数据到dataàsclk上升沿,芯片采样(0à1)à延时2usà等待芯片重新回到0à写入下一个数据

      读出过程

      下降沿芯片将数据放在dat总线上,低电平时读取

    具体过程请查看驱动代码

     

    #ifndef __DS1302_H
    #define __DS1302_H
    #include "stm32f10x.h"
    #include "delay.h"
    
    extern u8 ascii_time[7];     //保存ascii格式数据
    
    extern u8 bcd_time[7];       //保存bcd码数据
    
    typedef struct DS1302DATA
    {
        u8 year;    //年
        u8 month;   //月
        u8 day;     //日
        u8 hour;    //时
        u8 min;     //分
        u8 sec;     //秒
        u8 week;    //周
    }DS1302DATA;
    
    extern struct DS1302DATA ds1302Data;
    
    #define DS1302_RST      PDout(12)
    #define DS1302_CLK      PDout(10)
    #define DS1302_DATIN    PDin(11)
    #define DS1302_DATOUT   PDout(11)
    
    #define DS1302_DAT_INPUT()     {GPIOD->CRH &= 0XFFFF0FFF;GPIOD->CRH|=8<<12;}
    #define DS1302_DAT_OUTPUT()    {GPIOD->CRH &= 0XFFFF0FFF;GPIOD->CRH|=3<<12;}
    
    //芯片寄存器地址定义 定义的写地址,读需要+1
    #define DS1302_SEC_REG			0x80		//秒数据地址
    #define DS1302_MIN_REG			0x82		//分数据地址
    #define DS1302_HR_REG			0x84		//时数据地址
    #define DS1302_DATE_REG			0x86		//日数据地址
    #define DS1302_MONTH_REG		0x88		//月数据地址
    #define DS1302_DAY_REG			0x8a		//星期几数据地址
    #define DS1302_YEAR_REG			0x8c		//年数据地址
    #define DS1302_CONTROL_REG		0x8e		//写保护寄存器地址
    #define DS1302_CHARGER_REG		0x90 		//涓流充电寄存器			 
    #define DS1302_CLKBURST_REG		0xbe             //脉冲串寄存器
    #define DS1302_RAM_BASE                 0X30            //RAM基础地址
    
    #define CLOCKSTOP       0X80
    #define CLOCKSTART      0X00
    
    
    void Ds1302_Gpio_Init(void);
    void Ds1302_Write_Time_All(u8 start);
    void Ds1302_Readtime(void);
    
    
    
    
    #endif
    
    
    
    
    

    #include "ds1302.h"
    
    struct DS1302DATA ds1302Data = {0,0,0,0,0,0,0};
    u8 ascii_time[7] = {0};     //保存ascii格式数据
    
    u8 bcd_time[7] = {0};       //保存bcd码数据
    
    static u8 AsciiToBcd(u8 asciiData)
    {
        u8 bcdData = 0;
        bcdData = (((asciiData/10)<<4)|((asciiData%10)));
        return bcdData;
    }
    static u8 BcdToAscii(u8 bcdData)
    {
        u8 asciiData = 0;
        asciiData = (((bcdData&0xf0)>>4)*10 + (bcdData&0x0f));
        return asciiData;
    }
    
    //IO口初始化
    void Ds1302_Gpio_Init(void)
    {
        GPIO_InitTypeDef GPIO_InitStructure;
        RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOD, ENABLE);
        
        //RST
        GPIO_InitStructure.GPIO_Pin =GPIO_Pin_12;      
        GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
        GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;//推挽输出
        GPIO_Init(GPIOD, &GPIO_InitStructure);
        
        //CLK
        GPIO_InitStructure.GPIO_Pin =GPIO_Pin_10;      
        GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
        GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;//推挽输出
        GPIO_Init(GPIOD, &GPIO_InitStructure);
        
        //IO
        GPIO_InitStructure.GPIO_Pin =GPIO_Pin_11;      
        GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
        GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;//推挽输出
        GPIO_Init(GPIOD, &GPIO_InitStructure);
    }
    
    //读取一个字节的时序
    u8 Ds1302_ReadByte(void)
    {
        u8 i = 0, dat = 0;
        DS1302_DAT_INPUT();
        delayUs(5);
        for(i = 0; i <8; i++)
        {
            dat >>= 1;
            if(DS1302_DATIN == 1)dat |= 0x80;
            DS1302_CLK = 1;
            delayUs(2);
            DS1302_CLK = 0;
            delayUs(2);
        }
        return dat;
    }
    
    //写入一个字节的时序
    void Ds1302_WriteByte(u8 dat)
    {
        u8 i = 0, data = dat;
        DS1302_DAT_OUTPUT(); 
        DS1302_CLK = 0;
        delayUs(2);
        for(i = 0; i < 8; i++)
        {
            DS1302_DATOUT = data&0x01;
            delayUs(2);
            DS1302_CLK = 1;
            delayUs(2);
            DS1302_CLK = 0;
            data >>= 1;
        }
    }
    
    //写入一个寄存器
    void Ds1302_Write(u8 address,u8 dat)
    {
        DS1302_RST = 0;
        DS1302_CLK = 0;
        DS1302_RST = 1;
        Ds1302_WriteByte(address);
        Ds1302_WriteByte(dat);
        DS1302_CLK = 1;
        DS1302_RST = 0;
    }
    
    //单个写入时间
    void Ds1302_Write_Time_Singel(u8 address,u8 dat)
    {
        Ds1302_Write(DS1302_CONTROL_REG,0x00);  //取消写保护
        Ds1302_Write(address,dat);
        Ds1302_Write(DS1302_CONTROL_REG,0x80);  //打开写保护
    }
    
    //一次完成所有时间更新
    //start当前时钟运行还是停止
    void Ds1302_Write_Time_All(u8 start)
    {
        Ds1302_Write(DS1302_CONTROL_REG,0x00);      //取消写保护
        Ds1302_Write(DS1302_SEC_REG,(AsciiToBcd(ds1302Data.sec)|start));
        Ds1302_Write(DS1302_MIN_REG,AsciiToBcd(ds1302Data.min));
        Ds1302_Write(DS1302_HR_REG,AsciiToBcd(ds1302Data.hour));
        Ds1302_Write(DS1302_DATE_REG,AsciiToBcd(ds1302Data.day));
        Ds1302_Write(DS1302_MONTH_REG,AsciiToBcd(ds1302Data.month));
        Ds1302_Write(DS1302_DAY_REG,AsciiToBcd(ds1302Data.week));
        Ds1302_Write(DS1302_YEAR_REG,AsciiToBcd(ds1302Data.year));
        Ds1302_Write(DS1302_CONTROL_REG,0x80);  //打开写保护
    }
    
    
    //读取一个字节
    u8 Ds1302_Read(u8 address)
    {
        u8 data = 0;
        DS1302_RST = 0;
        DS1302_CLK = 0;
        DS1302_RST = 1;
        Ds1302_WriteByte(address|0x01); //读取地址需要与0x01相或,最低为变成1
        data = Ds1302_ReadByte();
        DS1302_CLK = 1;
        DS1302_RST = 0;
        return data;
    }
    
    //读取时间的时候默认让时间走起来
    void Ds1302_Readtime(void)
    {
        ds1302Data.sec = BcdToAscii(Ds1302_Read(DS1302_SEC_REG));  //秒
        ds1302Data.min = BcdToAscii(Ds1302_Read(DS1302_MIN_REG));  //分
        ds1302Data.hour = BcdToAscii(Ds1302_Read(DS1302_HR_REG));   //小时
        ds1302Data.day = BcdToAscii(Ds1302_Read(DS1302_DATE_REG)); //日
        ds1302Data.month = BcdToAscii(Ds1302_Read(DS1302_MONTH_REG)); //月
        ds1302Data.week = BcdToAscii(Ds1302_Read(DS1302_DAY_REG));  //星期几
        ds1302Data.year = BcdToAscii(Ds1302_Read(DS1302_YEAR_REG)); //年
    }
    
    
    
    



    DS1302有下列几组寄存器:

    DS1302 有关日历、时间的寄存器共有12个,其中有7个寄存器

    (读时81h8Dh,写时80h8Ch),存放的数据格式为BCD码形式,我们读取之后需要修改为acsii码模式,如下


    小时寄存器(85h84h)的位7用于定义DS1302是运行于12小时

    模式还是24小时模式。当为高时,选择12小时模式。在12小时模式时,

    5  ,当为1时,表示PM。在24小时模式时,位5是第二个10小时

    位。

    秒寄存器(81h80h)的位7定义为时钟暂停标志(CH)。当该

    位置为1时,时钟振荡器停止,DS1302处于低功耗状态;当该位置为

    0时,时钟开始运行。

    控制寄存器(8Fh8Eh)的位7是写保护位(WP),其它7位均置

    0。在任何的对时钟和RAM的写操作之前,WP位必须为0。当

    WP位为1时,写保护位防止对任一寄存器的写操作。

     

    DS1302中附加31字节静态RAM的地址如图


    所谓突发模式是指一次传送多个字节的时钟信号和RAM数据。

    突发模式寄存器如图


     

     

  • 相关阅读:
    176. Second Highest Salary
    175. Combine Two Tables
    172. Factorial Trailing Zeroes
    171. Excel Sheet Column Number
    169. Majority Element
    168. Excel Sheet Column Title
    167. Two Sum II
    160. Intersection of Two Linked Lists
    个人博客记录
    <meta>标签
  • 原文地址:https://www.cnblogs.com/dengxiaojun/p/4279434.html
Copyright © 2011-2022 走看看