Files

157 lines
4.0 KiB
C
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
/******************************************************************************
* 文件名:ds1302.c
* 功能:DS1302 实时时钟驱动
* 说明:提供读写 DS1302 的底层函数,以及时间和闹钟参数的存取。
* 时间以 BCD 码格式存储于 TIME 数组中。
* 硬件接口:DSIO=P3^4,RST=P3^5,SCLK=P3^6
* 编译器:Keil C51
******************************************************************************/
#include"ds1302.h"
/* DS1302 读写地址(存储顺序:秒、分、时、日、月、周、年) */
uchar code READ_RTC_ADDR[7] = {0x81, 0x83, 0x85, 0x87, 0x89, 0x8b, 0x8d};
uchar code WRITE_RTC_ADDR[7] = {0x80, 0x82, 0x84, 0x86, 0x88, 0x8a, 0x8c};
/* DS1302 默认时间:2013 年 1 月 1 日 星期二 12:00:00 */
/* 存储顺序:秒、分、时、日、月、周、年(BCD 码) */
uchar TIME[7] = {0, 0, 0x12, 0x01, 0x01, 0x02, 0x13};
/******************************************************************************
* 函数名:Ds1302Write
* 功能:向 DS1302 写入一字节数据(先写地址,再写数据)
* 输入:addr = 寄存器地址,dat = 要写入的数据
* 输出:无
* 时序:RST 置高 → 写入 8 位地址(低位在前)→ 写入 8 位数据(低位在前)→ RST 置低
******************************************************************************/
void Ds1302Write(uchar addr, uchar dat)
{
uchar n;
RST = 0;
_nop_();
SCLK = 0; /* 时钟先置低 */
_nop_();
RST = 1; /* 使能 DS1302 */
_nop_();
for(n = 0; n < 8; n++) /* 发送 8 位地址(低位在前) */
{
DSIO = addr & 0x01; /* 输出当前位 */
addr >>= 1;
SCLK = 1; /* 时钟上升沿,DS1302 锁存数据 */
_nop_();
SCLK = 0;
_nop_();
}
for(n = 0; n < 8; n++) /* 发送 8 位数据(低位在前) */
{
DSIO = dat & 0x01;
dat >>= 1;
SCLK = 1;
_nop_();
SCLK = 0;
_nop_();
}
RST = 0; /* 结束通信 */
_nop_();
}
/******************************************************************************
* 函数名:Ds1302Read
* 功能:从 DS1302 读取一字节数据(先写地址,再读数据)
* 输入:addr = 寄存器地址
* 输出:返回读取到的数据
* 时序:RST 置高 → 写入 8 位地址(低位在前)→ 读取 8 位数据(高位在前)→ RST 置低
******************************************************************************/
uchar Ds1302Read(uchar addr)
{
uchar n, dat, dat1;
RST = 0;
_nop_();
SCLK = 0; /* 时钟先置低 */
_nop_();
RST = 1; /* 使能 DS1302 */
_nop_();
for(n = 0; n < 8; n++) /* 发送 8 位地址(低位在前) */
{
DSIO = addr & 0x01;
addr >>= 1;
SCLK = 1;
_nop_();
SCLK = 0; /* 下降沿后 DS1302 输出数据 */
_nop_();
}
_nop_();
for(n = 0; n < 8; n++) /* 读取 8 位数据(高位在前) */
{
dat1 = DSIO; /* 采样数据线 */
dat = (dat >> 1) | (dat1 << 7); /* 高位在前,依次移入 */
SCLK = 1;
_nop_();
SCLK = 0;
_nop_();
}
RST = 0; /* 结束通信 */
_nop_();
SCLK = 1; /* 确保时序完整 */
_nop_();
DSIO = 0;
_nop_();
DSIO = 1;
_nop_();
return dat;
}
/******************************************************************************
* 函数名:Ds1302Init
* 功能:初始化 DS1302 时钟芯片
* 输入:无
* 输出:无
* 说明:检查秒寄存器的 CH 位。如果 CH=1 表示时钟停止(首次上电),
* 则关闭写保护并写入默认时间;如果 CH=0 表示时钟已在运行,跳过初始化。
******************************************************************************/
void Ds1302Init()
{
uchar n;
uchar sec;
sec = Ds1302Read(0x81); /* 读取秒寄存器,检查 CH 位(最高位) */
if(!(sec & 0x80)) /* CH=0:时钟正在运行,无需初始化 */
return;
/* CH=1:时钟停止,系统首次上电,写入默认时间 */
Ds1302Write(0x8E, 0x00); /* 关闭写保护 */
for(n = 0; n < 7; n++)
{
Ds1302Write(WRITE_RTC_ADDR[n], TIME[n]);
}
Ds1302Write(0x8E, 0x80); /* 开启写保护 */
}
/******************************************************************************
* 函数名:Ds1302ReadTime
* 功能:读取 DS1302 当前时间到 TIME 数组
* 输入:无
* 输出:无(结果存入全局 TIME 数组)
******************************************************************************/
void Ds1302ReadTime()
{
uchar n;
for(n = 0; n < 7; n++)
{
TIME[n] = Ds1302Read(READ_RTC_ADDR[n]);
}
}