22时钟ICDS1302应用之二实际制做.docx
《22时钟ICDS1302应用之二实际制做.docx》由会员分享,可在线阅读,更多相关《22时钟ICDS1302应用之二实际制做.docx(10页珍藏版)》请在冰豆网上搜索。
22时钟ICDS1302应用之二实际制做
22、时钟IC_DS1302应用之二……实际制做
2009-05-0719:
42
这个电路本身还是很简单的,见下图:
元件就是DS1302、一个晶振,一个104的瓷片电源滤波电容。
和98ATS52连接的线有电源5V(Vcc)、接地(GND)、SCLK、I/O、CE(RST)。
共5根线。
按上面的电路图焊好后别忘了检测一直是否有短路,我检测了我的电路,电源和地之间的静态电流为50uA。
接上单片机后如图:
软件部分的编写,首先得把显示部分调试好,我用的是LCD12864,是已经调试好的可调用子程序12863put.c
下面DS1302程序部分,是根据网上用的非常多的一个DS1302子程序修改的:
/**************************/
/*ds1302实时时钟C程序 */
/**************************/
#include
#defineucharunsignedchar
sbitT_CLK=P1^0;/*实时时钟时钟线引脚*/
sbitT_IO=P1^1;/*实时时钟数据线引脚*/
sbitT_RST=P1^2;/*实时时钟复位线引脚*/
sbitACC0=ACC^0;
sbitACC7=ACC^7;
voidInit1302(void);
voidv_W1302(ucharucAddr,ucharucDa);
ucharuc_R1302(ucharucAddr);
voidv_Set1302(uchar*pSecDa);
voidv_Get1302(ucharucCurtime[]);
/******************************************
*名称:
v_RTInputByte
*说明:
*功能:
往DS1302写入1Byte数据
*调用:
*输入:
ucDa写入的数据
*返回值:
无
******************************************/
voidv_WTInputByte(ucharucDa)
{
uchari;
ACC=ucDa;
for(i=8;i>0;i--)
{
T_IO=ACC0;//相当于汇编中的RRC
T_CLK=1;
T_CLK=0;
ACC=ACC>>1;
}
}
/*****************************************
*名称:
ucharuc_RTOutputByte
*说明:
*功能:
从DS1302读取1Byte数据
*调用:
*输入:
*返回值:
ACC
******************************************/
ucharuc_RTOutputByte(void)
{
uchari;
for(i=8;i>0;i--)
{
ACC=ACC>>1;//相当于汇编中的RRC
ACC7=T_IO;
T_CLK=1;
T_CLK=0;
}
return(ACC);
}
/********************************************
*名称:
v_W1302
*说明:
先写地址,后写数据
*功能:
往DS1302写入数据
*调用:
v_RTInputByte()
*输入:
ucAddr:
控制字,ucDa:
要写的数据
*返回值:
无
*********************************************/
voidv_W1302(ucharucAddr,ucharucDa)
{
//OE=0;
T_RST=0;
T_CLK=0;
T_RST=1;
v_WTInputByte(ucAddr);/*地址,命令*/
v_WTInputByte(ucDa);/*写1Byte数据*/
T_CLK=1;
T_RST=0;
//OE=1;
}
/*********************************************
*名称:
uc_R1302
*说明:
先写地址,后读数据
*功能:
读取DS1302某地址的数据
*调用:
v_RTInputByte(),uc_RTOutputByte()
*输入:
ucAddr:
控制字
*返回值:
ucDa:
读取的数据
**********************************************/
ucharuc_R1302(ucharucAddr)
{
ucharucDa;
//OE=0;
T_RST=0;
T_CLK=0;
T_RST=1;
v_WTInputByte(ucAddr);/*地址,命令*/
ucDa=uc_RTOutputByte();/*读1Byte数据*/
T_CLK=1;
T_RST=0;
//OE=1;
return(ucDa);
}
/***************************************
*
*名称:
v_Set1302
*说明:
*功能:
设置初始时间
*调用:
v_W1302()
*输入:
pSecDa:
初始时间数组首地址。
*返回值:
无
****************************************/
voidv_Set1302(uchar*pSecDa)
{
uchari;
ucharucAddr=0x80;
v_W1302(0x8e,0x00);//控制命令,WP=0,允许写操作
for(i=7;i>0;i--)
{
v_W1302(ucAddr,*pSecDa);//秒分时日月星期年
pSecDa++;
ucAddr+=2;
}
v_W1302(0x8e,0x80);//控制命令,WP=1,写保护
}
/**********************************************
*名称:
v_Get1302
*说明:
*功能:
读取DS1302当前时间
*调用:
uc_R1302()
*输入:
ucCurtime:
保存当前时间数据的数组地址
*返回值:
无
***********************************************/
voidv_Get1302(ucharucCurtime[])
{
uchari;
ucharucAddr=0x81;
for(i=0;i<7;i++)
{
ucCurtime[i]=uc_R1302(ucAddr);//格式为:
秒分时日月星期年
ucAddr+=2;
}
}
/*******************************************
*名称:
Init1302
*说明:
*功能:
初始化DS1302
*调用:
*输入:
*返回值:
无
*******************************************/
voidInit1302(void)
{
v_W1302(0x8e,0x00);//控制写入WP=0
v_W1302(0x90,0xa5);//辅助电源充电命令
v_W1302(0x80,0x00);//写秒
v_W1302(0x82,0x59);//写分
v_W1302(0x84,0x10);//写时
v_W1302(0x86,0x07);//写日
v_W1302(0x88,0x05);//写月
v_W1302(0x8a,0x04);//写星期
v_W1302(0x8c,0x09);//写年
v_W1302(0x8e,0x80);//写保护WP=1
}
下面是主程序部分DS1302main.c,将DS1302、LCD12864子程序整合在一起。
#include
#defineucharunsignedchar
#defineuintunsignedint
externvoidLcmClear(void); //清屏
externvoidLcmInit(void); //初始化
externvoidLcmPutstr(ucharrow,uchary,uchar*str);//在设定位置显示字符串
externvoidInit1302(void);//初始化DS1302
externvoidv_Get1302(ucharucCurtime[]);//获取DS1302内的7个字节时间数据存入数组中
uchargetTimebuf[7];//用于存放获取的时间数据
ucharsetTimebuf[7];//用于存放要设置的时间日期数据
uchartime[]={":
:
"};//时间格式字符串
uchardate[]={"20--"};//日期格式字符串
uchardaylist[]={"SunMonTueWedThuFriSat"};//星期字符列表
ucharday1[]={" "};//星期格式字符串
//****************
// 主函数
//****************
voidMain(void)
{uchari,j,k;
Init1302();//初始化DS1302
LcmInit();//初始化LCD12864
LcmClear();
LcmPutstr(0,28,"DS1302TEST");
LcmPutstr(3,24,"");
LcmPutstr(5,0,"BLOG:
http:
//");
LcmPutstr(6,18,");
LcmPutstr(7,8,"Email:
TXZ001@");
while
(1)
{
v_Get1302(getTimebuf);//获取DS1302内7个时间日期数据存入数组getTimebuf[].
time[6]=(getTimebuf[0])/16+48;//格式化时间秒
time[7]=(getTimebuf[0])%16+48;
time[3]=(getTimebuf[1])/16+48;//格式化时间分
time[4]=(getTimebuf[1])%16+48;
time[0]=(getTimebuf[2])/16+48;//格式化时间小时
time[1]=(getTimebuf[2])%16+48;
date[8]=getTimebuf[3]/16+48;//格式化日期日
date[9]=getTimebuf[3]%16+48;
date[5]=getTimebuf[4]/16+48;//格式化日期月
date[6]=getTimebuf[4]%16+48;
date[2]=getTimebuf[6]/16+48;//格式化日期年
date[3]=getTimebuf[6]%16+48;
day1[0]=daylist[(getTimebuf[5]%10)*3];//格式化星期
day1[1]=daylist[(getTimebuf[5]%10)*3+1];
day1[2]=daylist[(getTimebuf[5]%10)*3+2];
LcmPutstr(2,0,date);//显示日期
LcmPutstr(2,96,day1);//显示星期
LcmPutstr(3,36,time);//显示时间
for(i=0;i<5;i++)
for(j=0;j<255;j++)
for(k=0;k<255;k++);
}
}
用Keil将程序编译:
生成HEX文件后下载到AT89S52板上,运行,如下图:
结果并不好,时间数据在乱跳,但我发现秒数基本是一秒一跳,分钟也是一分一跳的,就是说DS1302在正常工作,说明CH修改已正常,只是读取数据不正常。
在分析了软件部分都正常后,决定将数据线缩短。
因为原来的数据线大约有10多CM。
再加上从接口到52芯片的转接线总共大约有30CM长了。
因此得将DS1302的数据线剪短,再直接插在52芯片的接口P1上试试。
如下图:
上面这张图是示意图,是晚上补做的图,没插电。
其结果是基本上能看出是在我设定的时间初值上每秒跳一下,但还是很频繁地有乱跳现象。
我于是就想那么短的线难道数据还不稳?
莫非是阻抗太高了,使数据线容易受到干扰?
我想起那个标准电路中三路数据线是有上拉10K的电阻的,当时我想反正常P1内部也有上拉电阻,就没外接电阻了。
现在想起来是不是P1内部的上拉电阻值太大了,使读取数据受外界干扰。
我想起我P0上外接的不就是10K的排阻吗?
于是将DS1302的数据线插到了P0口的P0.0、P0.1、P0.2上,在软件里修改了数据线接口的定义,然后烧写运行。
哈哈!
现在就非常稳定了。
总结,其实DS1302的数据引线略长一点是没关系的,但那三根数据线上的上拉电阻一定得要,否则阻抗太高就很容易造成数据传输不稳定,受到外界干扰,造成显示数据乱跳的现象。
DS1302的调试不是很容易,因为当你做好了电路,写好了软件烧写运行后,如果DS1302没有任何反应。
你就不太好判断问题出在哪,是晶振不起振还是程序改写秒寄存器CH没成功?
我就因此换过晶振,换过DS1302,反复修改过程序。
因为DS1302在初始接上电源时晶振是不起振的,就无法检测晶振电路的好坏。
这是这个电路的难点。
类别:
默认分类|添加到搜藏|浏览(855)|评论 (8)
上一篇:
21、时钟IC_DS1302的应用之一…... 下一篇:
23、补一堂通俗的电子基础课
最近读者:
登录后,您就出现在这里。