SCLK:
串行时钟输入端,控制数据的输入与输出。
I/O:
三线接口时的双向数据线。
CE:
输入信号,在读、写数据期间必须为高
DS1302的引脚如图4所示:
图4DS1302的引脚图
2.3.3时钟集成模块内部原理图
图5时钟集成模块内部原理图
3软件设计
3.1系统硬件概述
电路以AT89C51单片机最小系统为控制核心,时钟电路由高精度低功耗的DS1302提供,采用三线接口与CPU进行同步通信,输入部分采用四个独立式按键S1、S2、S3、S4、S5。
1602液晶显示部分,D0-D7口与单片机P0口相连。
具体电路连接,详见附录1
3.2程序结构图
图6程序结构图
3.3程序流程图
图7系统主程序流程图
4Proteus与Keil联调
4.1Keil调试
图8Keil调试图
4.2与Proteus联调
图9Proteus与Keil联调
4.3联调成功
图10联调成功
5设计心得
5.1实习日记
2015年6月29日
今天是硬件实习的第一天,潘老师在课堂上给我们布置了接下来3个礼拜的时间需要完成的任务,同时精心的给我们讲解了每道题目的要求,需要实现的功能,以及对于从没接触过的问题如何动手去做,在老师的一步步引导下我们慢慢的对自己要做的题目有个由浅到深的了解,之后怀着整装待出发的心情迎接这对于动手操作能力很强的实践挑战。
下午便开始了对资料的收集过程。
虽然说资料搜集过程很简单,但其实在这里面也不乏许多学问,能否收集的切题,收集的恰到好处,也是种收集的能力。
所以,在整个过程中不论是什么环节,我相信都是对能力锻炼的绝好机会。
对于即将开始的硬件实习,我满怀期待。
同时内心又存在担忧,因为我不知道我能否完成这样一个挑战。
2015年7月6日—8日
在这几天,我们需要做的就是协商量对于硬件和软件方面的设计方案,虽然上个星期我们收集了很多资料,也对这次的课题有了大概的了解。
但是真正动手去画仿真图的时候还是遇到了很多问题,毕竟这是我们第一次接触到Proteus软件。
我们用了2天时间边画边学,画好了仿真图。
看着那排列整齐的图形,我觉得非常自豪。
2015年7月9日—15日
这是这次硬件实习的最后一步,也是最重要的一步。
我们要用KeiluVision2为硬件编程,如果说仿真图是躯干,那程序就是大脑。
仿真图能不能运行就看程序了。
通过一个多星期的努力,我们不停的纠错改错,到最后终于看到LCD屏幕上出现时间信息。
5.2实习心得体会
本次经历了3个礼拜的时间,对我来说收获很大,记得一开始听说有单片机硬件实习的时候还有些担心自己是否能够按时完成任务,到后来的坦然面对,到后来的挫败感,再到后来的信心满满,心情不断的起伏变化,当然收获也是颇大的,实现了从学习理论知识的能力到实践动手操作的跨越。
参考文献
[1]李广第,朱月秀.单片机基础第三版.北京:
北京航空航天大学出版社(1——259)。
[2]李庆亮.C语言程序设计实用教程.北京:
机械工业出版社,2005.3(1——100)。
[3]康华光.电子技术基础数字部分.北京:
高等教育出版社,2008(1——560)。
[4]康华光.电子技术基础模拟部分.北京:
高等教育出版社,2008(1——560)。
[5]杨志忠.数字电子技术.北京:
高等教育出版社,2003.12(30——100)。
[6]及力.Protel99SE原理图与PCB设计教程.北京:
电子工业出版社,2007.8(48——100)。
[7]杨欣.电子设计从零开始.北京:
清华大学出版社,2005(10——200)。
[8]邢小杰.单片机电子时钟设计.中国科技博览,2009。
附录1硬件原理图
附录2代码清单
#include
#include
#defineucharunsignedchar
#defineuintunsignedint
sbitACC0=ACC^0;
sbitACC7=ACC^7;
sbitt=P1^0;//进入调时按键
sbitjia=P1^1;//加一按键
sbitjian=P1^2;//减一按键
sbitm=P1^3;//退出调时按键
sbitBEEP=P2^0;//蜂鸣器
sbitjtod=P1^4;//矩阵按键转独立按键,该脚置0
sbitT_CLK=P1^6;/*实时时钟时钟线引脚*/
sbitT_IO=P3^5;/*实时时钟数据线引脚*/
sbitT_RST=P1^7;/*实时时钟复位线引脚*/
sbitE=P2^7;//1602使能引脚
sbitRW=P2^6;//1602读写引脚
sbitRS=P2^5;//1602数据/命令选择引脚
ucharcodehanzi[][8]={{0x04,0x0f,0x12,0x0f,0x0a,0x1f,0x02,0x02},{0x0f,0x09,0x0f,0x09,0x0f,0x09,0x13,0x11},{0x1f,0x11,0x11,0x1f,0x11,0x11,0x1f,0x00}};
voidv_W1302(ucharucAddr,ucharucDa);
ucharuc_R1302(uchar);
uchardectobcd(ucharbcd);
ucharbcdtodec(uchar);
voidbeep();
voiddelay(ucharx)
{
uchari;
while(x--)
for(i=0;i<110;i++);
}
/********************************************************************
*名称:
enable(uchardel)
*功能:
1602命令函数
*输入:
输入的命令值
*输出:
无
***********************************************************************/
voidenable(uchardel)
{
RS=0;
RW=0;
P0=del;
E=1;
delay(3);
E=0;
}
/********************************************************************
*名称:
write(uchardel)
*功能:
1602写数据函数
*输入:
需要写入1602的数据
*输出:
无
***********************************************************************/
voidwrite(uchardel)
{
RS=1;
RW=0;
P0=del;
E=1;
delay(3);
E=0;
}
/********************************************************************
*名称:
L1602_init()
*功能:
1602初始化,请参考1602的资料
*输入:
无
*输出:
无
***********************************************************************/
voidL1602_init(void)
{
enable(0x01);
enable(0x38);
enable(0x06);
enable(0x0c);
E=0;
}
//装入自定义字符(汉字)
voidwritch()
{
uchari,j;
enable(0x40);
for(i=0;i<8;i++)
for(j=0;j<8;j++)
write(hanzi[i][j]);
}
/********************************************************************
*名称:
L1602_char(ucharhang,ucharlie,charsign)
*功能:
改变液晶中某位的值,如果要让第一行,第五个字符显示"b",调用该函数如下
L1602_char(1,5,'b')
*输入:
行,列,需要输入1602的数据
*输出:
无
***********************************************************************/
voidL1602_char(ucharhang,ucharlie,charsign)
{
uchara;
if(hang==1)a=0x80;
if(hang==2)a=0xc0;
a=a+lie-1;
enable(a);
write(sign);
}
/********************************************************************
*名称:
L1602_string(ucharhang,ucharlie,uchar*p)
*功能:
改变液晶中某位的值,如果要让第一行,第五个字符开始显示"abcdef",调用该函数如下
L1602_string(1,5,"abcdef;")
*输入:
行,列,需要输入1602的数据
*输出:
无
***********************************************************************/
voidL1602_string(ucharhang,ucharlie,uchar*p)
{
uchara;
if(hang==1)a=0x80;
if(hang==2)a=0xc0;
a=a+lie-1;
enable(a);
while
(1)
{
if(*p=='\0')break;
write(*p);
p++;
}
}
//时钟调节//
voidtimechange()
{
uchara,num=1;
ucharyear,mon,day,hour,min,sec;
//进入调时循环
while(num)
{
if(t==0)
delay(5);
if(t==0)
{
num++;
beep();
while(!
t);
}
//退出调时按键m
if(m==0)
delay(5);
if(m==0)
num=0;
enable(0x0f);
a=uc_R1302(0x81)|0x80;
v_W1302(0x8e,0);
v_W1302(0x80,a);
//调时到年以后退出调时
if(num==7)
num=0;
//num=1调秒
if(num==1)
{
enable(0xc0+12);
if(jia==0)
delay(5);
if(jia==0)//秒加一
{
while(!
jia);
sec=bcdtodec(uc_R1302(0x81)&0x7f);
sec++;
if(sec>59)
sec=0;
L1602_char(2,12,sec/10%10+48);
L1602_char(2,13,sec%10+48);
v_W1302(0x80,dectobcd(sec)|0x80);
}
if(jian==0)//秒减一
delay(5);
if(jian==0)
{
while(!
jian);
sec=bcdtodec(uc_R1302(0x81));
sec--;
if(sec==-1)
sec=59;
L1602_char(2,12,sec/10%10+48);
L1602_char(2,13,sec%10+48);
v_W1302(0x80,dectobcd(sec)|0x80);
}
}
if(num==2)//调分钟
{
enable(0xc0+9);
if(jia==0)
delay(5);
if(jia==0)
{
min=bcdtodec(uc_R1302(0x83));
min++;
while(!
jia);
if(min>59)
min=0;
L1602_char(2,9,min/10%10+48);
L1602_char(2,10,min%10+48);
v_W1302(0x82,dectobcd(min));
}
if(jian==0)
delay(5);
if(jian==0)
{
min=bcdtodec(uc_R1302(0x83));
min--;
while(!
jian);
if(min==-1)
min=59;
L1602_char(2,9,min/10%10+48);
L1602_char(2,10,min%10+48);
v_W1302(0x82,dectobcd(min));
}
}
if(num==3)//调小时
{
enable(0xc0+6);
if(jia==0)
delay(5);
if(jia==0)
{
hour=bcdtodec(uc_R1302(0x85));
hour++;
while(!
jia);
if(hour>23)
hour=0;
L1602_char(2,6,hour/10%10+48);
L1602_char(2,7,hour%10+48);
v_W1302(0x84,dectobcd(hour));
}
if(jian==0)
delay(5);
if(jian==0)
{
while(!
jian);
hour=bcdtodec(uc_R1302(0x85));
hour--;
if(hour==-1)
hour=23;
L1602_char(2,6,hour/10%10+48);
L1602_char(2,7,hour%10+48);
v_W1302(0x84,dectobcd(hour));
}
}
if(num==4)//调日期
{
enable(0x80+13);
if(jia==0)
delay(5);
if(jia==0)
{
hour=bcdtodec(uc_R1302(0x87));
day++;
while(!
jia);
if(day>31)
day=0;
L1602_char(1,13,day/10%10+48);
L1602_char(1,14,day%10+48);
v_W1302(0x86,dectobcd(day));
}
if(jian==0)
delay(5);
if(jian==0)
{
while(!
jian);
day=bcdtodec(uc_R1302(0x87));
day--;
if(day==-1)
day=31;
L1602_char(1,13,day/10%10+48);
L1602_char(1,14,day%10+48);
v_W1302(0x86,dectobcd(day));
}
}
if(num==5)//调月份
{
enable(0x80+10);
if(jia==0)
delay(5);
if(jia==0)
{
mon=bcdtodec(uc_R1302(0x89));
mon++;
while(!
jia);
if(mon>12)
mon=0;
L1602_char(1,10,mon/10%10+48);
L1602_char(1,11,mon%10+48);
v_W1302(0x88,dectobcd(mon));
}
if(jian==0)
delay(5);
if(jian==0)
{
while(!
jian);
mon=bcdtodec(uc_R1302(0x89));
mon--;
if(mon==-1)
mon=12;
L1602_char(1,10,mon/10%