/*-----------------------------------------------
名称:ds1302时钟芯片编程
修改:无
内容:在液晶上以二行的形式显示出时钟
------------------------------------------------*/
#include<reg52.h>
#include<intrins.h>
#define uchar unsigned char
#define uint unsigned int
sbit RS=P2^4;//位声明
sbit RW=P2^5;
sbit E =P2^6;
sbit SCLK=P3^6;//串行时钟
sbit IO =P3^4;//数据输入/输出
sbit RST =P3^5;//
void write_ds1302_byte(uchar dat);
void write_ds1302(uchar add,uchar dat);
uchar read_ds1302(uchar add);
void set_rtc(void);
void read_rtc(void);
void time_pros(void);
void init();
void write_com(uchar com);
void write_data(uchar date);
void delay(uint z);
uchar time_date[7]={11,6,8,6,20,22,30};//设置初值。年周月日时分秒
uchar write_add[7]={0x8c,0x8a,0x88,0x86,0x84,0x82,0x80};//写地址
uchar read_add[7]={0x8d,0x8b,0x89,0x87,0x85,0x83,0x81};//读地址
uchar disp1[11],disp2[8];
uchar code displcd[]="0123456789-: ";
/*------------------------------------------------
延时子函数
-------------------------------------------------*/
void delay(uint z)
{
uint x,y;
for(x=z;x>0;x--)
{
for(y=110;y>0;y--);
}
}
/*------------------------------------------------
单字节的写子函数
------------------------------------------------*/
void write_ds1302_byte(uchar dat)
{
uchar i;
for(i=0;i<8;i++)
{
SCLK=0;//SCLK为低电平时,数据可改;SCLK为高电平时,数据稳定
IO=dat&0x01;//准备数据,数据从最低位开始传
dat=dat>>1;//移位
SCLK=1;
}
}
/*------------------------------------------------
写多字节子函数
------------------------------------------------*/
void write_ds1302(uchar add,uchar dat)
{
RST=0;
_nop_();//停顿1个CPU周期 。需包含#include<intrins.h>
SCLK=0;
_nop_();
RST=1;//此时可写数据
_nop_();
write_ds1302_byte(add);//单字节的写数据地址
write_ds1302_byte(dat);//单字节的写数据
RST=0; //
_nop_();
IO=1;// 释放
SCLK=1;//释放
}
/*------------------------------------------------
读函数
------------------------------------------------*/
uchar read_ds1302(uchar add)
{
uchar i,value;
RST=0;
_nop_();//停顿1个CPU周期
SCLK=0;
_nop_();
RST=1;
_nop_();
write_ds1302_byte(add);//写地址。此时SCLK为高电平
for(i=0;i<8;i++)
{
value=value>>1;
SCLK=0;
if(IO)
{
value=value|0x80;//读和写都是从最低位开始的
}
SCLK=1;
}
RST=0;//芯片停止
_nop_();
SCLK=0;
_nop_();
SCLK=1;
IO=1;
return( value);
}
/*------------------------------------------------
设置实时时钟(rtc)
------------------------------------------------*/
void set_rtc(void)
{
uchar i,j;
for(i=0;i<7;i++)
{
j=time_date[i]/10; //转化为BCD码
time_date[i]=time_date[i]%10; //
time_date[i]=time_date[i]+j*16; //
}
write_ds1302(0x8e,0x00);//去除写保护
for(i=0;i<7;i++) //写数据
{
write_ds1302(write_add[i],time_date[i]);
}
write_ds1302(0x8e,0x80);//加写保护
}
/*------------------------------------------------
读时间子函数
-------------------------------------------------*/
void read_rtc(void)
{
uchar i;
for(i=0;i<7;i++)
{
time_date[i]=read_ds1302(read_add[i]);//读的数放入数组time_date[i]
}
}
/*-----------------------------------------------
处理函数(BCD转换为十进制)
------------------------------------------------*/
void time_pros(void)
{
disp1[0]=time_date[0]/16;//年的十位
disp1[1]=time_date[0]%16;//年的个位
disp1[2]=10;
disp1[3]=time_date[2]/16;//月的十位
disp1[4]=time_date[2]%16;//月的个位
disp1[5]=10;
disp1[6]=time_date[3]/16;//日的十位
disp1[7]=time_date[3]%16;//日的个位
disp1[8]=12;
disp1[9]=12;
disp1[10]=time_date[1]%16;//周的个位
disp2[0]=time_date[4]/16;//时的十位
disp2[1]=time_date[4]%16;//时的个位
disp2[2]=11;
disp2[3]=time_date[5]/16;//分的十位
disp2[4]=time_date[5]%16;//分的个位
disp2[5]=11;
disp2[6]=time_date[6]/16;//秒的十位
disp2[7]=time_date[6]%16;//秒的个位
}
/*------------------------------------------------
写指令子函数
------------------------------------------------*/
void write_com(uchar com)
{
RS=0;//写指令
P0=com;//输入指令
delay(5);//延时5ms
E=1;
delay(5);
E=0;
}
/*------------------------------------------------
写数据子函数
------------------------------------------------*/
void write_data(uchar date)
{
RS=1;//写数据
P0=date;//输入数据
delay(5);//延时5ms
E=1;
delay(5);
E=0;
}
/*------------------------------------------------
初始化子函数
------------------------------------------------*/
void init()
{
RW=0;//一直为写状态
E=0;//使能端置0
write_com(0x38);//显示模式设置,即设置16*2显示,5*7点阵,8位数据接口
write_com(0x06);//当读或写一个字符后地址指针加1,且光标加1
write_com(0x0e);//开显示,显示光标,光标不闪烁
write_com(0x80);//数据指针初始化
}
/*------------------------------------------------
主函数
------------------------------------------------*/
main()
{
uchar num,j;
init();
set_rtc();
while(1)
{
read_rtc();
time_pros();
write_com(0x80);
for(num=0;num<11;num++)//写入第1行字符
{
j=disp1[num];
write_data(displcd[j]);
delay(2);
}
write_com(0x80+0x40);
for(num=0;num<8;num++)//写入第2行字符
{
j=disp2[num];
write_data(displcd[j]);
delay(2);
}
}
} |