1200字范文,内容丰富有趣,写作的好帮手!
1200字范文 > 基于51单片机的DS1302实时时钟

基于51单片机的DS1302实时时钟

时间:2023-05-29 17:13:46

相关推荐

基于51单片机的DS1302实时时钟

本讲内容:

介绍DS1302实时时钟芯片基本知识,演示DS1302例程。

DS1302实时时钟:

DS1302能提供包括秒、分、时、日期、月份和年份信息。闰年可自行调整,可选择12小时制和24小时制,可以设置AM、PM。

只通过三根线进行数据的控制和传递:/RST、I/O、SCLK。

通过备用电源可以让芯片在小于1mw的功率下运作。

DS1302是总线驱动方式,它不仅要向寄存器写入控制字,还需要读取相应寄存器的数据。要想与DS1302通信,首先要先了解DS1302的控制字。DS1302的控制字如图。

位7:必须是逻辑1,如果它为0,则不能把数据写入到DS1302中。

位6:如果为0,则表示存取日历时钟数据,为1表示存取RAM数据。

位5至位1(A4~A0):指示操作单元的地址。

位0:为1表示进行读操作,为0表示要进行写操作,控制字后SCLK下降沿读数据,SCLK上升沿写数据。数据是低位在前,高位在后。

读数据:

读数据时在紧跟8位的控制字指令后的下一个SCLK脉冲的下降沿,读出DS1302的数据,读出的数据是从最低位到最高位。

写数据:

写数据时在紧跟8位的控制字指令后的下一个SCLK脉冲的上升沿,数据被写入DS1302,数据输入也是从最低位(0位)开始。

DS1302的数据读写是通过I/O串行进行的。当进行一次读写操作时最少要读写两个字节。

第一个字节是控制字节,就是一个命令,告诉DS1302是读还是写操作,是对RAM还是对CLOCK寄存器操作,以及操作的地址。

第二个字节就是要读或写的数据了。

单字节写:

在进行操作之前先将CE(也可说是RST)置高电平,然后单片机将控制字的位0放到I/O上,当I/O的数据稳定后,将SCLK置高电平,DS1302检测到SCLK的上升沿后就将I/O上的数据读取,然后单片机将SCLK置为低电平,再将控制字的位1放到I/O上,如此反复,将一个字节控制字的8个位传给DS1302。接下来就是传一个字节的数据给DS1302,当传完数据后,单片机将CE置为低电平,操作结束。

单字节读:

一开始写控制字的过程和上面的单字节写操作是一样,但是单字节读操作在写控制字的最后一个位,SCLK还在高电平时,DS1302就将数据放到I/O上,单片机将SCLK置为低电平后数据锁存,单片机就可以读取I/O上的数据。如此反复,将一个字节的数据读入单片机。

DS1302实时时钟芯片接口电路:

例程:

/**************DS1302_LCD1602显示****************

*单片机型号:STC89C52RC

*开发环境:KEIL

*名称:DS1302_LCD1602显示

********************************************************/

#include<reg52.h>

#define uint unsigned int

#define uchar unsigned char

uchar a,miao,shi,fen,ri,yue,nian,week,flag,temp,KEYn;

#define yh 0x80 //第一行的初始位置

#define er 0x80+0x40//第二行初始位置

sbit wr=P1^1;sbit rs=P1^0;sbit en=P2^5;

sbit SCLK=P2^1;sbit IO=P2^0;

sbit RST=P2^4;sbit ACC0=ACC^0;

sbit ACC7=ACC^7;

sbit key=P3^7;

sbit SWITCH_S6=P3^0;

sbit SWITCH_S11=P3^1;

sbit SWITCH_S16=P3^2;

uchar code tab1[]={"- - THU"};

uchar code tab2[]={" : : "};

void delay(int In,int Out)

{

int i,j;

for(i=0;i<In;i++)

{for(j=0;j<Out;j++){;}}

}

/******************液晶相关函数********************/

void write_1602com(uchar com) //液晶写入指令函数

{

rs=0; //置为写入命令

P0=com;//送入数据

delay(5,10);

en=1; //拉高使能端

delay(5,10);

en=0; //完成高脉冲

}

void write_1602dat(uchar dat)

{

rs=1; //置为写入数据

P0=dat;//送入数据

delay(5,10);

en=1;

delay(5,10);

en=0;

}

void lcd_init(void)

{

wr=0;

write_1602com(0x38); //设置液晶工作模式

write_1602com(0x0c); //开显示不显示光标

write_1602com(0x06); //整屏不移动,指针加一

write_1602com(0x01);

write_1602com(yh+2); //字符写入的位置

for(a=0;a<14;a++)

{write_1602dat(tab1[a]);}

write_1602com(er+4);

for(a=0;a<8;a++)

{write_1602dat(tab2[a]);}

}

