本设计是由STC89C52单片机为控制核心,具有在线编程功能,低功耗;时钟电路由DS1302提供,它是一种高性能、低功耗的时钟电路,工作电压为3V~5V;所以采用DS1302作为本设计的日历芯片;显示部份使用LCD1602B液晶模块进行数字显示,1602B液晶模块可以显示2行16个字符,有8位数据总线D0—D7,和RS、R/W、EN三个控制端口,工作电压为5V,并且带有字符对比度调节和背光。该模块也可以只用D4-D7作为四位数据分两次传送,这样就可以节省MCU的I/O口资源,系统主要由晶振电路、复位电路、时钟电路部分、中央处理单元、晶显示部分组成。
电路原理图如下:
制作出来的实物图如下:
Altium Designer画的原理图和PCB图如下:(51hei附件中可下载工程文件)
单片机源程序如下:
#include
#include
#define uchar unsigned char
#define uint unsigned int
#define LCDIO P0
sbit rs=P2^0;
sbit rd=P2^1;
sbit lcden=P2^2;
sbit acc0=ACC^0; //移位时的第0位
sbit acc7=ACC^7; //移位时用的第7位
sbit ct=P2^3;
sbit speaker=P3^5;
sbit DQ=P2^5;//ds18b20与单片机连接口
int djs11=0,js,dsmin=0,dshour=0;
uchar second,minute,hour,day,month,year,week,count=0;
uchar ReadValue,num,time;
uint tvalue;//温度值
uchar tflag;
uchar code table[]={" 2000-00-00 FRI"};
uchar code table1[]={" 00:00:00 "};
uchar code table2[]= "THUFRISATSUNMONTUEWES";
char szdata[8];
char szdata1[8];
uchar data disdata[5];
sbit DATA=P3^3; //时钟数据接口
sbit RST=P3^4;
sbit SCLK=P3^2;
sbit menu=P2^7; //菜单
sbit add=P2^6; //加一
sbit dec=P2^4;
sbit set=P2^3 ; //减一
sbit djs=P3^6;
void miaobiao();
void yx();
void delayms(int x)
{
char i;
while(x--)
{
for(i=150;i>0;i--);
}
}
void delay(uint z)
{
uint x,y;
for(x=z;x>0;x--)
for(y=110;y>0;y--);
}
void delay1(uint z)
{
for(;z>0;z--);
}
void write_com(uchar com)
{
rs=0;
rd=0;
lcden=0;
LCDIO=com;
delay(5);
lcden=1;
delay(5);
lcden=0;
}
void write_date(uchar date)
{
rs=1;
rd=0;
lcden=0;
LCDIO=date;
delay(5);
lcden=1;
delay(5);
lcden=0;
}
void init()
{
uchar num;
lcden=0;
write_com(0x38);
write_com(0x0c);
write_com(0x06);
write_com(0x01);
write_com(0x80);
delay(5);
write_com(0x80);
for(num=0;num<15;num++)
{
write_date(table[num]);
delay(5);
}
write_com(0x80+0x40);
for(num=0;num<15;num++)
{
write_date(table1[num]);
delay(5);
}
}
void Write1302(uchar dat)
{
uchar i;
SCLK=0; //拉低SCLK,为脉冲上升沿写入数据做好准备
delay1(2); //稍微等待,使硬件做好准备
for(i=0;i<8;i++) //连续写8个二进制位数据
{
DATA=dat&0x01; //取出dat的第0位数据写入1302
delay(2); //稍微等待,使硬件做好准备
SCLK=1; //上升沿写入数据
delay1(2); //稍微等待,使硬件做好准备
SCLK=0; //重新拉低SCLK,形成脉冲
dat>>=1; //将dat的各数据位右移1位,准备写入下一个数据位
}
}
void WriteSet1302(uchar Cmd,uchar dat)
{
RST=0; //禁止数据传递
SCLK=0; //确保写数居前SCLK被拉低
RST=1; //启动数据传输
delay1(2); //稍微等待,使硬件做好准备
Write1302(Cmd); //写入命令字
Write1302(dat); //写数据
SCLK=1; //将时钟电平置于已知状态
RST=0; //禁止数据传递
}
uchar Read1302(void)
{
uchar i,dat;
delay(2); //稍微等待,使硬件做好准备
for(i=0;i<8;i++) //连续读8个二进制位数据
{
dat>>=1; //将dat的各数据位右移1位,因为先读出的是字节的最低位
if(DATA==1) //如果读出的数据是1
dat|=0x80; //将1取出,写在dat的最高位
SCLK=1; //将SCLK置于高电平,为下降沿读出
delay1(2); //稍微等待
SCLK=0; //拉低SCLK,形成脉冲下降沿
delay1(2); //稍微等待
}
return dat; //将读出的数据返回
}
uchar ReadSet1302(uchar Cmd)
{
uchar dat;
RST=0; //拉低RST
SCLK=0; //确保写数居前SCLK被拉低
RST=1; //启动数据传输
Write1302(Cmd); //写入命令字
dat=Read1302(); //读出数据
SCLK=1; //将时钟电平置于已知状态
RST=0; //禁止数据传递
return dat; //将读出的数据返回
}
void Init_DS1302(void)
{
WriteSet1302(0x8E,0x00); //根据写状态寄存器命令字,写入不保护指令
WriteSet1302(0x80,((0/10)<<4|(0%10))); //根据写秒寄存器命令字,写入秒的初始值
WriteSet1302(0x82,((12/10)<<4|(12%10))); //根据写分寄存器命令字,写入分的初始值
WriteSet1302(0x84,((11/10)<<4|(11%10))); //根据写小时寄存器命令字,写入小时的初始值
WriteSet1302(0x86,((25/10)<<4|(25%10))); //根据写日寄存器命令字,写入日的初始值
WriteSet1302(0x88,((1/10)<<4|(1%10))); //根据写月寄存器命令字,写入月的初始值
WriteSet1302(0x8c,((13/10)<<4|(13%10))); //nian
WriteSet1302(0x8a,((1/10)<<4|(1%10)));
}
void DisplaySecond(uchar x)
{
uchar i,j;
i=x/10;
j=x%10;
write_com(0xc7);
write_date(0x30+i);
write_date(0x30+j);
}
void DisplayMinute(uchar x)
{
uchar i,j;
i=x/10;
j=x%10;
write_com(0xc4);
write_date(0x30+i);
write_date(0x30+j);
}
void DisplayHour(uchar x)
{
uchar i,j;
i=x/10;
j=x%10;
write_com(0xc1);
write_date(0x30+i);
write_date(0x30+j);
}
void DisplayDay(uchar x)
{
uchar i,j;
i=x/10;
j=x%10;
write_com(0x89);
write_date(0x30+i);
write_date(0x30+j);
}
void DisplayMonth(uchar x)
{
uchar i,j;
i=x/10;
j=x%10;
write_com(0x86);
write_date(0x30+i);
write_date(0x30+j);
}
void DisplayYear(uchar x)
{
uchar i,j;
i=x/10;
j=x%10;
write_com(0x83);
write_date(0x30+i);
write_date(0x30+j);
}
void DisplayWeek(uchar x)
{ uchar i;
x=x*3;
write_com(0x8c);
for(i=0;i<3;i++)
{
write_date(table2[x]);
x++;
}
}
void read_date(void)
{
ReadValue = ReadSet1302(0x81);
second=((ReadValue&0x70)>>4)*10 + (ReadValue&0x0F);
ReadValue = ReadSet1302(0x83);
minute=((ReadValue&0x70)>>4)*10 + (ReadValue&0x0F);
ReadValue = ReadSet1302(0x85);
『本文转载自网络,版权归原作者所有,如有侵权请联系删除』