52单片机是STC公司生产的一种低功耗、高性能CMOS8位微控制器,具有8K字节系统可编程Flash存储器。STC89C52使用经典的MCS-51内核,但是做了很多的改进使得芯片具有传统51单片机不具备的功能。在单芯片上,拥有灵巧的8 位CPU 和在系统可编程Flash,使得STC89C52为众多嵌入式控制应用系统提供高灵活、超有效的解决方案。
52单片机结合可以对年、月、日、周、时、分、秒进行计时,且具有闰年补偿等功能的dDS1302时钟芯片做出的电子闹钟会有什么火花呢?奉上基于52单片机与ds1302时钟芯片的电子闹钟C程序,让大家亲身体验。
52单片机与ds1302时钟芯片的电子闹钟C程序
#include《reg52.h》
#define w_second 0x80 //秒写入地址
#define w_minute 0x82 //分写入地址
#define w_hour 0x84 //时写入地址
#define w_day 0x86 //日写入地址
#define w_month 0x88 //月写入地址
#define w_week 0x8a //星期写入地址
#define w_year 0x8c //年写入地址
#define r_second 0x81 //秒读出地址
#define r_minute 0x83 //分读出地址
#define r_hour 0x85 //时读出地址
#define r_day 0x87 //日读出地址
#define r_month 0x89 //月读出地址
#define r_week 0x8b //星期读出地址
#define r_year 0x8d //年读出地址
#define w_wp 0x8e //指令写允许端地址
#define uchar unsigned char
uchar table[]=
{0xc0,0xf9,0xa4,0xb0,0x99,0x92,0x82,0xf8,0x80,0x90,0xff};//7段数码管编码
uchar second; // 秒指针
uchar minute; // 分指针
uchar hour; // 时指针
uchar day; // 日指针
uchar month; // 月指针
uchar week; // 星期指针
uchar year; // 年指针
uchar cc;
uchar h_clock,m_clock,h,m;
sbit change=P1^0; // 选择按钮
sbit ok=P1^2; // 确定更改按钮
sbit crrect=P1^1; // 更改按钮
sbit look=P1^3; // 时间和年月日查看切换按钮
sbit clock=P1^4; //闹钟设定
sbit ce=P3^2; // ds1302 片选端
sbit sclk=P3^0; // ds1302 时控端
sbit io=P3^1; // ds1302 串口端
sbit clock_beef=P3^7; //蜂鸣器控制端
sbit clock_button=P1^5; //闹钟启停按钮
void write_ds1302(uchar addr,uchar dat) //写程序
{ uchar i,temp;
ce=0;sclk=0;ce=1;
for(i=0;i《8;i++)
{ sclk=0;
temp=addr;
io=(bit)(temp&0x01); //每一次只传送一位数据
addr》》=1;
sclk=1;
}
for(i=0;i《8;i++)
{ sclk=0;
temp=dat;
io=(bit)(temp&0x01);
dat》》=1;
sclk=1;
}
ce=0;
}
uchar read_ds1302(uchar addr) //读程序
{ uchar i,temp;
ce=0;sclk=0;ce=1;
for(i=0;i《8;i++)
{ sclk=0;
temp=addr;
io=(bit)(temp&0x01);
addr》》=1;
sclk=1;
}
for(i=0;i《8;i++)
{ temp》》=1;
sclk=0;
if(io) temp=temp|0x80;
else temp=temp&0x7f;
sclk=1;
}
return temp;
}
void set_ds1302() //初始化ds1302
{ write_ds1302(w_wp,0x00);
write_ds1302(w_second,second);
write_ds1302(w_minute,minute);
write_ds1302(w_hour,hour);
write_ds1302(w_day,day);
write_ds1302(w_month,month);
write_ds1302(w_week,week);
write_ds1302(w_year,year);
write_ds1302(w_wp,0x80);
}
void view1() //时间显示
{ uchar i;
P0=table[second]; //秒显示
P2=0x01;
for(i=0;i《=123;i++);
P2=0;
P0=table[second/16];
P2=0x02;
for(i=0;i《=123;i++);
P2=0;
P0=table[minute]-0x80; //分显示,(-0x80表示dp点亮)
P2=0x04;
for(i=0;i《=123;i++);
P2=0;
P0=table[minute/16];
P2=0x08;
for(i=0;i《=123;i++);
P2=0;
P0=table[hour]-0x80;//时显示
P2=0x10;
for(i=0;i《=123;i++);
P2=0;
P0=table[hour/16];
P2=0x20;
for(i=0;i《=123;i++);
P2=0;
}
void view2() //日期显示
{ uchar i;
P2=0;
P0=table[week]; //星期显示
P2=0x01;
for(i=0;i《=123;i++);
P2=0;
P0=table[week/16];
P2=0x02;
for(i=0;i《=123;i++);
P2=0;
P0=table[day]-0x80; //日显示
P2=0x04;
for(i=0;i《=123;i++);
P2=0;
P0=table[day/16];
P2=0x08;
for(i=0;i《=123;i++);
P2=0;
P0=table[month]-0x80;//月显示
P2=0x10;
for(i=0;i《=123;i++);
P2=0;
P0=table[month/16];
P2=0x20;
for(i=0;i《=123;i++);
P2=0;
P0=table[year]-0x80; //年显示
P2=0x40;
for(i=0;i《=123;i++);
P2=0;
P0=table[year/16];
P2=0x80;
for(i=0;i《=123;i++);
P2=0;
}
void view3() //闹钟设定程序
{ uchar i;
P0=table[m];
P2=0x01;
for(i=0;i《=123;i++);
P2=0;
P0=table[m/16];
P2=0x02;
for(i=0;i《=123;i++);
P2=0;
P0=table[h]-0x80;
P2=0x04;
for(i=0;i《=123;i++);
P2=0;
P0=table[h/16];
P2=0x08;
for(i=0;i《=123;i++);
P2=0;
}
void beep() //蜂鸣器启动程序
{ int i;
clock_beef=~clock_beef;
for(i=1;i《=50;i++)
{ second=read_ds1302(r_second);
minute=read_ds1302(r_minute);
hour=read_ds1302(r_hour);
view1();
}
}
void display1() //读秒,分,时程序
{ second=read_ds1302(r_second);
minute=read_ds1302(r_minute);
hour=read_ds1302(r_hour);
view1();
if((h_clock==read_ds1302(r_hour)) &&
(m_clock==read_ds1302(r_minute)) && (~clock_button)) //判断时分,且闹钟是否开启
{ while(~clock_button)
{ beep();
}
clock_beef=0;
}
}
void display2() //读星期,日,月,年程序
{ week=read_ds1302(r_week);
day=read_ds1302(r_day);
month=read_ds1302(r_month);
year=read_ds1302(r_year);
view2();
if((h_clock==read_ds1302(r_hour)) &&
(m_clock==read_ds1302(r_minute)) && (~clock_button))
{ while(~clock_button)
{ beep();
}
clock_beef=0;
}
}
void crrect_ds1302(uchar cc) //更改程序
{
while(~crrect);
switch(cc)
{
case 1: if(read_ds1302(r_minute)==0x59)
minute=0x00;
else { if(read_ds1302
(r_minute)==9) { minute=read_ds1302
(r_minute)/16;minute=(minute+1)*16;}
else
minute=read_ds1302(r_minute)+1;
}
set_ds1302();
break;
case 2: if(read_ds1302(r_hour)==0x23)
hour=0x00;
else { if(read_ds1302(r_hour)
《0x20)
{ if
(read_ds1302(r_hour)==9) {hour=read_ds1302
(r_hour)/16;hour=(hour+1)*16;}
else hour=read_ds1302(r_hour)+1;
}
else
hour=read_ds1302(r_hour)+1;
}
set_ds1302();
break;
case 3: if(read_ds1302(r_week)==0x07)
week=0x01;
else week=read_ds1302(r_week)+1;
set_ds1302();
break;
case 4: if(read_ds1302(r_day)==0x31)
day=0x01;
else { if(read_ds1302
(r_day)==9) { day=read_ds1302(r_day)/16;day=(day+1)
*16;}
else
day=read_ds1302(r_day)+1;
}
set_ds1302();
break;
case 5: if(read_ds1302(r_month)==0x12)
month=0x01;
else { if(read_ds1302
(r_month)==9) { month=read_ds1302
(r_month)/16;month=(month+1)*16;}
else
month=read_ds1302(r_month)+1;
}
set_ds1302();
break;
case 6: if(read_ds1302(r_year)==0x99)
year=0x00;
else { if(read_ds1302
(r_year)==9) { year=read_ds1302(r_year)/16;year=(year
+1)*16;}
else
year=read_ds1302(r_year)+1;
}
set_ds1302();
break;
default:{;}
}
}
void change_ds1302() //更改设定选择
{ uchar i;
cc=0;
while(ok)
{ if(cc==6) cc=0;
cc++;
while(change&&ok)
{ if(i==320) i=0;
else i++;
switch(cc)
{
case 1: if(i《160) minute=read_ds1302
(r_minute);
else {minute=0xaa; year=read_ds1302
(r_year);}
view1();
break;
case 2: if(i《160) hour=read_ds1302(r_hour);
else {hour=0xaa; minute=read_ds1302
(r_minute);}
view1();
break;
case 3: if(i《160)
week=read_ds1302(r_week);
else {week=0xaa;hour=read_ds1302
(r_hour);}
view2();
break;
case 4: if(i《160) day=read_ds1302
(r_day);
else {day=0xaa; week=read_ds1302
(r_week);}
view2();
break;
case 5: if(i《160)
month=read_ds1302(r_month);
else {month=0xaa; day=read_ds1302
(r_day);}
view2();
break;
case 6: if(i《160)
year=read_ds1302(r_year);
else {year=0xaa; month=read_ds1302
(r_month);}
view2();
break;
default: {;}
}
if(~crrect) crrect_ds1302(cc);
}
while( ~change );
}
}
void crrect_clock(uchar i) //设定定时程序
{ switch(i)
{ case 0: if(m_clock==0x59) m_clock=0x00;
else { if(m_clock==9) {
m_clock=m_clock/16;m_clock=(m_clock+1)*16;}
else
m_clock=m_clock+1;
}
break;
case 1: if(h_clock==0x23)
h_clock=0x00;
else { if(h_clock《0x20)
{ if
(h_clock==9) {h_clock=h_clock/16;h_clock=(h_clock+1)
*16;}
else h_clock=h_clock+1;
}
else
h_clock=h_clock+1;
}
break;
default:{;}
}
}
void set_clock() //分、时设定选择程序
{ uchar i,j;
while(ok)
{ while(clock && ok)
{ if(j==320) j=0;
else j++;
switch(i)
{
case 0: if(j《160) m=m_clock;
else {m=0xaa; h=h_clock;}
view3();
break;
case 1: if(j《160) h=h_clock;
else {h=0xaa; m=m_clock;}
view3();
break;
default:{;}
}
if(~crrect) {while
(~crrect);crrect_clock(i);}
}
while(~clock);
if(i==0) i++;
else i=0;
}
}
void main()
{ uchar i;
cc=0;m_clock=0x00;h_clock=0x00;clock_beef=0;
second=0x15;
minute=0x58;
hour=0x18;
day=0x18;
month=0x07;
week=0x01;
year=0x11;
set_ds1302(); //初始化ds1302
while(1)
{ if(~look) { i=~i;while(~look);}
if(i==0) display1();
if(i) display2();
if(~change) { while(~change);change_ds1302();}
if(~clock) { while(~clock);set_clock();}
}
}