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数据。

    突发模式寄存器如图


     

     

  • 相关阅读:
    我的数学之美(一)——RANSAC算法详解
    机器学习经典算法之-----最小二乘法(zz)
    基于大数据的餐饮推荐系统总结
    Hive 数据错位修复方案
    Python 2.x 判断 Excel 是否包含指定的 sheet
    Shell脚本判断目录是否为空
    MySQL启动报错 The server quit without updating PID file 解决方案
    DolphinScheduler 1.3.2集群版(基于CDH5.13.1)安装手册
    添加 Shell 脚本的启动用户限制
    CentOS 7 离线安装 MySQL 5.7
  • 原文地址:https://www.cnblogs.com/dengxiaojun/p/4279434.html
Copyright © 2011-2022 走看看