ds1302 电子时钟
#include<reg51.h>#define uint8 unsigned char
#define uint16 unsigned int
sbit RST=P1^7;
sbit SDA=P3^5;
sbit SCK=P1^6;
uint8 LedBitCnt; //LedBitCnt控制数码管的位选
uint8 ms2_flag; //2ms数码管动态扫描时标消息
uint8 ms10_flag,ms500_flag;
uint8 ms2_cnt,ms10_cnt,count,s1num;
uint8 dis_buff={0};
uint8 shi=12,fen=23,miao=56;
uint8 code SegTab[]={0x3f,0x06,0x5b,0x4f,
0x66,0x6d,0x7d,0x07,
0x7f,0x6f,0x40,0x00};
sbit ADDR0 = P2^0;//74hc138的输入控制端A
sbit ADDR1 = P2^1;//74hc138的输入控制端B
sbit ADDR2 = P2^2;//74hc138的输入控制端C
sbit adjust=P3^2;
sbit add=P3^3;
sbit sub=P3^4;
//常数宏
#define DS1302_SECOND_WRITE 0x80//写时钟芯片的寄存器位置
#define DS1302_MINUTE_WRITE 0x82
#define DS1302_HOUR_WRITE 0x84
#define DS1302_SECOND_READ0x81//读时钟芯片的寄存器位置
#define DS1302_MINUTE_READ0x83
#define DS1302_HOUR_READ0x85
void reset_ds1302(void)
{
RST=0;
SCK=0;
RST=1;
}
/****************************
*名称:write_ds1302_byte
*说明:无
*功能: 写入8bit数据
*调用: 无
*输入:dat:要写入的数据
*输出:无
*****************************/
void write_ds1302_byte(uint8 dat)
{
uint8i;
SCK=0;//初始化时钟线置为0
for(i=0;i<8;i++)//开始传输8个字节的数据
{
SDA=dat&0x01;//取最低位,注意DS1302的数据
//和地址都是从最低位开始传输的
SCK=1;//时钟线拉高,制造上升沿,SDA数据被传输
SCK=0;//时钟线拉低,为下个上升沿做准备
dat>>=1;//数据右移一位,准备传输的下一位
}
}
/****************************
*名称:read_ds1302_byte
*说明:无
*功能: 读取8bit数据
*调用: 无
*输入:dat:读取的数据
*输出:无
*****************************/
uint8 read_ds1302_byte(void)
{
uint8i ,dat=0;
for (i=0;i<8;i++)
{
dat >>=1;
if(SDA)
dat|=0x80;
SCK=1;
SCK=0;//制造下降沿
}
return dat;
}
/****************************
*名称:write_ds1302
*说明:先写地址,后写数据
*功能:向addr相应地址中写一个字节的数据
*调用: write_ds1302_byte()
*输入:addr:要写入的控制字,dat:要写入的数据
*输出:无
*****************************/
void write_ds1302(uint8 addr,uint8 dat)
{
reset_ds1302();
write_ds1302_byte(addr);
write_ds1302_byte((dat/10)<<4|(dat%10));
//将10进制转化为压缩的BCD码,传输时为BCD码
SCK=1;//时钟线拉高
RST=0;//读取结束,CE置0,结束数据的传输
}
/****************************
*名称:uint8 read_ds1302
*说明:先写地址,后读数据
*功能: 从addr相应地址中读取一个字节的数据
*调用: write_ds1302_byte(),read_ds1302_byte()
*输入:addr:要写入的控制字
*输出:dat:要写入的数据
*****************************/
uint8 read_ds1302(uint8 addr)
{
uint8 dat,datH,datL,temp=0;
reset_ds1302();
write_ds1302_byte(addr);
dat=read_ds1302_byte();
SCK=1;
RST=0;
datH=dat/16;//将压缩的BCD码转换为十进制相当于左移4位
datL=dat%16;
temp=datH*10+datL;
return temp;//返回得到的时间/日期
}
/****************************
*名称:void Init_DS1302
*说明:给1302写一个初始值
*功能:
*调用: write_ds1302()
*输入:无
*输出:无
*****************************/
void Init_DS1302(void)
{
write_ds1302(0x8e,0x00);//写保护关
write_ds1302(DS1302_SECOND_WRITE,40);
write_ds1302(DS1302_MINUTE_WRITE,59);
write_ds1302(DS1302_HOUR_WRITE,23);//初始24小时模式
write_ds1302(0x8e,0x80);//写保护开
}
void init()
{
TMOD=0x01;
TH1=0xf8;
TL1=0xcd;
ET0=1;
TR1=1;
ET1=1;
}
void time_to_disbuff(void)
{
dis_buff=miao%10;
dis_buff=miao/10;
dis_buff=10;
dis_buff=fen%10;
dis_buff=fen/10;
dis_buff=10;
dis_buff=shi%10;
dis_buff=shi/10;
}
void disp()
{
P0=SegTab];
switch(LedBitCnt)
{
case 0:
ADDR0=0;ADDR1=0;ADDR2=0;
break;
case 1:
ADDR0=1;ADDR1=0;ADDR2=0;
break;
case 2:
ADDR0=0;ADDR1=1;ADDR2=0;
break;
case 3:
ADDR0=1;ADDR1=1;ADDR2=0;
break;
case 4:
ADDR0=0;ADDR1=0;ADDR2=1;
break;
case 5:
ADDR0=1;ADDR1=0;ADDR2=1;
break;
case 6:
ADDR0=0;ADDR1=1;ADDR2=1;
break;
case 7:
ADDR0=1;ADDR1=1;ADDR2=1;
break;
}
}
void main()
{
Init_DS1302();
init();
EA=1;
while(1)
{
miao=read_ds1302(DS1302_SECOND_READ);
fen=read_ds1302(DS1302_MINUTE_READ);
shi=read_ds1302(DS1302_HOUR_READ);
if(ms2_flag)
{
ms2_flag=0;
LedBitCnt++;
if(LedBitCnt>7)
{
LedBitCnt=0;
}
time_to_disbuff();
disp();
}
}
}
void timer1() interrupt 3//定时1ms
{
TH1=0xf8;
TL1=0xcd;
ms2_flag=1; //用于数码管显示
ms2_cnt++;
if(ms2_cnt>=5)
{
ms2_cnt=0;
ms10_flag=1;//用于键扫描
if(++ms10_cnt>=50)
{
ms10_cnt=0;
ms500_flag=~ms500_flag;
}
}
} 成功读取DS1302的时间,现在在添加按键调时遇到了问题,在第一次按下调整键时候,停止走时,显示秒的两位数码管以1 Hz 频率闪烁;如果第二次按下调整键,则分开始闪烁,秒恢复正常显示;如果第三次按下调整键,则时开始闪烁,分恢复正常显示;如果第四次按下调整键,时恢复正常显示,开始走时。在数码管闪烁的时候,按下加或者减键可以调整相应的显示内容,按下加减时要把调整后的数据送到时钟寄存器中后,在读出来,还是直接显示? 一般是在进调整状态时,把当前时钟读到一个缓存中,调整时钟其实是在调整缓存中的数据,当调整完一起写入1302,并开始走时。调整期间,1302会按原时钟继续走时。
另外,你这个帖子放这个版不合适 sf49ers 发表于 2012-11-11 21:33 static/image/common/back.gif
一般是在进调整状态时,把当前时钟读到一个缓存中,调整时钟其实是在调整缓存中的数据,当调整完一起写入13 ...
一般的时钟不是进入调时状态,都停止走时,我的功能键第一次按下,调整秒的,我要把秒从0x80中读出来,当按加时,秒++,在把这个值写进0x80,最后在送到数码管显示? bbxyliyang08 发表于 2012-11-11 23:17 static/image/common/back.gif
一般的时钟不是进入调时状态,都停止走时,我的功能键第一次按下,调整秒的,我要把秒从0x80中读出来,当 ...
干吗做这么麻烦,反正时钟不走了,中间往1302写有什么意义。
如果象pc界面那样,专门有个取消键,本次调整无效,按原时间走,你怎么办 void keyscan()
{
if(adjust==0)
{
delayms(10);
if(adjust==0)
{
s1num++;
while(!adjust);
if(s1num==1)
{
flagm=1;
TR0=0;
}
}
}
if(s1num==2)
{
flagm=0;
flagf=1;
}
if(s1num==3)
{
flagm=0;
flagf=0;
flags=1;
}
if(s1num==4)
{
TR0=1;
flags=0;
s1num=0;
}
if(adjust!=0)
{
if(add==0)
{
delayms(10);
if(add==0)
{
while(!add);
if(s1num==1)
{
miao++;
if(miao==60)
miao=0;
}
if(s1num==2)
{
fen++;
if(fen==60)
fen=0;
}
if(s1num==3)
{
shi++;
if(shi==24)
shi=0;
}
}
}
if(sub==0)
{
delayms(10);
if(sub==0)
{
while(!sub);
if(s1num==1)
{
miao--;
if(miao==-1)
miao=59;
}
if(s1num==2)
{
fen--;
if(fen==-1)
fen=59;
}
if(s1num==3)
{
shi--;
if(shi==-1)
shi=23;
}
}
}
}
write_ds1302(DS1302_SECOND_WRITE,miao);
write_ds1302(DS1302_MINUTE_WRITE,fen);
write_ds1302(DS1302_HOUR_WRITE,shi);
} 这样写对吗?
页:
[1]