完整版 电路图和程序代码 下载地址
https://pan.baidu.com/s/1DEeLkidDxWFqs-c98673tw?pwd=8888
部分代码展示
#include <REGX51.H>
#define uchar unsigned char
#define uint unsigned int
sbit DATA=P1^2; //数据(PA0)
sbit SCK=P1^0; //移位时钟(PA1)
sbit RCK=P1^1; //锁存时钟(PA2)
sbit P20=P2^0;
sbit P21=P2^1;
sbit P33=P3^3;
sbit DS1302_CLK = P1^7; //实时时钟时钟线引脚
sbit DS1302_IO = P1^6; //实时时钟数据线引脚
sbit DS1302_RST = P1^5;//实时时钟复位线引脚
sbit ACC0 = ACC^0;
sbit ACC7 = ACC^7;
char hide_sec,hide_min,hide_hour,hide_day,hide_week,hide_month,hide_year; //秒,分,时到日,月,年位闪的计数
sbit Set = P3^0; //模式切换键
sbit Up = P3^1; //加法按钮
sbit Down = P3^2; //减法按钮
sbit out = P3^4; //立刻跳出调整模式按钮
char done,count,temp,flag,up_flag,down_flag;
uchar DS1302[8]={4,5,6,7,8,6,9}; //秒,分,时,日,月,星期,年
uint f;
uchar t[14];
uchar k;
uchar code Seg[]={0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7f,0x6f,0x00};
void display(uchar L1,uchar L2,uchar L3,uchar L4,uchar L5,uchar L6,uchar L7,uchar L8,
uchar L9,uchar L10,uchar L11,uchar L12,uchar L13,uchar L14);
/***********DS1302时钟部分子程序******************/
typedef struct __SYSTEMTIME__
{
unsigned char Second;
unsigned char Minute;
unsigned char Hour;
unsigned char Week;
unsigned char Day;
unsigned char Month;
unsigned char Year;
unsigned char DateString[14];
}SYSTEMTIME; //定义的时间类型
SYSTEMTIME CurrentTime;
#define DS1302_SECOND 0x81 //时钟芯片的寄存器位置,存放时间
#define DS1302_MINUTE 0x83
#define DS1302_HOUR 0x85
#define DS1302_WEEK 0x8A
#define DS1302_DAY 0x87
#define DS1302_MONTH 0x89
#define DS1302_YEAR 0x8D
void DS1302InputByte(unsigned char d) //实时时钟写入一字节(内部函数)
{
unsigned char i;
ACC = d;
for(i=8; i>0; i--)
{
DS1302_IO = ACC0; //相当于汇编中的 RRC
DS1302_CLK = 1;
DS1302_CLK = 0;
ACC = ACC >> 1;
}
}
unsigned char DS1302OutputByte(void) //实时时钟读取一字节(内部函数)
{
unsigned char i;
for(i=8; i>0; i--)
{
ACC = ACC >>1; //相当于汇编中的 RRC
ACC7 = DS1302_IO;
DS1302_CLK = 1;
DS1302_CLK = 0;//在下降沿数据从移位寄存器输出
}
return(ACC);
}
void Write1302(unsigned char ucAddr, unsigned char ucDa) //ucAddr: DS1302地址, ucData: 要写的数据
{
DS1302_RST = 0;
DS1302_CLK = 0;
DS1302_RST = 1;//只有在clk为低时,才能将rst置高
DS1302InputByte(ucAddr); // 地址,命令
DS1302InputByte(ucDa); // 写1Byte数据
DS1302_CLK = 1;//上升沿将数据写入DS1302内部移位寄存器
DS1302_RST = 0;
}
unsigned char Read1302(unsigned char ucAddr) //读取DS1302某地址的数据
{
unsigned char ucData;
DS1302_RST = 0;
DS1302_CLK = 0;
DS1302_RST = 1;//启动数据传送
DS1302InputByte(ucAddr|0x01); // 地址,命令 ,读操作
ucData = DS1302OutputByte(); // 读1Byte数据,应在上升沿前读取
DS1302_CLK = 1;
DS1302_RST = 0;
return(ucData);
}
void DS1302_GetTime(SYSTEMTIME *Time) //获取时钟芯片的时钟数据到自定义的结构型数组
{
unsigned char ReadValue;
ReadValue = Read1302(DS1302_SECOND);
Time->Second = ((ReadValue&0x70)>>4)*10 + (ReadValue&0x0F);//16进制转为10进制
ReadValue = Read1302(DS1302_MINUTE);
Time->Minute = ((ReadValue&0x70)>>4)*10 + (ReadValue&0x0F);
ReadValue = Read1302(DS1302_HOUR);
Time->Hour = ((ReadValue&0x70)>>4)*10 + (ReadValue&0x0F);
ReadValue = Read1302(DS1302_DAY);
Time->Day = ((ReadValue&0x70)>>4)*10 + (ReadValue&0x0F);
ReadValue = Read1302(DS1302_WEEK);
Time->Week = ((ReadValue&0x70)>>4)*10 + (ReadValue&0x0F);
ReadValue = Read1302(DS1302_MONTH);
Time->Month = ((ReadValue&0x70)>>4)*10 + (ReadValue&0x0F);
ReadValue = Read1302(DS1302_YEAR);
Time->Year = ((ReadValue&0x70)>>4)*10 + (ReadValue&0x0F);
}
void DateToStr(SYSTEMTIME *Time) //将时间年,月,日,星期数据转换成液晶显示字符串,放到数组里DateString[]
{ if(hide_year<5) //这里的if,else语句都是判断位闪烁,<2显示数据,>2就不显示,输出字符串为 2007/07/22
{
Time->DateString[0] = 2;
Time->DateString[1] = 0;
Time->DateString[2] = Time->Year/10;
Time->DateString[3] = Time->Year%10;
}
else
{
Time->DateString[2] =10 ;
Time->DateString[3] =10 ;
}
if(hide_month<5)
{
Time->DateString[4] = Time->Month/10;
Time->DateString[5] = Time->Month%10;
}
else
{
Time->DateString[4] =10;
Time->DateString[5] =10;
}
if(hide_day<5)
{
Time->DateString[6] = Time->Day/10;
Time->DateString[7] = Time->Day%10;
}
else
{
Time->DateString[6] =10;
Time->DateString[7] =10;
}
if(hide_hour<5)
{
Time->DateString[8] = Time->Hour/10;
Time->DateString[9] = Time->Hour%10;
}
else
{
Time->DateString[8] =10;
Time->DateString[9] =10;
}
if(hide_min<5)
{
Time->DateString[10] = Time->Minute/10;
Time->DateString[11] = Time->Minute%10;
}
else
{
Time->DateString[10] =10;
Time->DateString[11] =10;
}
if(hide_sec<5)
{
Time->DateString[12] = Time->Second/10 ;
Time->DateString[13] = Time->Second%10 ;
}
else
{
Time->DateString[12] =10;
Time->DateString[13] =10;
}
}
void show_time() //显示程序
{ uchar i;
uchar j;
DS1302_GetTime(&CurrentTime); //获取时钟芯片的时间数据
DateToStr(&CurrentTime);
for(j=0;j<14;j++)
{t[j]=Seg[CurrentTime.DateString[13-j]];}
RCK=0;//锁存置低
for(j=0;j<14;j++)
{
for(i=0;i<8;i++)
{
SCK=0; //移位脉冲置低
DATA=t[j]&0x80;
t[j]=t[j]<<1;
SCK=1;//上升沿时数据寄存器的数据移位
}
}
RCK=1; //上升沿时移位寄存器的数据进入数据存储寄存器
}
/*延时子程序*/
void mdelay(uint delay)
{ uint i;
for(;delay>0;delay--)
{for(i=0;i<62;i++) //1ms延时.
{;}
}
}
void outkey() //跳出调整模式,返回默认显示
{ uchar Second;
if(out==0)
{ mdelay(8);
count=0;
hide_sec=0,hide_min=0,hide_hour=0,hide_day=0,hide_week=0,hide_month=0,hide_year=0;
Second=Read1302(DS1302_SECOND);
Write1302(0x80,Second&0x7f);
done=0;
while(out==0);
}
}
void Upkey()//升序按键
{
Up=1;
if(Up==0)
{
mdelay(8);
switch(count)
{/*case 1:
temp=Read1302(DS1302_SECOND); //读取秒数
temp=temp+1; //秒数加1
up_flag=1; //数据调整后更新标志
if((temp&0x7f)>0x59) //超过59秒,清零
temp=0;