您的位置:首页 > 其它

DS1302+AT24C02+按键数码管显示程序 (原创)

2017-03-25 15:25 477 查看
#include<reg52.h>
#include<intrins.h>
#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;
d
4000
elayms(1);
init_DS1302();			  //DS1302初始化
delayms(1);
steins();				  //获取时钟数据
while(1)
{
display();
confirm();
sec=minute*60+second;
write_add(2,sec);
keyscan();
}
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  51单片机