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

突发模式寄存器如图


 

 

posted @ 2014-10-07 23:36  邓小俊  阅读(4047)  评论(0编辑  收藏  举报