最近用了款DS1302 RTC实时时钟,自己动手做个万年历时钟,加上闹钟,再也不用担心午睡超时了。
按键说明:S1 时间设置;S2 闹铃设置;S3 移动模式;S4 时间减;S5 时间加;S6 确认; S7 取消。
制作出来的实物图如下:
电路原理图如下:
单片机源程序如下:
先来一段1302驱动程序:
/*
*******************************************************************************
*
* 文 件 名:DS1302.c
* 描 述:实时时钟芯片DS1302驱动模块
* 功 能:
*******************************************************************************
*/
#include "Config.h"
#include "DS1302.h"
/********LCD1302的读/写函数编辑写程序********/
/**********************************************
函 数 名: RTInputByte()
功 能: 实时时钟写入一字节
说 明: 往DS1302写入1Byte数据(内部函数)
入口参数: d 写放的数据
返 回 值: 无
**********************************************/
void RTInputByte(uchar d)
{
uchar i;
T_IO = 0; //把此双向口清零,不用在此脚加上拉电阻
for(i=8; i>0; i--)
{
T_IO=d&0x01; //取最低位
T_CLK=0;
T_CLK=1;
d=d>>1;
}
}
/******************************************************************************/
/* 函数名称 : DS1302_OutputByte */
/* 函数描述 : 从DS1302读取1Byte数据函数 */
/* 输入参数 : 无 */
/* 参数描述 : 无 */
/* 返回值 : 无 */
/******************************************************************************/
uchar RTOutputByte(void) //换此函数正确
{
uchar i;
uchar temp;
temp = 0;
for(i = 0; i < 8; i++)
{
T_CLK = 0;
if(T_IO != 0)
temp |= (1 << i);
T_CLK = 1;
}
return(temp);
}
void reset_ds1302()
{
T_RST = 0;
T_CLK = 0;
T_RST = 1;
}
void clear_ds1302_WP()
{
reset_ds1302();
T_RST = 1;
RTInputByte(0x8E);
RTInputByte(0);
T_IO = 0;
T_RST = 0;
}
/*设置写保护*/
void set_ds1302_WP()
{
reset_ds1302();
T_RST = 1;
RTInputByte(0x8E);
RTInputByte(0x80);
T_IO = 0;
T_RST = 0;
}
/**********************************************
函 数 名: Write1302()
功 能: 往DS1302写入数据
说 明: 先写地址,后写命令/数据(内部函数)
调 用: RTInputByte(), RTOutputByte()
入口参数: ucAddr:DS1302地址,ucData:要写的数据
返 回 值: 无
**********************************************/
void Write1302(uchar ucAddr,uchar ucDa)
{
clear_ds1302_WP();
T_RST = 0;
T_CLK = 0;
T_RST = 1;
RTInputByte(ucAddr); //地址,写地址
RTInputByte(ucDa); //写1Byte数据
T_CLK = 1;
T_RST = 0;
set_ds1302_WP();
}
/**********************************************
函 数 名: Read1302()
功 能: 读取DS1302某地址的数据
说 明: 先写地址,后读命令/数据(内部函数)
调 用: RTInputByte(), RTOutputByte()
入口参数: ucAddr:DS1302地址
返 回 值: ucData:读取的数据
**********************************************/
uchar Read1302(uchar ucAddr)
{
uchar ucData;
T_RST = 0;
T_CLK = 0;
T_RST = 1;
RTInputByte(ucAddr); //地址,命令
ucData = RTOutputByte(); //读1Byte数据
T_CLK = 1;
T_RST = 0;
return(ucData);
}
/**********************************************
函 数 名: Set1302()
功 能: 设置初始时间
说 明: 先写地址,后读命令/数据(寄存器多字节方式)
调 用: Write1302()
入口参数: pClock:设置时钟数据地址 格式为: 秒 分 时 日 月 星期 年
7Byte(BCD码) 1B 1B 1B 1B 1B 1B 1B
返 回 值: 无
**********************************************/
void Set1302(uchar *pClock)
{
uchar i;
uchar ucAddr = 0x80;
Write1302(0x8e,0x00); //控制命令,WP=0, 写操作
for(i=7; i>0; i--)
{
Write1302(ucAddr, *pClock); //秒 分 时 日 月 星期 年
pClock++;
ucAddr += 2;
}
Write1302(0x8e,0x80); //控制命令,WP=1,写保护
}
/**********************************************
函 数 名: get_time()
功 能: 获取DS1302时间数据
说 明: 先写地址,后读命令/数据
调 用: Read1302()
入口参数: 无
返 回 值: *p: 把读取到的数据保存到 p 指向的数组里
**********************************************/
void get_time(uchar *p)
{
uchar i,n;
n = 0x81;
for(i=7; i>0; i--)
{
*p = Read1302(n);
p++;
n+=2;
}
}
详见附件哦~~
全部资料51hei下载地址:
DS1302.rar
(297.68 KB, 下载次数: 187)
|