📄 ds1302.c
字号:
//===========================================================
// 文件名: ds1302.c
// 创建日期: 080303
// 创建: 神之吻
// 试验难度: 入门级试验
// 描述: 该文件包含了操作ds1302时钟芯片的底层驱动函数,
// 自底向上依次为:
// 1.向I/O引脚发送/接受一个字节的数据(可为命令/地址或是数据)
// 2.向ds1302芯片的寄存器读/写一个字节数据
// 3.设置初始时间以及读出当前时间(秒,分,小时,日,月,星期,年
//
//------------------------------------------------------------
//********************************************************
//* 头文件
//********************************************************
#include <reg52.h>
#include "main.h"
//*******************************************************
//* WriteByte
//*
//*功能描述:该函数是最底层的驱动函数,负责向ds1302的I/0口
// 发送一个字节的数据
//*输入参数: ByteData,
//*返回值:无
//*******************************************************
void WriteByte(uint8 ByteData)
{
uint8 i,DataTmp;
DataTmp = ByteData; //缓存数据
//NOP
//由低位(bit0)到高位(bit7)依次向I/O引脚写入数据
for(i = 0;i < 8;i ++)
{
SCLK = 0;
//NOP //此处延时函数待定,手册给出的最小值为100ns
//在SCLK上升沿之前,向I/O口准备好数据
if((DataTmp & 0x01) == 1)
IO = 1;
else
IO = 0;
//NOP //延时建立时间tDC,手册上给出最小值位50ns
SCLK = 1; //SCLK的上升沿向写入字节中的一位数据
DataTmp >>= 1; //右移一位,以便下一位写入
}
}
//*******************************************************
//* ReadByte
//*
//*功能描述:该函数是最底层的驱动函数,负责从ds1302的I/0口
// 接收一个字节的数据
//*输入参数:无
//*返回值:读出的一个字节数据
//*******************************************************
uint8 ReadByte()
{
uint8 i,DataTmp;
DataTmp = 0; //数据缓冲初始化为0
for(i = 0;i < 8;i ++)
{
SCLK = 0; //下降沿触发I/O口读出一位数据
//NOP //延迟至少Tcdd时间,以等待输出数据有效,手册上给出Tcdd最大值为200ns
DataTmp += ((uint8)IO<<7); //读出I/O输出的一位数据,置于dataTmp的最高位(由于数据是按bit0~bit7读出)
DataTmp >>= 1; //右移一位,以便存储读出后续数据
SCLK = 1;
}
return DataTmp; //返回读出的一个字节数据
}
//*******************************************************
//* WriteReg
//*
//*功能描述: 1.该函数通过调用最底层驱动函数WriteByte,向ds1302
// 的RAM中写入一个字节数据
// 2.写入方法为:在连续的十六个SCLK时钟内,
// 前八个时钟周期写入一个字节的命令/地址,后八个
// 时钟周期写入一个字节的数据
// 3.每一位在时钟周期的上升沿写入
//*输入参数:
// Addr:待写入寄存器的地址
// Data:待写入的一个字节数据
//*返回值:无
//*******************************************************
void WriteReg(uint8 Addr,uint8 Data)
{
RST = 1; //拉高RST,以使能读写操作
//NOP //延时tCC后方可拉高SCLK,手册上给出Vcc=5V的条件下,tCC的最小值为1us
WriteByte(Addr); //写入地址
WriteByte(Data); //写入数据
RST = 0; //RST复位为0,以便下一次读写操作
SCLK = 0; //SCLK复位为0,以便下一次读写操作
}
//*******************************************************
//* ReadReg
//*
//*功能描述: 1.该函数通过调用最底层驱动函数WriteByte和ReadByte,从ds1302
// 的RAM中读出一个字节数据
// 2.写入方法为:在连续的十六个SCLK时钟内,
// 前八个时钟周期写入一个字节的命令/地址,后八个
// 时钟周期写入一个字节的数据
// 3.其中地址在前八个时钟周期上升沿写入,数据在后八个
// 时钟周期的下降沿读出
//*输入参数:
// Addr:待读出数据的目的寄存器的地址
//*返回值: Data:读出的一个字节数据
//*******************************************************
uint8 ReadReg(uint8 Addr)
{
uint8 ReadData; //缓冲读出的一个字节数据
RST = 1; //拉高RST,以使能读写操作
//NOP //延时tCC后方可拉高SCLK,手册上给出Vcc=5V的条件下,tCC的最小值为1us
WriteByte(Addr); //写入地址
ReadData = ReadByte(); //读出寄存器内容
RST = 0; //RST复位为0,以便下一次读写操作
SCLK = 0; //SCLK复位为0,以便下一次读写操作
return ReadData; //返回读出数据
}
//*******************************************************
//* SetTime
//*
//*功能描述: 1.该函数通过调用最驱动函数WriteReg,向ds1302的时间/日历寄存器
// 中写入初始化时间(写入顺序为秒 分 时 日 月 星期 年)
// 2.写入方法为:先写控制寄存器,将其WP置为0,以解除写保护,然后依次
// 写入秒 分 时 日 月 星期 年寄存器
//*输入参数:
// *TimePtr:指向时间信息区域首地址的指针(格式为秒 分 时 日 月 星期 年)
//*返回值: 无
//*******************************************************
void SetTime(uint8* TimePtr)
{
uint8* TimePtrTmp;
uint8 CtrRegAddr = 0x8E; //控制寄存器地址,RD/WR位(Bit0)为0,表明对该寄存器进行写操作,
uint8 CtrRegData = 0x00; //写入控制寄存器的数据,WP为0,以解除写保护
uint8 InitRegAddr = 0x80; //初始寄存器地址,即秒寄存器地址,RD/WR位(Bit0)为0,表明对该寄存器进行写操作
uint8 i;
TimePtrTmp = TimePtr;
RST = 0;
WriteReg(CtrRegAddr,CtrRegData); //写控制寄存器,以解除写保护
//启动写操作(顺序为秒 分 时 日 月 星期 年)
for( i = 0;i < 7;i ++)
{
WriteReg(InitRegAddr,*TimePtrTmp); //将时间信息写入当前寄存器
InitRegAddr += 0x02; //指向下一个时间/日历寄存器
TimePtrTmp += 1; //指向下一个数据
}
}
//*******************************************************
//* ReadTime
//*
//*功能描述: 1.该函数通过调用最驱动函数ReadReg,从ds1302的时间/日历寄存器
// 中读出当前时间(读出顺序为秒 分 时 日 月 星期 年)
// 2.读方法为:依次读出秒 分 时 日 月 星期 年寄存器
//*输入参数:
// *TimePtr:指向时间信息存储区域首地址的指针(格式为秒 分 时 日 月 星期 年)
//*返回值: 无
//*******************************************************
void ReadTime(uint8 *TimePtr)
{
uint8* TimePtrTmp;
uint8 InitRegAddr = 0x81; //初始寄存器地址,即秒寄存器地址,RD/WR位(Bit0)为1,表明对该寄存器进行读操作
uint8 i;
TimePtrTmp = TimePtr;
RST = 0; //读写之前将RST复位为0
//启动读操作(顺序为秒 分 时 日 月 星期 年)
for( i = 0;i < 7;i ++)
{
*TimePtrTmp = ReadReg(InitRegAddr); //读出当前寄存器的值
InitRegAddr += 0x02; //指向下一个时间/日历寄存器
TimePtrTmp += 1; //指向下一个数据的存储区域
}
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -