51单片机ds1302时钟报告Word文档下载推荐.docx
《51单片机ds1302时钟报告Word文档下载推荐.docx》由会员分享,可在线阅读,更多相关《51单片机ds1302时钟报告Word文档下载推荐.docx(23页珍藏版)》请在冰豆网上搜索。
首先,RST接通控制逻辑,允许地址/命令序列送入移位寄存器;
其次,RST提供终止单字节或多字节数据传送的方法。
当RST为高电平时,所有的数据传送被初始化,允许对DS1302进行操作。
如果在传送过程中RST置为低电平,则会终止此次数据传送,I/O引脚变为高阻态。
上电运行时,在Vcc>
2.0V之前,RST必须保持低电平。
只有在SCLK为低电平时,才能将RST置为高电平。
I/O为串行数据输入输出端(双向),后面有详细说明。
SCLK为时钟输入端。
下图为DS1302的引脚功能图:
图1Ds1302引脚口
1.2单片机概述
单片微型计算机的诞生是计算机发展史上的一个新的里程碑。
近年来,随着技术的发展和进步,以及市场对产品功能和性能的要求不断提高,直流电动机的应用更加广泛,尤其是在智能机器人中的应用。
直流电动机的起动和调速性能、过载能力强等特点显得十分重要,为了能够适应发展的要求,单闭环直流电动机的调速控制系统得到了很大的发展。
而作为单片嵌入式系统的核心—单片机,正朝着多功能、多选择、高速度、低功耗、低价格、大存储容量和强I/O功能等方向发展。
随着计算机档次的不断提高,功能的不断完善,单片机已越来越广泛地应用在各种领域的控制、自动化、智能化等方面,特别是在直流电动机的调速控制系统中。
这是因为单片机具有很多优点:
体积小,功能全,抗干扰能力强,可靠性高,结构合理,指令丰富,控制功能强,造价低等。
所以选用单片机作为控制系统的核心以提高整个系统的可靠性和可行性。
本设计的80C51单片机属于MCS-51系列单片机,由Intel公司开发,其结构是8048的延伸,改进了8048的缺点,增加了如乘(MUL)、除(DIV)、减(SUBB)、比较(CMP)、16位数据指针、布尔代数运算等指令,以及串行通信能力和5个中断源。
采用40引脚双列直插式DIP(DualInLinePackage),内有128个RAM单元及4K的ROM。
图280C51单片机引脚口
第二章总体方案
2.1系统框架设计
方案说明:
时钟系统以80C51单片机为控制核心,由输入模块、LCD显示模块及时钟电路组成。
采用独立式键盘作为命令的输入,单片机在程序控制下,定时读取DS1302的片内数据,完成年、月、日、小时、分钟、秒的实时显示。
图3系统框架设计
2.2设计思路
时钟系统的主要功能包括:
实现对时间的显示,时间的调整,能够很方便的实现时间系统控制。
程序启动后,由DS1302的初始化,LCD1602的初始化后进入主循环,主循环由扫描按键,读取时间,显示三部分构成。
第三章系统硬件设计
3.1单片机控制模块
本设计采用protues仿真,80C51单片机的VCC、GND、XTAL1、XTAL2、RST、EA脚均没有接外部电路,也可使用
图480C51电路的设计
3.2DS1302模块
本设计采用protues仿真,DS1302的X1、X2、GND脚没有接外部电路,即可使用
图5DS1302电路的设计
3.3LCD显示模块
本设计采用protues仿真,LCD1602的Vcc、VEE、VDD、VSS、GND脚没有接外部电路,即可使用
图6LCD1602电路的设计
3.1独立键盘控制模块
本设计采用protues仿真,共有5个按键,分别对应不同功能,如下表:
本设计中有5个独立式按键,具体功能如下:
I/O口
按键
具体功能
P3.0
K1
开启时间修改
P3.1
K2
时间位选加
P3.2
K3
时间位选减
P3.3
K4
时间加
P3.7
K5
时间减
表1独立按键功能
图7独立按键电路的设计
结论
通过本次实验设计,使我们学到了许多书本上无法学到的知识,也使我们深刻体会到单片机技术应用领域的广泛。
不仅让我们对学过的单片机知识有了很多的巩固,同时也对单片机这一门学科产生了更大的兴趣。
通过本次设计,较系统地掌握有关单片机控制的设计思想和设计方法,主要对51系列单片机的结构、功能、及内部资源,LCD显示器等的了解,并对其进行测试和加以应用的知识得到学习。
附录一:
总电路图
附录二:
程序
#include<
reg51.h>
intrins.h>
#defineucharunsignedchar
#defineuintunsignedint
sbitK1=P3^0;
//定义K1键
sbitK2=P3^1;
//定义K2键
sbitK3=P3^2;
//定义K3键
sbitK4=P3^3;
//P1^3定义K4键
sbitK5=P3^7;
sbitBEEP=P2^3;
//定义蜂鸣器
sbitreset=P1^2;
//P2^5;
sbitsclk=P1^0;
//P2^6;
sbitio=P1^1;
//P2^7;
sbitLCD_RS=P3^5;
sbitLCD_RW=P3^6;
sbitLCD_EN=P3^4;
ucharcount_10ms;
//定义10ms计数器
bitK1_FLAG=0;
//定义按键标志位,当按下K1键时,该位置1,K1键未按下时0。
uchardisp_buf[16]={0x00};
//定义显示缓冲区
uchartime_buf[7]={0,0,0,0,0,0,0};
//DS1302时间缓冲区,存放秒、分、时、日、月、星期、年
uchartemp[2]={0};
//用来存放设置时的小时、分钟的中间值
uintm=0,n=0,r=0;
/********以下是函数声明********/
voidDelay_ms(uintxms);
bitlcd_busy();
voidlcd_wcmd(ucharcmd);
voidlcd_wdat(uchardat);
voidlcd_clr();
voidlcd_init();
voidwrite_byte(ucharinbyte);
//写一字节数据函数声明
ucharread_byte();
//读一字节数据函数声明
voidwrite_ds1302(ucharcmd,ucharindata);
//写DS1302函数声明
ucharread_ds1302(ucharaddr);
//读DS1302函数声明
voidset_ds1302(ucharaddr,uchar*p,ucharn);
//设置DS1302初始时间函数声明
voidget_ds1302(ucharaddr,uchar*p,ucharn);
//读当前时间函数声明
voidinit_ds1302();
//DS1302初始化函数声明
/********以下是延时函数********/
voidDelay_ms(uintxms)
{
uinti,j;
for(i=xms;
i>
0;
i--)//i=xms即延时约xms毫秒
for(j=70;
j>
j--);
}
/********以下是LCD忙碌检查函数********/
bitlcd_busy()
bitresult;
LCD_RS=0;
LCD_RW=1;
LCD_EN=1;
_nop_();
_nop_();
result=(bit)(P0&
0x80);
LCD_EN=0;
returnresult;
/********以下是写指令寄存器IR函数********/
voidlcd_wcmd(ucharcmd)
{Delay_ms(5);
LCD_RW=0;
P0=cmd;
/********以下是写寄存器DR函数********/
voidlcd_wdat(uchardat)
LCD_RS=1;
P0=dat;
/********以下是LCD清屏函数********/
voidlcd_clr()
lcd_wcmd(0x01);
//清除LCD的显示内容
Delay_ms(5);
/********以下是LCD初始化函数********/
voidlcd_init()
Delay_ms(15);
//等待LCD电源稳定
lcd_wcmd(0x38);
//16*2显示,5*7点阵,8位数据
lcd_wcmd(0x0c);
//显示开,关光标
lcd_wcmd(0x06);
//移动光标
/********以下是写一字节数据函数********/
voidwrite_byte(ucharinbyte)
uchari;
for(i=0;
i<
8;
i++)
{
sclk=0;
//写时低电平改变数据
if(inbyte&
0x01)
io=1;
else
io=0;
sclk=1;
//高电平把数据写入DS1302
_nop_();
inbyte=inbyte>
>
1;
}
/********以下是读一字节数据函数********/
ucharread_byte()
uchari,temp=0;
io=1;
7;
if(io==1)
temp=temp|0x80;
temp=temp&
0x7f;
//产生下跳沿
temp=temp>
return(temp);
/********写DS1302函数,往DS1302的某个地址写入数据********/
voidwrite_ds1302(ucharcmd,ucharindata)
sclk=0;
reset=1;
write_byte(cmd);
write_byte(indata);
reset=0;
/********读DS1302函数,读DS1302某地址的的数据********/
ucharread_ds1302(ucharaddr)
ucharbackdata;
write_byte(addr);
//先写地址
backdata=read_byte();
//然后读数据
return(backdata);
/*********以下是蜂鸣器响一声函数********/
voidbeep()
BEEP=0;
//蜂鸣器响
Delay_ms(100);
BEEP=1;
//关闭蜂鸣器
/********以下是转换函数,负责将走时数据转换为适合LCD显示的数据********/
voidLCD_conv(ucharin7,in5,in4,in1,in2,in3)//形参in1、in2、in3接收实参time_buf[2]、time_buf[1]、time_buf[0]传来的小时、分钟、秒数据
disp_buf[0]=in1/10+0x30;
//小时十位数据
disp_buf[1]=in1%10+0x30;
//小时个位数据
disp_buf[2]=in2/10+0x30;
//分钟十位数据
disp_buf[3]=in2%10+0x30;
//分钟个位数据
disp_buf[4]=in3/10+0x30;
//秒十位数据
disp_buf[5]=in3%10+0x30;
//秒个位数据
disp_buf[6]=2+0x30;
//年千位数据
disp_buf[7]=0+0x30;
//年百位数据
disp_buf[8]=in7/10+0x30;
//年十位数据
disp_buf[9]=in7%10+0x30;
//年时个位数据
disp_buf[10]=in5/10+0x30;
//月十位数据
disp_buf[11]=in5%10+0x30;
//月个位数据
disp_buf[12]=in4/10+0x30;
//日十位数据
disp_buf[13]=in4%10+0x30;
//日个位数据
/********以下是LCD显示函数,负责将函数LCD_conv转换后的数据显示在LCD上********/
voidLCD_disp()
lcd_wcmd(0x80+3);
//显示第一行
lcd_wdat(disp_buf[6]);
//显示年千位
lcd_wdat(disp_buf[7]);
//显示年百位
lcd_wdat(disp_buf[8]);
//显示年十位
lcd_wdat(disp_buf[9]);
//显示年个位
lcd_wdat(0x3a);
lcd_wdat(disp_buf[10]);
//显示月十位
lcd_wdat(disp_buf[11]);
//显示月个位
lcd_wdat(disp_buf[12]);
//显示日十位
lcd_wdat(disp_buf[13]);
//显示日个位
lcd_wcmd(0x44+0x80);
//从第2行第4列开始显示
lcd_wdat(disp_buf[0]);
//显示小时十位
lcd_wdat(disp_buf[1]);
//显示小时个位
//显示'
:
'
lcd_wdat(disp_buf[2]);
//显示分钟十位
lcd_wdat(disp_buf[3]);
//显示分钟个位
lcd_wdat(disp_buf[4]);
//显示秒十位
lcd_wdat(disp_buf[5]);
//显示秒个位
/********以下是按键处理函数********/
voidKeyProcess()
ucharmiao16,min16,hour16,ri16,yue16,nian16;
//定义16进制的分钟和小时变量
write_ds1302(0x8e,0x00);
//DS1302写保护控制字,允许写
lcd_wcmd(0x0f);
lcd_wcmd(0x80+0x40+12);
if(K2==0)
Delay_ms(10);
//延时去抖
if(K2==0)
{
while(!
K2);
m++;
if(m==7)
{
m=1;
}
}
if(K3==0)
if(K3==0)
K3);
m--;
if(m==0)
m=6;
if(m!
=0)
if(m==1&
&
K4==0)
Delay_ms(10);
if(m==1&
lcd_wcmd(0x0f);
lcd_wcmd(0x80+0x40+8);
while(!
K4);
beep();
time_buf[1]=time_buf[1]+1;
//分钟加1
if(time_buf[1]==60)time_buf[1]=0;
//当分钟加到60时初始化为0
min16=time_buf[1]/10*16+time_buf[1]%10;
//将所得的分钟数据转变成16进制数据
write_ds1302(0x82,min16);
if(m==2&
if(m==2&
lcd_wcmd(0x80+0x40+5);
time_buf[2]=time_buf[2]+1;
//小时减1
if(time_buf[2]==24)time_buf[2]=0;
//当变成0时初始化为24
hour16=time_buf[2]/10*16+time_buf[2]%10;
//将所得的小时数据转变成16进制数据
write_ds1302(0x84,hour16);
if(m==3&
if(m==3&
lcd_wcmd(0x80+12);
time_buf[3]=time_buf[3]+1;
//日减1
if(time_buf[3]==32)time_buf[3]=1;
//当日加到31初始化为0
ri16=time_buf[3]/10*16+time_buf[3]%10;
//将所得的日数据转变成16进制数据
write_ds1302(0x86,ri16);
if(m==4&
if(m==4&
lcd_wcmd(0x80+9);
time_buf[4]=time_buf[4]+1;
//月加1
if(time_buf[4]==13)time_buf[4]=1;
//当月加到12初始化为1
yue16=time_buf[4]/10*16+time_buf[4]%10;
//将所得的月数据转变成16进制数据
write_ds1302(0x88,yue16);
if(m==5&