/******************DS1302相关函数********************/

void write_byte(uchar dat)

{

ACC=dat;

RST=1;

for(a=8;a>0;a--)

{

IO=ACC0;

SCLK=0;

SCLK=1;

ACC=ACC>>1;

}

}

uchar read_byte()

{

RST=1;

for(a=8;a>0;a--)

{

ACC7=IO;

SCLK=1;

SCLK=0;

ACC=ACC>>1;

}

return (ACC);

}

void write_1302(uchar add,uchar dat)

{

RST=0;

SCLK=0;

RST=1;

write_byte(add);

write_byte(dat);

SCLK=1;

RST=0;

}

uchar read_1302(uchar add)

{

uchar temp;

RST=0;

SCLK=0;

RST=1;

write_byte(add);

temp=read_byte();

SCLK=1;

RST=0;

return(temp);

}

uchar BCD_Decimal(uchar bcd)

{

uchar Decimal;

Decimal=bcd>>4;

return(Decimal=Decimal*10+(bcd&=0x0F));

}

void ds1302_init()

{

RST=0;

SCLK=0;

write_1302(0x80,miao|0x00);

}

void write_sfm(uchar add,uchar dat)

{

uchar gw,sw;

gw=dat%10;

sw=dat/10;

write_1602com(er+add);

write_1602dat(0x30+sw);

write_1602dat(0x30+gw);

}

void write_nyr(uchar add,uchar dat)

{

uchar gw,sw;

gw=dat%10;

sw=dat/10;

write_1602com(yh+add);

write_1602dat(0x30+sw);

write_1602dat(0x30+gw);

}

void write_week(uchar week) //写星期函数

{

write_1602com(yh+0x0d);

switch(week)

{

case 1:

{

write_1602dat('M');

write_1602dat('O');

write_1602dat('N');

}break;

case 2:

{

write_1602dat('T');

write_1602dat('U');

write_1602dat('E');

}break;

case 3:

{

write_1602dat('W');

write_1602dat('E');

write_1602dat('D');

}break;

case 4:

{

write_1602dat('T');

write_1602dat('H');

write_1602dat('U');

}break;

case 5:

{

write_1602dat('F');

write_1602dat('R');

write_1602dat('I');

}break;

case 6:

{

write_1602dat('S');

write_1602dat('T');

write_1602dat('A');

}break;

case 7:

{

write_1602dat('S');

write_1602dat('U');

write_1602dat('N');

}break;

}

}

/******************按键扫描相关函数*****************/

void keyscan()

{

key=0;

if(SWITCH_S6==0) //SWITCH_S6为功能键

{

delay(5,100);

if(SWITCH_S6==0)

{

while(!SWITCH_S6);

KEYn++;

if(KEYn==9)

KEYn=1;

switch(KEYn)

{

case 1:

{

TR0=0; //关闭定时器

write_1602com(er+0x0b); //写入光标位置

write_1602com(0x0f); //设置光标为闪烁

temp=(miao)/10*16+(miao)%10;

write_1302(0x8e,0x00);

write_1302(0x80,0x80|temp); //miao

write_1302(0x8e,0x80);

}break;

case 2:{write_1602com(er+8);}break; //fen

case 3:{write_1602com(er+5);}break; //shi

case 4:{write_1602com(yh+0x0f);}break; //week

case 5:{write_1602com(yh+0x0b);}break; //ri

case 6:{write_1602com(yh+0x08);}break; //yue

case 7:{write_1602com(yh+0x05);}break; //nian

case 8:

{

write_1602com(0x0c); //设置光标不闪烁

TR0=1; //打开定时器

temp=(miao)/10*16+(miao)%10;

write_1302(0x8e,0x00);

write_1302(0x80,0x00|temp); //miao

write_1302(0x8e,0x80);

}break;

}

}

}

if(KEYn!=0)

//当SWITCH_S6按下以下。再按以下键才有效

{

if(SWITCH_S11==0) //上调键

{

delay(5,10);

if(SWITCH_S11==0)

{

while(!SWITCH_S11);

switch(KEYn)

{

case 1:

{

miao++;

if(miao==60){miao=0;}

write_sfm(0x0a,miao); //写入新的秒数

temp=(miao)/10*16+(miao)%10;

write_1302(0x8e,0x00);

write_1302(0x80,0x80|temp);

write_1302(0x8e,0x80);

write_1602com(er+0x0b);

//因为设置液晶的模式是写入数据后,指针自动加一,在这里是写回原来的位置

}break;

case 2:

{

fen++;

if(fen==60){fen=0;}

write_sfm(0x07,fen);

temp=(fen)/10*16+(fen)%10;

write_1302(0x8e,0x00);

write_1302(0x82,temp);

write_1302(0x8e,0x80);

write_1602com(er+8);

}break;

case 3:

{

shi++;

if(shi==24){shi=0;}

write_sfm(4,shi);

temp=(shi)/10*16+(shi)%10;

write_1302(0x8e,0x00);

write_1302(0x84,temp);

write_1302(0x8e,0x80);

write_1602com(er+5);

}break;

case 4:

{

week++;

if(week==8){week=0;}

write_week(week);

write_1602com(yh+0x0f);

}break;

case 5:

{

ri++;

if(ri==31){ri=0;}

write_nyr(10,ri);

temp=(ri)/10*16+(ri)%10;

write_1302(0x8e,0x00);

write_1302(0x86,temp);

write_1302(0x8e,0x80);

write_1602com(yh+11);

}break;

case 6:

{

yue++;

if(yue==13){yue=0;}

write_nyr(7,yue);

temp=(yue)/10*16+(yue)%10;

write_1302(0x8e,0x00);

write_1302(0x88,temp);

write_1302(0x8e,0x80);

write_1602com(yh+8);

}break;

case 7:

{

nian++;

if(nian==100){nian=0;}

write_nyr(4,nian);

write_1602com(yh+5);

}break;

}

}

}

if(SWITCH_S16==0)

{

delay(5,100);

if(SWITCH_S16==0)

{

while(!SWITCH_S16);

switch(KEYn)

{

case 1:

{

miao--;

if(miao==-1){miao=59;}

write_sfm(0x0a,miao); //写入新的秒数

write_1602com(er+0x0b);

//因为设置液晶的模式是写入数据后,指针自动加一,在这里是写回原来的位置

}break;

case 2:

{

fen--;

if(fen==-1){fen=59;}

write_sfm(7,fen);

temp=(fen)/10*16+(fen)%10;

write_1302(0x8e,0x00);

write_1302(0x82,temp);

write_1302(0x8e,0x80);

write_1602com(er+8);

}break;

case 3:

{

shi--;

if(shi==-1){shi=23;}

write_sfm(4,shi);

temp=(shi)/10*16+(shi)%10;

write_1302(0x8e,0x00);

write_1302(0x84,temp);

write_1302(0x8e,0x80);

write_1602com(er+5);

}break;

case 4:

{

week--;

if(week==-1){week=7;}

write_week(week);

write_1602com(yh+0x0f);

}break;

case 5:

{

ri--;

if(ri==-1){ri=30;}

write_nyr(10,ri);

temp=(ri)/10*16+(ri)%10;

write_1302(0x8e,0x00);

write_1302(0x86,temp);

write_1302(0x8e,0x80);

write_1602com(yh+11);

}break;

case 6:

{

yue--;

if(yue==-1){yue=12;}

write_nyr(7,yue);

temp=(yue)/10*16+(yue)%10;

write_1302(0x8e,0x00);

write_1302(0x88,temp);

write_1302(0x8e,0x80);

write_1602com(yh+8);

}break;

case 7:

{

nian--;

if(nian==-1){nian=99;}

write_nyr(4,nian);

write_1602com(yh+5);

}break;

}

}

}

}

}

void timer_init(){TMOD=0x11;TH0=0;TL0=0;EA=1;ET0=1;TR0=1;}

void sys_init(void)

{

lcd_init();

ds1302_init();

timer_init();

}

void main()

{

sys_init();

while(1){keyscan();}

}

void timer0() interrupt 1

{

miao = BCD_Decimal(read_1302(0x81));

fen = BCD_Decimal(read_1302(0x83));

shi = BCD_Decimal(read_1302(0x85));

ri = BCD_Decimal(read_1302(0x87));

yue = BCD_Decimal(read_1302(0x89));

nian = BCD_Decimal(read_1302(0x8d));

week = BCD_Decimal(read_1302(0x8b));

write_sfm(10,miao);

write_sfm(7,fen);

write_sfm(4,shi);

write_nyr(10,ri);

write_nyr(7,yue);

}

最后,求求看到的此文的小伙伴点赞关注支持一下下哦。毕竟,码字不容易哦,您的支持是我最大的动力呀!!!呜呜呜~~~

本内容不代表本网观点和政治立场,如有侵犯你的权益请联系我们处理。
网友评论
网友评论仅供其表达个人看法,并不表明网站立场。