DS1302 是 DALLAS 公司推出的涓流充电时钟芯片内含有一个实时时钟/日历和 31 字节静态 RAM可通过简单的串行接口与单片机进行通信。
可提供:
1.秒分时日日期月年的信息;
2.每月的天数和闰年的天数可自动调整;
3.可通过 AM/PM 指示决定采用 24 或 12 小时格式;
4.保持数据和时钟信息时功率小于 1mW。
设计内容:
1.设备初始化时钟为 23 时 59 分 50 秒,闹钟提醒时间 0 时 0 分 0 秒;
2.指示灯L1以0.2秒闪烁,5秒后关闭,代表闹钟提醒功能。
考试的时候官方是会提供驱动给我们的,不太清楚的同学可以参考蓝桥杯大赛——驱动程序,官方给我们提供了这部分程序,对我们的代码编写工作量来说确实减少了很多,但这个驱动并不是可以直接拿来用的,我们还需要再写一部分程序才能真正利用到这部分代码,下面咱们就用官方提供的驱动来编程吧。
#include<stc15f2k60s2.h>
#include <intrins.h>
#define uchar unsigned char //定义无符号字符类型uchar
#define uint unsigned int //定义无符号整型类型uint
sbit SCK=P1^7;
sbit SDA=P2^3;
sbit RST = P1^3; // DS1302复位
uchar shijian[]={50,59,23,0,0,0,0};
uchar code tab[]={0xc0,0xf9,0xa4,0xb0,0x99,0x92,0x82,0xf8,0x80,0x90,0xbf,0xff};//数字0~9,“-”,“关”
uchar yi,er,san,si,wu,liu,qi,ba; //定义字符型变量yi,er,san,si,wu,liu,qi,ba,当作数码管显示控制变量
uchar Naozhong[]={0,0,0};
uint L1_shan_tt=0,L1_guan_tt=0;
bit fla=0,L1=0;
void delayms(int ms); //延时函数
void allinit(); //初始化函数
void display1(uchar yi,uchar er); //第一、二段数码管函数
void display2(uchar san,uchar si); //第三、四段数码管函数
void display3(uchar wu,uchar liu); //第五、六段数码管函数
void display4(uchar qi,uchar ba); //第七、八段数码管函数
void Write_Ds1302_Byte(unsigned char temp);
void Write_Ds1302(unsigned char address,unsigned char dat) ;
unsigned char Read_Ds1302(unsigned char address);
void DS_init();
void DS_get();
void Timer0Init(void); //1毫秒@12.000MHz
void main()//主函数
{
allinit(); //初始化函数
DS_init();
Timer0Init();
while(1)
{
DS_get();
yi=shijian[2]/10;er=shijian[2]%10;san=10;
si=shijian[1]/10;wu=shijian[1]%10;liu=10;
qi=shijian[0]/10;ba=shijian[0]%10;
if((shijian[2]==Naozhong[2])&&(shijian[1]==Naozhong[1])&&(shijian[0]==Naozhong[0]))
{
L1=1;EA=1;ET0=1;
}
display1(yi,er); //第一、二段数码管函数
display2(san,si); //第三、四段数码管函数
display3(wu,liu); //第五、六段数码管函数
display4(qi,ba); //第七、八段数码管函数
}
}
void Timer0Init(void) //1毫秒@12.000MHz
{
AUXR |= 0x80; //定时器时钟1T模式
TMOD &= 0xF0; //设置定时器模式
TL0 = 0x20; //设置定时初值
TH0 = 0xD1; //设置定时初值
TF0 = 0; //清除TF0标志
TR0 = 1; //定时器0开始计时
}
void time0() interrupt 1
{
if((++L1_shan_tt==200)&&(L1==1))
{
L1_shan_tt=0;
if(fla==0){fla=1;P2=0X80;P0=0XFE;}
else if(fla==1){fla=0;P2=0X80;P0=0XFF;}
}
if(++L1_guan_tt==5000)
{
EA=1;ET0=1;L1=0;P2=0X80;P0=0XFF;L1_shan_tt=0;L1_guan_tt=0;
}
}
void delayms(int ms)//延时函数
{
uint i,j;
for(i=ms;i>0;i--)
for(j=845;j>0;j--);
}
void allinit()//初始化函数
{
P2=0XA0;P0=0X00; //关闭蜂鸣器继电器
P2=0X80;P0=0XFF; //关闭所有LED灯
P2=0XC0;P0=0XFF; //选中所有数码管段选
P2=0XFF;P0=0XFF; //关闭所有数码管
}
void display1(uchar yi,uchar er)//第一、二段数码管函数
{
P2=0XC0;P0=0X01; //选中第一个数码管段选
P2=0XFF;P0=tab[yi]; //让第一个数码管显示yi指向的值
delayms(1); //延时1ms
P2=0XC0;P0=0X02; //选中第二个数码管段选
P2=0XFF;P0=tab[er]; //让第一个数码管显示er指向的值
delayms(1); //延时1ms
}
void display2(uchar san,uchar si)//第三、四段数码管函数
{
P2=0XC0;P0=0X04; //选中第s三个数码管段选
P2=0XFF;P0=tab[san]; //让第一个数码管显示san指向的值
delayms(1); //延时1ms
P2=0XC0;P0=0X08; //选中第四个数码管段选
P2=0XFF;P0=tab[si]; //让第一个数码管显示si指向的值
delayms(1); //延时1ms
}
void display3(uchar wu,uchar liu)//第五、六段数码管函数
{
P2=0XC0;P0=0X10; //选中第五个数码管段选
P2=0XFF;P0=tab[wu]; //让第一个数码管显示wu指向的值
delayms(1); //延时1ms
P2=0XC0;P0=0X20; //选中第六个数码管段选
P2=0XFF;P0=tab[liu]; //让第一个数码管显示liu指向的值
delayms(1); //延时1ms
}
void display4(uchar qi,uchar ba)//第七、八段数码管函数
{
P2=0XC0;P0=0X40; //选中第七个数码管段选
P2=0XFF;P0=tab[qi]; //让第一个数码管显示qi指向的值
delayms(1); //延时1ms
P2=0XC0;P0=0X80; //选中第八个数码管段选
P2=0XFF;P0=tab[ba]; //让第一个数码管显示ba指向的值
delayms(1); //延时1ms
}
/*******************DS1302驱动代码************************/
void Write_Ds1302_Byte(unsigned char temp)
{
unsigned char i;
for (i=0;i<8;i++)
{
SCK=0;
SDA=temp&0x01;
temp>>=1;
SCK=1;
}
}
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/10<<4)|(dat%10));
RST=0;
}
unsigned char Read_Ds1302(unsigned char address)
{
unsigned char i,temp=0x00,dat1,dat2;
RST=0;
_nop_();
SCK=0;
_nop_();
RST=1;
_nop_();
Write_Ds1302_Byte(address);
for (i=0;i<8;i++)
{
SCK=0;
temp>>=1;
if(SDA)
temp|=0x80;
SCK=1;
}
RST=0;
_nop_();
RST=0;
SCK=0;
_nop_();
SCK=1;
_nop_();
SDA=0;
_nop_();
SDA=1;
_nop_();
dat1=temp/16;
dat2=temp%16;
temp=dat1*10+dat2;
return (temp);
}
void DS_init()
{
unsigned char add,i;
add=0x80;
Write_Ds1302(0x8e,0x00);
for(i=0;i<7;i++)
{
Write_Ds1302(add,shijian[i]);
add=add+2;
}
Write_Ds1302(0x8e,0x80);
}
void DS_get()
{
unsigned char add,i;
add=0x81;
Write_Ds1302(0x8e,0x00);
for(i=0;i<7;i++)
{
shijian[i]=Read_Ds1302(add);
add=add+2;
}
Write_Ds1302(0x8e,0x80);
}