|||
使用DS1302时主要注意的地方:
1. 在上电时,RST 必须为逻辑0 直至Vcc>2.0V。同时SCLK 在RST 驱动至逻辑1 状态时必须为逻辑0。
2. 数据输入是在SCLK的上升沿,数据输出是在SCLK的下降沿。
3. 传输方式:低位先传输。
4. 时钟运行:秒寄存器的最高位(BIT7)是作为时钟控制位,当为逻辑1时,时钟停止,为0时钟运行。所以如果要时钟运行的话就必须将秒寄存器的最高位清0
5. 12/24小时模式:小时寄存器的第7位(最高位)是选择12小时制还是24小时制。当为逻辑1时选择12小时,逻辑0选择24小时。当为12小时制时,小时寄存器的第5位用来表示上午AM和下午PM,逻辑1的时候表示PM,逻辑0的时候表示AM。
6. 在企图对DS1302操作之前,必须将WP位清零。
7. 读写模式:有两种模式,可以单字节读写,以及连续多字节读写(burst mode)。在连续多字节读写时,即burst mode,地址是必须从地址0的0位开始的。如果对时钟操作,即CLOCK操作,则必须连续写满8个字节,如下图的8个字节。若是对RAM操作,则可以不必须写满31个字节。
8. DS1302包含了实时时钟日历和31个字节的RAM,这里需要注意的是实时时钟日历的8个寄存器和31个字节的RAM是独立的,没有任何关系,不要混淆。31个RAM字节可以做其他用途,如闹钟等。因为DS1302有电池供电,所以RAM的内容不会丢失,相当于EEPROM了。用户可以用来实现特别的要求。
9. 时序必须严格按照其数据手册上来。
10. 程序如下。(已调试通过)
#include <htc.h>
//晶振4M,若晶振不一样,注意延时是否满足时序要求。
#define DS1302_Data RB2
#define DS1302_Data_Dir TRISB2
#define DS1302_CLK RB1
#define DS1302_Rst RB3
#define BURST_CLOCK 0xbe
#define BURST_RAM 0xfe
#define ADD_WP 0x8e
#define DISNABLE_WP 0x00
#define OP_CLOCK 1
#define OP_RAM 0
//启动计时,24小时制,
UINT8 bank1 Clock_InitData[8] = {0x00,0x00,0x23,0x24,0x11,0x03,0x10,0x00};
//秒 分 时 日 月 星期 年 控制
UINT8 CurClockData[8];//当前时钟数据
void Delay_us(unsigned char dus);//函数声明
//***********************************************************************
//*功能: 初始化DS1302
//*参数: 无
//*返回: 无
//***********************************************************************
void Init_DS1302(void)
{
//初始化IO口
TRISB &= ~0x0a;//RB1,RB3作为输出
DS1302_Rst = 0;
DS1302_CLK = 0;
//初始化时间:
DS1302_BurstWtData(OP_CLOCK,Clock_InitData,8);
}
//***********************************************************************
//*功能: 向DS1302写入一个字节
//*参数: 所需要写入的内容
//*返回: 无
//***********************************************************************
void DS1302_WtOneByte(UINT8 wtdata)
{
UINT8 i;
DS1302_Data_Dir = OUTPUT;
for (i=0;i<8;i++)
{
if (wtdata&0x01)//低位先发:
{
DS1302_Data = 1;
}
else
{
DS1302_Data = 0;
}
wtdata >>= 1;
DS1302_CLK = 0;//上升沿写
Delay_us(5);
DS1302_CLK = 1;
Delay_us(5);
}
Delay_us(10);
}
//***********************************************************************
//*功能: 向DS1302读出一个字节
//*参数: 无
//*返回: 读到的字节内容
//***********************************************************************
UINT8 DS1302_RdOneByte(void)
{
UINT8 i,Recv = 0;
DS1302_Data_Dir = INPUT;
for (i=0;i<8;i++)
{
Recv >>= 1;
DS1302_CLK = 0;//下降沿读
Delay_us(2);
if (DS1302_Data)
{
Recv |= 0x80;
}
DS1302_CLK = 1;
Delay_us(4);
}
Delay_us(10);
return Recv;
}
//***********************************************************************
//*功能: 向DS1302写入单字节数据
//*参数: 数据内容
//*返回: 无
//***********************************************************************
void DS1302_WtData(UINT8 Addr,UINT8 wtdata)
{
DS1302_CLK = 0;//在RST置1前清0
Delay_us(2);
DS1302_Rst = 1;
Delay_us(5);
DS1302_WtOneByte(Addr);
DS1302_WtOneByte(wtdata);
Delay_us(2);
DS1302_Rst = 0;
Delay_us(10);
}
//***********************************************************************
//*功能: 向DS1302读出单字节数据
//*参数: 数据内容
//*返回: 无
//***********************************************************************
UINT8 DS1302_RdData(UINT8 Addr)
{
UINT8 RdTemp;
DS1302_CLK = 0;
Delay_us(2);
DS1302_Rst = 1;
Delay_us(5);
DS1302_WtOneByte(Addr);
RdTemp = DS1302_RdOneByte();
Delay_us(2);
DS1302_Rst = 0;
Delay_us(10);
return RdTemp;
}
//***********************************************************************
//*功能: 向DS1302连续写入多字节数据,Burst Mode
//*参数: 数据内容
//*返回: 无
//***********************************************************************
void DS1302_BurstWtData(UINT8 BurstType,UINT8 *wtp,UINT8 wtcnt)
{
UINT8 i,Command;
if (BurstType == OP_CLOCK)
{
Command = BURST_CLOCK;
#if wtcnt > 8
#error CLOCK MAX bytes is 8.
#endif
}
else
{
Command = BURST_RAM;
}
DS1302_WtData(ADD_WP,DISNABLE_WP);
Delay_us(5);
DS1302_CLK = 0;
Delay_us(2);
DS1302_Rst = 1;
Delay_us(5);
DS1302_WtOneByte(Command);//写BURST指令
for (i=0;i<wtcnt;i++)//连续写字节
{
DS1302_WtOneByte(*wtp);
wtp++;
}
DS1302_Rst = 0;
Delay_us(2);
}
//***********************************************************************
//*功能: 向DS1302连续读出多字节数据,Burst Mode
//*参数: 数据内容
//*返回: 无
//***********************************************************************
void DS1302_BurstRdData(UINT8 BurstType,UINT8 *rdp,UINT8 rdcnt)
{
UINT8 i,Command;
if (BurstType == OP_CLOCK)
{
Command = BURST_CLOCK;
#if wtcnt > 8
#error CLOCK MAX bytes is 8.
#endif
}
else
{
Command = BURST_RAM;
}
Command += 1;//读
DS1302_CLK = 0;
Delay_us(2);
DS1302_Rst = 1;
Delay_us(5);
DS1302_WtOneByte(Command);//写BURST指令
for (i=0;i<rdcnt;i++)//连续读出多字节
{
*rdp = DS1302_RdOneByte();
rdp++;
}
DS1302_Rst = 0;
Delay_us(2);
}
//***********************************************************************
//*功能:粗略延时
//*参数: 延时的NOP数,最大255
//*返回: 无
//***********************************************************************
void Delay_us(unsigned char dus)
{
while(dus--);
}