#include
#include
#define uint unsigned int
#define uchar unsigned char
bit write=0;
sbit led0=P1^5;
sbit led1=P1^6;
sbit led2=P1^7;
sbit sda=P1^1;
sbit scl=P1^0;
sbit SCLK=P3^5;
sbit DATA=P3^6;
sbit RST=P3^7;
sbit sg=P2^7;
sbit ss=P2^6;
sbit sb=P2^5;
sbit sq=P2^4;
uchar code table[]={0xc0,0xf9,0xa4,0xb0,0x99,0x92,0x82,0xf8,0x80,0x90};
uchar second,minute=0;
uchar sec;
sbit beep=P3^4; // 0
uint state=0; // 0:时钟状态 1:设置秒 2:设置分 3:初始设置状态
sbit key1=P2^1; // 进入设定模式以及 确认设置 先设置秒 后设置分
sbit key3=P2^0; // ++
sbit key4=P2^2; // --
uchar count=0;
void display();
void delay()
{;;}
void delayms(uint ms)
{
uint i,j;
for(i=ms;i>0;i--);
for(j=110;j>0;j--);
}
/******************/
void start()
{
sda=1;
delay();
scl=1;
_nop_();
_nop_();
_nop_();
_nop_();
_nop_();
sda=0;
_nop_();
_nop_();
_nop_();
_nop_();
_nop_();
}
void stop()
{
sda=0;
_nop_();
scl=1;
_nop_();
_nop_();
_nop_();
_nop_();
_nop_();
sda=1;
_nop_();
_nop_();
_nop_();
_nop_();
}
void respons()
{
uchar i;
scl=1;
delay();
while((sda==1)&&(i<100))i++;
scl=0;
delay();
}
void initAT()
{
sda=1;
delay();
scl=1;
delay();
}
void write_byte(uchar date)
{
uchar i,temp;
temp=date;
for(i=0;i<8;i++)
{
temp=temp<<1;
scl=0;
delay();
sda=CY;
delay();
scl=1;
delay();
}
scl=0;
delay();
sda=1;
delay();
}
uchar read_byte()
{
uchar i,k;
scl=0;
delay();
sda=1;
delay();
for(i=0;i<8;i++)
{
scl=1;
delay();
k=(k<<1)|sda;
scl=0;
delay();
}
return k;
}
void write_add(uchar address,uchar date)
{
start();
write_byte(0xa0); //1010 000 0 0为读 1为写
respons();
write_byte(address);
respons();
write_byte(date);
respons();
stop();
}
uchar read_add(uchar address)
{
uchar date;
start();
write_byte(0xa0);
respons();
write_byte(address);
respons();
start();
write_byte(0xa1); //1010 000 1
respons();
date=read_byte();
stop();
return date;
}
/*************************************************/
void write1302(uchar dat)
{
uchar i;
SCLK=0; //拉低SCLK,为脉冲上升沿写入数据做好准备
delay(); //稍微等待,使硬件做好准备
for(i=0;i<8;i++) //连续写8个二进制位数据
{
DATA=dat&0x01; //取出dat的第0位数据写入1302 低位在前,高位在后
delay(); //稍微等待,使硬件做好准备
SCLK=1; //上升沿写入数据
delay(); //稍微等待,使硬件做好准备
SCLK=0; //重新拉低SCLK,形成脉冲
dat>>=1; //将dat的各数据位右移1位,准备写入下一个数据位
}
}
void writeset1302(uchar Cmd,uchar dat)
{
RST=0; //禁止数据传递
SCLK=0; //确保写数居前SCLK被拉低
RST=1; //启动数据传输
delay(); //稍微等待,使硬件做好准备
write1302(Cmd); //写入命令字
write1302(dat); //写数据
SCLK=1; //将时钟电平置于高电平状态
RST=0; //禁止数据传递
}
uchar Read1302()
{
uchar i,dat;
delayms(2); //稍微等待,使硬件做好准备
for(i=0;i<8;i++) //连续读8个二进制位数据
{ dat>>=1;
if(DATA==1) //如果读出的数据是1
dat|=0x80; //将1取出,写在dat的最高位
SCLK=1; //将SCLK置于高电平,为下降沿读出
_nop_(); //稍微等待
SCLK=0; //拉低SCLK,形成脉冲下降沿
_nop_();
}
return dat; //将读出的数据返回
}
uchar ReadSet1302(uchar Cmd)
{
uchar dat;
RST=0; //拉低RST
SCLK=0; //确保写数居前SCLK被拉低
RST=1; //启动数据传输
write1302(Cmd); //写入命令字
dat=Read1302(); //读出数据
SCLK=1; //将时钟电平置于已知状态
RST=0; //禁止数据传递
return dat; //将读出的数据返回
}
void confirm()
{
uchar ReadValue;
ReadValue = ReadSet1302(0x81); //从秒寄存器读数据
second=((ReadValue&0x70)>>4)*10 + (ReadValue&0x0F);//将读出数据转化 //0x70=01110000 &同为同 异为0 保留111位 0x0f=1111 保留后四位
ReadValue = ReadSet1302(0x83); //从分寄存器读
minute=((ReadValue&0x70)>>4)*10 + (ReadValue&0x0F); //将读出数据转化
}
/********************************************************************************************************************/
void init_DS1302()
{
uchar flag;
flag= ReadSet1302(0x81);
if(flag&0x80)
{ //判断时钟芯片是否关闭
writeset1302(0x8E,0x00); //根据写状态寄存器命令字,写入不保护指令
writeset1302(0x80,((second/10)<<4|(second%10))); //根据写秒寄存器命令字,写入秒的初始值
writeset1302(0x82,((minute/10)<<4|(minute%10))); //根据写分寄存器命令字,写入分的初始值
writeset1302(0x84,((23/10)<<4|(23%10))); //根据写小时寄存器命令字,写入小时的初始值
writeset1302(0x86,((18/10)<<4|(18%10))); //根据写日寄存器命令字,写入日的初始值
writeset1302(0x88,((6/10)<<4|(6%10))); //根据写月寄存器命令字,写入月的初始值
writeset1302(0x8c,((9/10)<<4|(9%10))); //根据写年寄存器命令字,写入年的初始值
writeset1302(0x90,0xa5); //打开充电功能 选择2K电阻充电方式
writeset1302(0x8E,0x80); //根据写状态寄存器命令字,写入保护指令
}
}
void bee()
{
beep=0;
delayms(100);
beep=1;
}
void display() //先秒后分
{
if(state==0||state==3)
{
uchar ge0,ge1,shi1,shi0;
ge0=second%10;
shi0=second/10;
ge1=minute%10;
shi1=minute/10;
sq=0;
P0=table[ge0];
delayms(5);
sq=1;
P0=0xff;
sb=0;
P0=table[shi0];
delayms(5);
sb=1;
P0=0xff;
ss=0;
P0=table[ge1];
delayms(5);
ss=1;
P0=0xff;
sg=0;
P0=table[shi1];
delayms(5);
sg=1;
P0=0xff;
}
else
{
uchar ge,shi;
ge=count%10;
shi=count/10;
sq=0;
P0=table[ge];
delayms(5);
sq=1;
P0=0xff;
sb=0;
P0=table[shi];
delayms(5);
sb=1;
P0=0xff;
}
}
void steins() // 将设置后的数据存入时钟模块内
{
writeset1302(0x8E,0x00); //根据写状态寄存器命令字,写入不保护指令
writeset1302(0x80,((second/10)<<4|(second%10))); //根据写秒寄存器命令字,写入秒的初始值
writeset1302(0x82,((minute/10)<<4|(minute%10))); //根据写分寄存器命令字,写入分的初始值
writeset1302(0x8E,0x80); //根据写状态寄存器命令字,写入保护指令
}
void keyscan()
{
if(key1==0) // 进入设定模式0 1 2 &确认设置 PS:先设置秒 后设置分
{
delayms(10);
if(key1==0)
{ while(!key1)display();
display();
bee();
if(state==0)
{
led0=0;
led1=1;
led2=1;
state=3;
}
else
{
if(state==3)
{
led0=1;
led1=0;
led2=1;
state=1;
count=second;
}
else
{
if(state==1) //s
{
led0=1;
led1=1;
led2=0;
state=2;
second=count;
count=minute;
}
else
{
if(state==2) //m
{
led2=0;
led1=0;
led0=0;
state=0;
minute=count;
count=0;
steins();
}
}
}
}
}
}
if(key3==0) //++
{
delayms(10);
if(key3==0)
{
while(!key3)display();;
display();
bee();
if(state==1||state==2)
{
if(count==60)
count=0;
else
count++;
}
}
}
if(key4==0) //--
{
delayms(10);
if(key4==0)
{
while(!key4)display();
display();
bee();
if(state==1||state==2)
{
if(count==0)
count=60;
else
count--;
}
}
}
}
void main()
{
beep=1;
led0=0;
led1=0;
led2=0;
state=0; //引脚初始化
initAT(); //AT24c02初始化
sec=read_add(2);
second=sec%60;
minute=sec/60;
delayms(1);
init_DS1302(); //DS1302初始化
delayms(1);
steins(); //获取时钟数据
while(1)
{
display();
confirm();
sec=minute*60+second;
write_add(2,sec);
keyscan();
}
}
上一篇:51单片机DS1302时钟芯片简单程序
下一篇:DS1302时钟与LCD1602液晶显示
推荐阅读最新更新时间:2024-03-16 16:06