可设置时间的时钟
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
#include<reg52.h>
#include <intrins.h>
#define uchar unsigned char
#define uint unsigned int
//1302
sbit SCK=P3^6; // 时钟脉冲
sbit SDA=P3^4; // 数据
sbit RST = P3^5;// DS1302复位
//1602
sbit rs=P2^6; // 命令/数据
sbit rw=P2^5; // 读/写
sbit e=P2^7; // 读写使能
sbit t=P2^0; //
sbit w=P2^1; //
unsigned char l_tmpdate[7]={0,40,20,9,12,1,11};//秒分时日月周年
unsigned char l_tmpdisplay[18];
code unsigned char write_rtc_address[7]=
{0x80,0x82,0x84,0x86,0x88,0x8a,0x8c}; //秒分时日月周年 最低位读写位
code unsigned char read_rtc_address[7]=
{0x81,0x83,0x85,0x87,0x89,0x8b,0x8d}; //共阴数码管 0-9 '-' '熄灭‘表
/******************************************************************/
/* 函数声明 */
/******************************************************************/
void Write_Ds1302_byte(unsigned char temp);
void Write_Ds1302( unsigned char address,unsigned char dat );
unsigned char Read_Ds1302 ( unsigned char address );
void Read_RTC(void);
void Set_RTC(void);
void InitTIMER0(void);
void delay(uchar a);
void lcd_mang();
void write_lcd1602(uchar cmd,uchar i);
void ini_lcd1602();
void time();
void settime();
void Set(uchar j);
/******************************************************************/
/* 主函数 */
/******************************************************************/
void main()
{
ini_lcd1602();
Set_RTC(); //写入时钟值,如果使用备用电池时候,不需要每次上电写入,此程序应该屏蔽
while(1)
{
if(t==0)
{
delay(50);
if(t==0)
{
settime();
}
}
time();
}
}
void settime()
{
uchar j;
uchar tmp;
j=1;
while(j!=0)
{
if(t==0)
{
delay(50);
if(t==0)
j++;
}
if(j==6)
{j=0;write_lcd1602(0x0c,0);};//关闭闪烁,退出设置
if(j==6)
{j=0;};
if(j==1) //分
{
write_lcd1602(0x80+0x44,0);
write_lcd1602(0x0d,0);
delay(5);
if(w==0)
{
delay(50);
if(w==0)
{
tmp=l_tmpdate[1]%16;//取低四位
l_tmpdate[1]=l_tmpdate[1]/16; //取高四位
l_tmpdate[1]=l_tmpdate[1]*10+tmp;
l_tmpdate[1]=l_tmpdate[1]+1;
if(l_tmpdate[1]==60)
l_tmpdate[1]=0;
Set(1);
time();
}
}
}
if(j==2) //时
{
write_lcd1602(0x80+0x41,0);
write_lcd1602(0x0d,0);
delay(1);
if(w==0)
{
delay(50);
if(w==0)
{
tmp=l_tmpdate[2]%16;//取低四位
l_tmpdate[2]=l_tmpdate[2]/16; //取高四位
l_tmpdate[2]=l_tmpdate[2]*10+tmp;
l_tmpdate[2]=l_tmpdate[2]+1;
if(l_tmpdate[2]==24)
l_tmpdate[2]=0;
Set(2);
time();
}
}
}
if(j==3) //日
{
write_lcd1602(0x80+0x09,0);
write_lcd1602(0x0d,0);
delay
(5);
if(w==0)
{
delay(50);
if(w==0)
{
tmp=l_tmpdate[3]%16;//取低四位
l_tmpdate[3]=l_tmpdate[3]/16; //取高四位
l_tmpdate[3]=l_tmpdate[3]*10+tmp;
l_tmpdat
e[3]=l_tmpdate[3]+1;
if(l_tmpdate[3]==32)
l_tmpdate[3]=1;
Set(3);
time();
}
}
}
if(j==4) //月
{
write_lcd1602(0x80+0x06,0);
write_lcd1602(0x0d,0);
delay(5);
if(w==0)
{
delay(50);
if(w==0)
{
tmp=l_tmpdate[4]%16;//取低四位
l_tmpdate[4]=l_tmpdate[4]/16; //取高四位
l_tmpdate[4]=l_tmpdate[4]*10+tmp;
l_tmpdate[4]=l_tmpdate[4]+1;
if(l_tmpdate[4]==13)
l_tmpdate[4]=1;
Set(4);
time();
}
}
}
if(j==5) //年
{
write_lcd1602(0x80+0x03,0);
write_lcd1602(0x0d,0);
delay(5);
if(w==0)
{
delay(50);
if(w==0)
{
tmp=l_tmpdate[6]%16;//取低四位
l_tmpdate[6]=l_tmpdate[6]/16; //取高四位
l_tmpdate[6]=l_tmpdate[6]*10+tmp;
l_tmpdate[6]=l_tmpdate[6]+1;
if(l_tmpdate[6]==99)
l_tmpdate[6]=0;
Set(6);
time();
}
}
}
}
}
void Set(uchar j)
{
uchar tmp;
tmp=l_tmpdate[j]/10; //shiwei
l_tmpdate[j]=l_tmpdate[j]%10; //gewei
l_tmpdate[j]=l_tmpdate[j]+tmp*16;
Write_Ds1302(0x8E,0x00);
Write_Ds1302(write_rtc_address[j],l_tmpdate[j]);
Write_Ds1302(0x8E,0x80);
}
void time()
{
uchar i;
Read_RTC();
l_tmpdisplay[0]=0x32;
l_tmpdisplay[1]=0x30;
l_tmpdisplay[2]=l_tmpdate[6]/16+0x30; //BCD变ASCII
l_tmpdisplay[3]=l_tmpdate[6]%16+0x30; //BCD变ASCII
l_tmpdisplay[4]='-'; //加入"-"
l_tmpdisplay[5]=l_tmpdate[4]/16+0x30; //BCD变ASCII
l_tmpdisplay[6]=l_tmpdate[4]%16+0x30; //BCD变ASCII
l_tmpdisplay[7]='-';
l_tmpdisplay[8]=l_tmpdate[3]/16+0x30; //BCD变ASCII
l_tmpdisplay[9]=l_tmpdate[3]%16+0x30; //BCD变ASCII
l_tmpdisplay[10]=l_tmpdate[2]/16+0x30; //BCD变ASCII
l_tmpdisplay[11]=l_tmpdate[2]%16+0x30; //BCD变ASCII
l_tmpdisplay[12]=':'; //加入":"
l_tmpdisplay[13]=l_tmpdate[1]/16+0x30; //BCD变ASCII
l_tmpdisplay[14]=l_tmpdate[1]%16+0x30; //BCD变ASCII
l_tmpdisplay[15]=':';
l_tmpdisplay[16]=l_tmpdate[0]/16+0x30; //BCD变ASCII
l_tmpdisplay[17]=l_tmpdate[0]%16+0x30; //BCD变ASCII
write_lcd1602(0x80,0); //显示年月日
for(i=0;i<=9;i++)
write_lcd1602(l_tmpdisplay[i],1);
write_lcd1602(0x80+0x40,0); //显秒
for(i=10;i<=17;i++)
write_lcd1602(l_tmpdisplay[i],1);
}
void delay(uchar a)
{
uchar i;
while(a--)
{
for(i=0;i<250;i++)
{
_nop_();
_nop_();
_nop_();
_nop_();
}
}
}
//判忙
void lcd_mang()
{
rs=0;
rw=1;
e=1;
_nop_();
_nop_();
_nop_();
_nop_();
while(P0&0x80);
e=0;
}
//1602的写
void write_lcd1602(uchar cmd,uchar i)
{
lcd_mang();
rs=i;
rw=0;
e=0;
_nop_();
_nop_();
e=1;
_nop_();
_nop_();
P0=cmd;
_nop_();
_nop_();
_nop_();
_nop_();
e=0;
}
//1602的初始化
void ini_lcd1602()
{
write_lcd1602(0x38,0);
delay(1);
write_lcd1602(0x0c,0);
delay(1);
write_lcd1602(0x06,0);
delay(1);
write_lcd1602(0x01,0);
delay(1);
}
/******************************************************************/
/* 写一个字节 */
/*********
*********************************************************/
void Write_Ds1302_Byte(unsigned char temp)
{
unsigned char i;
for (i=0;i<8;i++) //循环8次 写入数据
{
SCK=0;
SDA=temp&0x01; //每次传输低字节
temp>>=1; //右移一位
SCK=1;
}
}
/******************************************************************/
/* 写入DS1302 */
/******************************************************************/
void Write_Ds1302( unsigned char address,unsigned char dat )
{
RST=0;
_nop_();
SCK=0;
_nop_();
RST=1;
_nop_(); //启动
Write_Ds1302_Byte(address); //发送地址
Write_Ds1302_Byte(dat); //发送数据
RST=0; //恢复
}
/******************************************************************/
/* 读出DS1302数据 */
/******************************************************************/
unsigned char Read_Ds1302 ( unsigned char address )
{
unsigned char i,temp=0x00;
RST=0;
_nop_();
_nop_();
SCK=0;
_nop_();
_nop_();
RST=1;
_nop_();
_nop_();
Write_Ds1302_Byte(address);
for (i=0;i<8;i++) //循环8次 读取数据
{
if(SDA)
temp|=0x80; //每次传输低字节
SCK=0;
temp>>=1; //右移一位
_nop_();
_nop_();
_nop_();
SCK=1;
}
return (temp); //返回
}
/******************************************************************/
/* 读时钟数据 */
/******************************************************************/
void Read_RTC(void) //读取 日历
{
unsigned char i,*p;
p=read_rtc_address; //地址传递
for(i=0;i<7;i++) //分7次读取 秒分时日月周年
{
l_tmpdate[i]=Read_Ds1302(*p);
p++;
}
}
/******************************************************************/
/* 设定时钟数据 */
/******************************************************************/
void Set_RTC(void) //设定 日历
{
unsigned char i,*p,tmp;
for(i=0;i<7;i++)
{ //BCD处理
tmp=l_tmpdate[i]/10;
l_tmpdate[i]=l_tmpdate[i]%10;
l_tmpdate[i]=l_tmpdate[i]+tmp*16;
}
Write_Ds1302(0x8E,0x00);
p=write_rtc_address; //传地址
for(i=0;i<7;i++) //7次写入 秒分时日月周年
{
Write_
Ds1302(*p,l_tmpdate[i]);
p++;
}
Write_Ds1302(0x8E,0x80);
}