|
实现功能:1、以AT89C51/52为设计核心,采用LCD屏幕显示。
2、可以显示公历日期、时间、星期(可调)
3、平年和润年区分
4、闹钟设置
5、包含原理图、源码、仿真
仿真原理图如下(proteus仿真工程文件可到本帖附件中下载)
Altium Designer画的原理图如下:(51hei附件中可下载工程文件)
调试及性能分析
6.1 软件测试
软件测试为利用Keil4软件的编译功能,讲程序导入keil编译运行,无错误显示,故通过软件测试,如图6-1所示:
6.2 proteus电路仿真
为了测试电路在下载程序后是否能够按设计运行,有两种测试方法,最初为制作硬件电路板测试,这种测试方法在有错误后常常需要重新制作电路板故后来渐渐被其它方法取代,另一种方法为在计算机上进行模拟电路仿真,这种方法简便并易差错,在此次设计电路初次测试即为利用proteus进行仿真测试,如图6-2所示:
图6-2 proteus电路仿真
DS1302模块的电路图如图4-3所示,第1脚和第4脚分别接到了电路的VCC和GND,这2个脚是芯片工作的电源输入脚。第8脚接了一个3V的纽扣电池作为时钟芯片的后备电池,可以保证断掉主电源后时钟继续行走。第2和第3脚接了一个32.768K的晶振给芯片提供时钟脉冲,最后,第5、6、7依次连接到单片机的IO口,进行数据的传输。
本设计中由于采用的按键数量较少,只有4个按键,分别是“时钟设置”、“闹钟设置”、“减”、“加”,故采用了独立键盘的方式。按键的连接图4-4所示:
程序设计
5.1 液晶程序算法
(1)1602液晶写数据函数,dat就是要写入的命令
void LcdWriteData(uchar dat)
{
LcdRs_P = 1;
LcdRw_P = 0;
LcdEn_P = 0;
P0=dat;
DelayMs(2);
LcdEn_P = 1;
DelayMs(2);
LcdEn_P = 0;
}
(2)1602液晶初始化函数
void LcdInit()
{
LcdWriteCmd(0x38); // 16*2显示,5*7点阵,8位数据口
LcdWriteCmd(0x0C); // 开显示,不显示光标
LcdWriteCmd(0x06); // 地址加1,当写入数据后光标右移
LcdWriteCmd(0x01); // 清屏
}
(3)液晶光标定位函数
void LcdGotoXY(uchar line,uchar column)
{
// 第一行
if(line==0)
LcdWriteCmd(0x80+column);
// 第二行
if(line==1)
LcdWriteCmd(0x80+0x40+column);
}
(4)液晶显示内容的初始化
void LcdShowInit()
{
LcdGotoXY(0,0);
LcdPrintStr("20 - - ");
LcdGotoXY(1,0);
LcdPrintStr(" : : ");
}
(5)液晶输出数字
void LcdPrintNum(uchar num)
{
LcdWriteData(num/10+48); // 十位
LcdWriteData(num%10+48); // 个位
}
(6)液晶显示星期
void LcdPrintWeek(uchar week)
{
switch(week)
{
case 1: LcdPrintStr(" Sun"); break;
case 2: LcdPrintStr(" Mon"); break;
case 3: LcdPrintStr("Tues"); break;
case 4: LcdPrintStr(" Wed"); break;
case 5: LcdPrintStr("Thur"); break;
case 6: LcdPrintStr(" Fri"); break;
case 7: LcdPrintStr(" Sat"); break;
default: break;
}
}
(7)液晶显示平润年
void LcdPrintYearType(uchar type)
{
switch(type)
{
case 0: LcdPrintStr(" RUN"); break;
case 1: LcdPrintStr(" PING"); break;
default: break;
}
}
(8)刷新时间显示
void FlashTime()
{
LcdGotoXY(0,2); // 年份
LcdPrintNum(TimeBuff[0]);
LcdGotoXY(0,5); // 月份
LcdPrintNum(TimeBuff[1]);
LcdGotoXY(0,8); // 日期
LcdPrintNum(TimeBuff[2]);
LcdGotoXY(1,0); // 小时
LcdPrintNum(TimeBuff[4]);
LcdGotoXY(1,3); // 分钟
LcdPrintNum(TimeBuff[5]);
LcdGotoXY(1,6); // 秒钟
LcdPrintNum(TimeBuff[6]);
LcdGotoXY(0,11); // 星期
LcdPrintWeek(TimeBuff[3]);
LcdGotoXY(1,11); // 平润年
LcdPrintYearType(nian_type);
}
5.2 时钟程序算法
(1)初始化DS1302
void DS1302_Init(void)
{
RST_P=0; // RST脚置低
SCK_P=0; // SCK脚置低
SDA_P=0; // SDA脚置低
}
(2)从DS1302读出一字节数据
uchar DS1302_Read_Byte(uchar addr)
{
uchar i;
uchar temp;
RST_P=1;
for(i=0;i<8;i++)
{
if(addr&0x01)
SDA_P=1;
else
SDA_P=0;
SCK_P=1;
_nop_();
SCK_P=0;
_nop_();
addr=addr>> 1;
}
for(i=0;i<8;i++)
{
temp=temp>>1;
if(SDA_P)
temp|= 0x80;
else
temp&=0x7F;
SCK_P=1;
_nop_();
SCK_P=0;
_nop_();
}
RST_P=0;
return temp;
}
(3)向DS1302写入时间数据
void DS1302_Write_Time()
{
uchar i;
uchar temp1;
uchar temp2;
for(i=0;i<7;i++) // 十进制转BCD码
{
temp1=(TimeBuff[ i]/10)<<4;
temp2=TimeBuff[ i]%10;
TimeBuff[ i]=temp1+temp2;
}
DS1302_Write_Byte(0x8E,0x00); // 关闭写保护
DS1302_Write_Byte(0x80,0x80); // 暂停时钟
DS1302_Write_Byte(0x8C,TimeBuff[0]); // 年
DS1302_Write_Byte(0x88,TimeBuff[1]); // 月
DS1302_Write_Byte(0x86,TimeBuff[2]); // 日
DS1302_Write_Byte(0x8A,TimeBuff[3]); // 星期
DS1302_Write_Byte(0x84,TimeBuff[4]); // 时
DS1302_Write_Byte(0x82,TimeBuff[5]); // 分
DS1302_Write_Byte(0x80,TimeBuff[6]); // 秒
DS1302_Write_Byte(0x80,TimeBuff[6]&0x7F); // 运行时钟
DS1302_Write_Byte(0x8E,0x80); // 打开写保护
}
(4)从DS1302读出时间数据
void DS1302_Read_Time()
{
uchar i;
uint nian_temp;
TimeBuff[0]=DS1302_Read_Byte(0x8D); // 年
TimeBuff[1]=DS1302_Read_Byte(0x89); // 月
TimeBuff[2]=DS1302_Read_Byte(0x87); // 日
TimeBuff[3]=DS1302_Read_Byte(0x8B); //星期
TimeBuff[4]=DS1302_Read_Byte(0x85); // 时
TimeBuff[5]=DS1302_Read_Byte(0x83); // 分
TimeBuff[6]=(DS1302_Read_Byte(0x81))&0x7F; // 秒
for(i=0;i<7;i++) // BCD转十进制
{
TimeBuff[ i]=(TimeBuff[ i]/16)*10+TimeBuff[ i]%16;
}
nian_temp=2000+TimeBuff[0];
//计算平润年
if((nian_temp%4==0&&nian_temp%100!=0)||(nian_temp%400==0))
{
nian_type=0;
}
else
{
nian_type=1;
}
}
下载:
基于51单片机LCD万年历.7z
(359.96 KB, 下载次数: 219)
|
评分
-
查看全部评分
|