DS1302是一种串行接口的实时时钟,芯片内部具有可编程的日历时钟和31个字节的静态RAM。
仿真:
程序:
main.c
#include<reg51.h>
#include<ds1302.c>
unsigned int cp0,cp1;
unsigned char flash;
bit flag;
unsigned char smg[] = {0xc0,0xf9,0xa4,0xb0,0x99,0x92,0x82,0xf8,0x80,0x90};
#include<display.c>
void timer0_isr(void) interrupt 1
{
TH0 = (65536 - 1000) / 256;
TL0 = (65536 - 1000) % 256;
cp0++;cp1++;
if(cp0 >= 500)
{get_ds1302();cp0 = 0;flash = ~flash;}
if(cp1>=2000)
{
cp1 = 0;
flag = ~flag;
}
if(flag == 0)display0();
if(flag == 1)display1();
}
void timer0_init(void)
{
TMOD = 0x01;
TH0 = (65536 - 1000) / 256;
TL0 = (65536 - 1000) % 256;
EA = 1;
ET0 = 1;
TR0 = 1;
}
void main(void)
{
timer0_init();
write_init_time();
while(1)
{
}
}
DS1302.C
sbit CE = P3^5;
sbit SCLK = P3^6;
sbit IO = P3^7;
unsigned char sec = 30,min = 55,hour = 20,day = 21,month = 1, year = 21,week;
void ds1302_init()//初始化
{
CE = 0;
SCLK = 0;
CE = 1; //允许读写数据
}
/*对ds1302写一字节数据*/
void write_ds1302_onebyte(unsigned char dat)
{
unsigned char i;
for(i = 0;i < 8;i++)
{
SCLK = 0;
IO = (bit)(dat & 0x01); // 0001 & 0001 //把写入的数据取出来给DS1302
SCLK = 1;
dat = dat >> 1; //每取一次 移一位
}
}
/*从DS1302里面读出一字节数据*/
unsigned char read_ds1302_onebyte()
{
unsigned char i,j;
for(i = 0;i<8;i++)
{
SCLK = 1;
SCLK = 0;
j = j >> 1; //移位
if(IO)j = j | 0X80; //一位一位的读取数据
}
return(j);//8421BCD码
}
/*对DS1302某一地址写数据*/
void write_ds1302_add_dat(unsigned char add,unsigned char dat)
{
ds1302_init();
write_ds1302_onebyte(add);
write_ds1302_onebyte(dat);
CE = 0; //关闭CE不再读写数据 IO SCLK 变为高阻态(断路)
}
/*从DS1302里面读出数据*/
unsigned char read_ds1302_add(unsigned char add)
{
unsigned char dat_temp;
ds1302_init();
write_ds1302_onebyte(add);
dat_temp = read_ds1302_onebyte();
CE = 0;
return(dat_temp);
}
/*8421BCD码转十进制*/
unsigned char BCD_DEC(unsigned char x)
{
unsigned char dec;
dec = x & 0x0f; //取出低四位
x = x >> 4; //挤出低四位,把高四位放到地位
dec = x*10 + dec;
return(dec);
}
/*十进制转8421BCD码*/
unsigned char DEC_BCD(unsigned char x)
{
unsigned char bcd;
bcd = x % 10;//取出十进制的个位
x = x / 10;//取出十进制的十位
x = x << 4;
bcd = bcd | x;
return(bcd);
}
/*单片机向DS1302里面写数据*/
void write_init_time()
{
write_ds1302_add_dat(0x8e,0x00);//关闭保护
write_ds1302_add_dat(0x80,DEC_BCD(sec));//写秒
write_ds1302_add_dat(0x82,DEC_BCD(min));//写分
write_ds1302_add_dat(0x84,DEC_BCD(hour));//写时
write_ds1302_add_dat(0x86,DEC_BCD(day));//写日
write_ds1302_add_dat(0x88,DEC_BCD(month));//写月
write_ds1302_add_dat(0x8A,DEC_BCD(week));//写周
write_ds1302_add_dat(0x8C,DEC_BCD(year));//写年
write_ds1302_add_dat(0x8e,0x10);//打开保护
}
/*单片机从DS1302里面得到时间数据*/
void get_ds1302()
{
unsigned char R;
R = read_ds1302_add(0x81);//读秒
sec = BCD_DEC(R);
R = read_ds1302_add(0x83);//读分
min = BCD_DEC(R);
R = read_ds1302_add(0x85);//读时
hour = BCD_DEC(R);
R = read_ds1302_add(0x87);//读日
day = BCD_DEC(R);
R = read_ds1302_add(0x89);//读月
month = BCD_DEC(R);
R = read_ds1302_add(0x8B);//读周
week = BCD_DEC(R);
R = read_ds1302_add(0x8D);//读年
year = BCD_DEC(R);
}
DISPLAY.C
char k;
void display0(void)
{
P0 = 0xff;
switch(k)
{
case 0:P1 = 0x01;P0 = smg[sec % 10];break;
case 1:P1 = 0x02;P0 = smg[sec / 10];break;
case 2:P1 = 0x04;P0 = 0xbf | flash;break;
case 3:P1 = 0x08;P0 = smg[min % 10];break;
case 4:P1 = 0x10;P0 = smg[min / 10];break;
case 5:P1 = 0x20;P0 = 0xbf | flash;break;
case 6:P1 = 0x40;P0 = smg[hour % 10];break;
case 7:P1 = 0x80;P0 = smg[hour / 10];break;
}
k++;
if(k>=8)k = 0;
}
void display1(void)
{
P0 = 0xff;
switch(k)
{
case 0:P1 = 0x01;P0 = smg[day % 10];break;
case 1:P1 = 0x02;P0 = smg[day / 10];break;
case 2:P1 = 0x04;P0 = 0xbf;break;
case 3:P1 = 0x08;P0 = smg[month % 10];break;
case 4:P1 = 0x10;P0 = smg[month / 10];break;
case 5:P1 = 0x20;P0 = 0xbf;break;
case 6:P1 = 0x40;P0 = smg[year % 10];break;
case 7:P1 = 0x80;P0 = smg[year / 10];break;
}
k++;
if(k>=8)k = 0;
}
运行结果:
20:55:47为时间
21—01—21为 日期