基于stc51单片机的LCD1602显示时间的电子万年历显示Word格式文档下载.docx
《基于stc51单片机的LCD1602显示时间的电子万年历显示Word格式文档下载.docx》由会员分享,可在线阅读,更多相关《基于stc51单片机的LCD1602显示时间的电子万年历显示Word格式文档下载.docx(36页珍藏版)》请在冰点文库上搜索。
(6)程序写入完毕,目标板开始运行程序结果。
2 方案分析与确定
2.1方案思路分析
由题目要求,根据设置的年份日的显示全年的年月公历、星期等信息。
由于需要显示去年的日期以及星期等信息,普通的LED数码管显然已经不能胜任,为此,我们可以选择LCD1602液晶显示器完成课设要求。
目前所具备的设备只有一块以STC89C52为内核的单片机,PC机。
课设要求显示日期等信息,我们可以充分利用单片机上面集成的DS1302时钟芯片。
该芯片可以产生年份,月份,日期,星期,时,分,秒的数据,因此,完全可以完成实验的各项要求。
基于以上分析,我们可以利用DS1302产生的各种时钟数据,由CPU完成对数据的读取,然后通过CPU将数据写至LCD1602,以显示数据,达到可视化的效果。
对于课程设计的拓展部分,我们可以利用单片机开发板上面集成的DS18B20温度传感器来测试周围环境的温度,同样通过LCD1602来显示。
此外可以通过测试按键是否闭合来改变各种时间数据,已达到校准的目的。
图2.1 整体设计框架图
2.2方案流程图
根据以上分析,以及使用各种芯片的操作流程,我们可以大致确定课程设计的软件设计方案方案,其大致流程如下:
图2.2设计流程图
3单元芯片电路的设置及总体设计
3.1DS1302芯片引脚功能
DS1302是美国DALLAS公司推出的一种高性能、低功耗、带RAM的实时时钟电路,它可以对年、月、日、周日、时、分、秒进行计时,具有闰年补偿功能,工作电压为2.5V~5.5V。
采用三线接口与CPU进行同步通信,并可采用突发方式一次传送多个字节的时钟信号或RAM数据。
DS1302内部有一个31×
8的用于临时性存放数据的RAM寄存器。
DS1302是DS1202的升级产品,与DS1202兼容,但增加了主电源/后备电源双电源引脚,同时提供了对后备电源进行涓细电流充电的能力。
DS1302的引脚排列,其中Vcc1为后备电源,VCC2为主电源。
在主电源关闭的情况下,也能保持时钟的连续运行。
DS1302由Vcc1或Vcc2两者中的较大者供电。
当Vcc2大于Vcc1+0.2V时,Vcc2给DS1302供电。
当Vcc2小于Vcc1时,DS1302由Vcc1供电。
X1和X2是振荡源,外接32.768kHz晶振。
RST是复位/片选线,通过把RST输入驱动置高电平来启动所有的数据传送。
RST输入有两种功能:
首先,RST接通控制逻辑,允许地址/命令序列送入移位寄存器;
其次,RST提供终止单字节或多字节数据的传送手段。
当RST为高电平时,所有的数据传送被初始化,允许对DS1302进行操作。
如果在传送过程中RST置为低电平,则会终止此次数据传送,I/O引脚变为高阻态。
上电运行时,在Vcc>
2.0V之前,RST必须保持低电平。
只有在SCLK为低电平时,才能将RST置为高电平。
I/O为串行数据输入输出端(双向),后面有详细说明。
SCLK为时钟输入端。
下图为DS1302的引脚功能图:
图3.1DS1302引脚图
管脚描述:
X1X2 32.768KHz晶振管脚
GND 地
RST 复位脚
I/O 数据输入/输出引脚
SCLK 串行时钟
Vcc1,Vcc2 电源供电管脚
此外,拓展中用到了DS18B20温度传感器,其使用与DS1302比较类似,因此这里不再赘述。
3.2 DS1302的使用方法
使用DS1302时,要对其引脚和寄存器进行特殊设置,以实现所需功能。
引脚设置后面会提及,这里不做说明,主要讲一下程序的编写。
DS1302的的工作过程中包过读写一个字节数据等过程,下面做相应的解释。
/********************************
功 能:
往DS1302写入数据
*********************************/
voidW1302(ucharucAddr,ucharucDa)
{
T_RST =0;
T_CLK= 0;
T_RST = 1;
RTInputByte(ucAddr);
/*地址,命令 */
RTInputByte(ucDa);
/*写1Byte数据*/
T_CLK= 1;
T_RST=0;
}
/********************************
功 能:
读取DS1302某地址的数据
*********************************/
ucharR1302(ucharucAddr)
ucharucData;
T_RST=0;
T_CLK= 0;
T_RST= 1;
RTInputByte(ucAddr);
/* 地址,命令*/
ucData= RTOutputByte();
/* 读1Byte数据*/
T_CLK=1;
T_RST=0;
return(ucData);
/***********************************
功能:
设置初始时间
************************************/
void Set1302(uchar *pClock)
uchar i;
ucharucAddr=0x80;
ﻩEA=0;
W1302(0x8e,0x00);
/*控制命令,WP=0,写操作?
*/
for(i=7;
i>
0;
i--)
{
W1302(ucAddr,*pClock);
/*秒分时日 月星期 年*/
pClock++;
ucAddr+=2;
}
W1302(0x8e,0x80);
/* 控制命令,WP=1,写保护?
*/
ﻩEA=1;
/******************************
功 能:
读取DS1302当前时间
*******************************/
voidGet1302(ucharucCurtime[])
uchari;
ucharucAddr =0x81;
EA=0;
for (i=0;
i<
7;
i++)
{
ucCurtime[i]=R1302(ucAddr);
/*格式为:
秒分时日 月星期 年 */
ucAddr+=2;
}
EA = 1;
}
3.3 LCD1602引脚功能
1602液晶也叫1602字符型液晶它是一种专门用来显示字母、数字、符号等的点阵型液晶模块它有若干个5X7或者5X11等点阵字符位组成,每个点阵字符位都可以显示一个字符。
每位之间有一个点距的间隔每行之间也有间隔起到了字符间距和行间距的作用,正因为如此所以他不能显示图形
n1602LCD是指显示的内容为16X2,即可以显示两行,每行16个字符液晶模块(显示字符和数字)。
图3.2LCD1602引脚图
1602采用标准的16脚接口,其中:
第1脚:
VSS为电源地
第2脚:
VDD接5V电源正极
第3脚:
V0为液晶显示器对比度调整端,接正电源时对比度最弱,接地电源时对比度最高(对比度过高时会产生“鬼影”,使用时可以通过一个10K的电位器调整对比度)。
第4脚:
RS为寄存器选择,高电平1时选择数据寄存器、低电平0时选择指令寄存器。
第5脚:
RW为读写信号线,高电平
(1)时进行读操作,低电平(0)时进行写操作。
第6脚:
E(或EN)端为使能(enable)端。
第7~14脚:
D0~D7为8位双向数据端。
第15~16脚:
空脚或背灯电源。
15脚背光正极,16脚背光负极。
3.4LCD1602的使用
LCD1602的使用与前面的DS1302的使用有类似的地方,包括引脚的设置和对应的编程,引脚的设置后面会提及到,这里只涉及对应的编程。
/*LCD1602延时*/
void Lcd_delay(ucharms)
{
ucharj;
while(ms--){
for(j=0;
j<250;
j++)
{;
}
/*LCD1602忙等待*/
voidLcd_busy_wait(){
Lcd_rs=0;
Lcd_rw = 1;
Lcd_en=1;
Lcd_data=0xff;
while (Lcd_data&0x80);
Lcd_en= 0;
/*LCD1602命令字写入*/
voidLcd_command_write(ucharcommand)
Lcd_busy_wait();
Lcd_rs=0;
Lcd_rw = 0;
Lcd_en=0;
Lcd_data=command;
Lcd_en=1;
Lcd_en=0;
/*LCD1602初始化*/
voidInit_lcd()
Lcd_delay(20);
Lcd_command_write(0x38);
Lcd_delay(100);
Lcd_comman/*LCD1602延时*/d_write(0x38);
Lcd_delay(50);
Lcd_command_write(0x38);
Lcd_delay(10);
Lcd_command_write(0x08);
Lcd_command_write(0x01);
Lcd_command_write(0x06);
Lcd_command_write(0x0c);
ﻩLcd_data=0xff;
/*释放数据端口*/
voidLcd_char_write(uchar x_pos,y_pos,lcd_dat)/*LCD1602字符写入*/
x_pos&
=0x0f;
/*X位置范围0~15*/
y_pos&
=0x01;
/*Y位置范围0~1 */
if(y_pos==1) x_pos+=0x40;
x_pos+=0x80;
Lcd_command_write(x_pos);
Lcd_busy_wait();
Lcd_rs =1;
Lcd_rw=0;
Lcd_en=0;
Lcd_data= lcd_dat;
Lcd_en=1;
Lcd_en =0;
Lcd_data = 0xff;
/*释放数据端口*/
4 整体电路设计和程序
由上面的分析可以得到实验的电路图如下:
图4.1仿真电路图
设计源代码如下:
/****************************************************************
程序名称:
LCD1602显示时间显示当前温度
*****************************************************************/
/*头文件*/
#include <
reg52.h>
#include <
intrins.h>
#defineuintunsignedint
#defineucharunsignedchar
#definenop()_nop_()
sbits1=P1^0;
sbits2=P1^1;
sbit s3=P1^2;
sbits4=P1^3;
sbitDQ=P3^5;
//定义DS18B20通信端口
sbitlcd_rs_port=P1^7;
/*定义LCD控制端口*/
sbitlcd_rw_port=P1^6;
sbitlcd_en_port=P2^4;
#define lcd_data_port P0
sbitled_latch_port= P2^5;
/*发光二极管寄存器LE引脚*/
sbit sled_latch_port=P3^6;
/*数码管寄存器LE引脚*/
sbit T_CLK = P1^4;
/*实时时钟时钟线引脚 */
sbitT_IO=P1^5;
/*实时时钟数据线引脚*/
sbit T_RST =P2^2;
/*实时时钟复位线引脚*/
sbitACC0=ACC^0;
sbitACC7=ACC^7;
ucharcodemun_to_char[] ={"0123456789ABCDEF"
};
/*定义数字跟ASCII码的关系*/
uchardatatime_data_buff[7]={0x50,0x59,0x23,0x31,0x12,0x04,0x12};
秒分 时日月星期年 */
uchar datalcd1602_line1[]={"
2000/00/00 000"
};
uchar data lcd1602_line2[]={"
00:
00:
00 00.0"};
ucharcode Weeks[][3]={{"
SUN"
},{"
MON"},{"
TUE"
WED"
},{"
THU"
FRI"},{"
SAT"},{"
SUN"}};
/**************************************************************** 函 数名:
RTInputByte()
功 能:
实时时钟写入一字节
说 明:
往DS1302写入1Byte数据(内部函数)
入口参数:
d写入的数据
返回值:
无
****************************************************************/
voidRTInputByte(uchard)
{
uchari;
ACC =d;
for(i=8;
i>0;
i--)
{
T_IO= ACC0;
/*相当于汇编中的RRC*/
T_CLK=1;
T_CLK= 0;
ACC=ACC>
>1;
}
/****************************************************************函数名:
RTOutputByte()
功 能:
实时时钟读取一字节
说 明:
从DS1302读取1Byte数据 (内部函数)
入口参数:
无
返回值:
ACC
****************************************************************/
ucharRTOutputByte(void)
{
uchari;
for(i=8;
i--)
{
ACC=ACC>
>
1;
/*相当于汇编中的 RRC */
ACC7=T_IO;
T_CLK=1;
T_CLK = 0;
}
return(ACC);
/**************************************************************** 函 数名:
W1302()
功 能:
往DS1302写入数据
说明:
先写地址,后写命令/数据(内部函数)
调 用:
RTInputByte() ,RTOutputByte()
ucAddr:
DS1302地址,ucData:
要写的数据
返回 值:
无
****************************************************************/voidW1302(ucharucAddr,ucharucDa)
T_RST=0;
T_CLK= 0;
T_RST=1;
RTInputByte(ucAddr);
/*地址,命令*/
RTInputByte(ucDa);
/*写1Byte数据*/
T_CLK = 1;
T_RST=0;
}
/***************************************************************
函 数名:
R1302()
功能:
读取DS1302某地址的数据
说 明:
先写地址,后读命令/数据(内部函数)
调 用:
RTInputByte(),RTOutputByte()
ucAddr:
DS1302地址
ucData:
读取的数据
****************************************************************/uchar R1302(ucharucAddr)
uchar ucData;
T_RST = 0;
T_CLK=0;
T_RST= 1;
RTInputByte(ucAddr);
/*地址,命令 */
ucData= RTOutputByte();
/*读1Byte数据*/
T_CLK= 1;
T_RST= 0;
return(ucData);
/****************************************************************
函数 名:
Set1302()
功 能:
先写地址,后读命令/数据(寄存器多字节方式)
调用:
W1302()
pClock:
设置时钟数据地址格式为:
秒分时日月 星期年
7Byte(BCD码)1B1B1B1B1B 1B 1B
****************************************************************/void Set1302(uchar *pClock)
uchari;
uchar ucAddr =0x80;
ﻩEA=0;
W1302(0x8e,0x00);
/*控制命令,WP=0,写操作?
for(i=7;
{
W1302(ucAddr,*pClock);
/*秒