DS1302是DALLAS公司推出的涓流充电时钟芯片,内含有一个实时时钟/日历和31字节静态RAM,通过简单的串行接口与单片机进行通信实时时钟/日历电路。提供秒分时日星期月年的信息,每月的天数和闰年的天数可自动调整,时钟操作可通过AM/PM指示决定采用24或12小时格式。DS1302与单片机之间能简单地采用同步串行的方式进行通信,仅需用到三个口线:1)RST 复位,2)SDA 数据线,3)SCK 串行时钟。时钟/RAM的读/写数据以一个字节或多达31个字节的字符组方式通信。以下程序包含DS1302的主要操作以及数据存取功能。
Ds1302.h代码
#define DS1302_VT_SECOND 0 #define DS1302_VT_MINURE 1 #define DS1302_VT_HOUR 2 #define DS1302_VT_DATE 3 #define DS1302_VT_MONTH 4 #define DS1302_VT_DAY 5 #define DS1302_VT_YEAR 6 extern unsigned char Ds1302_Buff[7]; //秒分时日月周年2011-07-14 12:00:00 void Ds1302_Init(); void Ds1302_Read_RTC(void); void Ds1302_Set_RTC(void); unsigned char Ds1302_Read_Value(unsigned char valueType); void Ds1302_Set_Value(unsigned char valueType, unsigned char value);
Ds1302.c代码
#include "intrins.h"
#include "Hardware.h"
#include "Ds1302.h"
sbit SCK = P1^3; //时钟
sbit SDA = P1^4; //数据
sbit RST = P1^5; // DS1302复位
unsigned char Ds1302_Buff[7]; //秒分时日月周年
code unsigned char write_rtc_address[7]={0x80,0x82,0x84,0x86,0x88,0x8a,0x8c}; //秒分时日月周年 最低位读写位
code unsigned char read_rtc_address[7]={0x81,0x83,0x85,0x87,0x89,0x8b,0x8d};
void Ds1302_Delay()
{
unsigned char t_delay = 100;
while(t_delay--);
}
void Ds1302_Write_Byte(unsigned char temp)
{
unsigned char i;
for (i=0; i<8; i++) //循环8次 写入数据
{
SCK = 0;
SDA = temp & 0x01; //每次传输低字节
temp >>= 1; //右移一位
SCK = 1;
}
}
unsigned char Ds1302_Read_Byte()
{
unsigned char i, temp = 0x00;
for (i=0; i<8; i++) //循环8次 读取数据
{
temp >>= 1; //右移一位
SCK = 0;
_nop_();
if(SDA)
temp |= 0x80; //每次传输低字节
SCK = 1;
}
return temp;
}
void Ds1302_Prepare_IO()
{
RST = 0;
Ds1302_Delay();
SCK = 0;
_nop_();
RST = 1;
Ds1302_Delay();
}
void Ds1302_Write(unsigned char address, unsigned char dat)
{
Ds1302_Prepare_IO();
Ds1302_Write_Byte(address); //发送地址
Ds1302_Write_Byte(dat); //发送数据
RST = 0; //恢复
}
unsigned char Ds1302_Read(unsigned char address)
{
unsigned char temp;
Ds1302_Prepare_IO();
Ds1302_Write_Byte(address);
temp = Ds1302_Read_Byte();
RST = 0;
return temp;
}
void Ds1302_Read_RTC(void) //读取 日历
{
unsigned char i, *p;
p = read_rtc_address; //地址传递
for(i=0; i<7; i++) //分7次读取 秒分时日月周年
{
Ds1302_Buff[i] = Ds1302_Read(*p);
p++;
}
}
void Ds1302_Set_RTC(void) //设定 日历
{
unsigned char i, *p;
Ds1302_Write(0x8E, 0X00);
p = write_rtc_address; //传地址
for(i=0; i<7; i++) //7次写入 秒分时日月周年
{
Ds1302_Write(*p, Ds1302_Buff[i]);
p++;
}
Ds1302_Write(0x8E, 0x80);
}
void Ds1302_Init()
{
Ds1302_Write(0x8e, 0x00); //写保护控制字,允许写
Ds1302_Write(0x80, 0x00); //开启时钟
Ds1302_Write(0x90, 0x5c); //禁止充电
}
unsigned char Ds1302_Read_Value(unsigned char valueType)
{
unsigned char temp = Ds1302_Buff[valueType];
unsigned char hour12;
if (valueType == 2)
{
if (temp & 0x80)
{
// 12小时转24小时
hour12 = ((temp & 0x10) >> 4) * 10 + (temp & 0x0F);
if (temp & 0x20)
return (hour12 + 12) % 24;
else
return hour12;
} else return ((temp & 0x30) >> 4) * 10 + (temp & 0x0F); } else return (temp >> 4) * 10 + (temp & 0x0F); } void Ds1302_Set_Value(unsigned char valueType, unsigned char value) { unsigned char highBits = value / 10; highBits <<= 4; if (valueType == 2) { Ds1302_Buff[2] = highBits + value % 10; } else Ds1302_Buff[valueType] = highBits + value % 10; }