1、 项目介绍(设计内容)
基于AT89S52单片机的多功能电子万年历的硬件结构和软硬件设计方法。本设计由数据显示模块、温度采集模块、时间处理模块和调整设置模块四个模块组成。系统以AT89S52单片机为控制器,以串行时钟日历芯片DS1302记录日历和时间,它可以对年、月、日、时、分、秒进行计时,还具有闰年补偿等多种功能。温度采集选用DS18B20芯片,万年历采用直观的数字显示,数据显示采用1602液晶显示模块,可以在LCD1602上同时显示年、月、日、周日、时、分、秒,还具有时间校准等功能。
2、 项目的总体设计
系统的功能往往决定了系统采用的结构,经过成本,性能,功耗等多方面的考虑决定用三个8位74LS164串行接口外接LED显示器,RESPACK-8对单片机AT89S52进行供电,时间芯片DS1302连接单片机AT89S52。从而实现电子万年历的功能。
按照系统设计的要求,初步确定系统由电源模块、时钟模块、显示模块、键盘接口模块、温度测量模块和闹钟模块共六个模块组成,电路系统构成框图如图1所示。
图1 硬件电路框图
图2 主程序流程图
3、 设计思路方法及实现步骤(包括硬件设计和软件设计两个部分)
3.1 Proteus仿真图
单片机电子万年历的制作有多种方法,可供选择的器件和运用的技术也有很多种。所以,系统的总体设计方案应在满足系统功能的前提下,充分考虑系统使用的环境,所选的结构要简单使用、易于实现,器件的选用着眼于合适的参数、稳定的性能、较低的功耗以及低廉的成本。
系统的功能往往决定了系统采用的结构,经过成本,性能,功耗等多方面的考虑决定用三个8位74LS164串行接口外接LED显示器,RESPACK-8对单片机AT89S52进行供电,时间芯片DS1302连接单片机AT89S52。从而实现电子万年历的功能。
按照系统设计的要求,初步确定系统由电源模块、时钟模块、显示模块、键盘接口模块、温度测量模块和闹钟模块共六个模块组成,电路系统构成框图如图1所示。
图3 硬件电路框图
3.2 DS1302读写程序设计
本系统的时间读取主要来源于单片机对DS1302的操作,在硬件上时钟芯片DS1302与单片机的连接需要三条线,即SCLK(7)、I/O(6)、RST(5),具体连接图见系统硬件设计原理图。读取写程序设计如下:
函 数 名:RTInputByte()
功 能:实时时钟写入一字节
说 明:往DS1302写入1Byte数据 (内部函数)
入口参数:d 写入的数据
返 回 值:无
void RTInputByte(uchar d)
{
uchar i;
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
uchar RTOutputByte(void)
{
uchar i;
for(i=8; i>0; i--)
{
ACC = ACC >>1; /*相当于汇编中的 RRC */
ACC7 = T_IO;
T_CLK = 1;
T_CLK = 0;
}
return(ACC);
}
函 数 名:W1302()
功 能:往DS1302写入数据
说 明:先写地址,后写命令/数据 (内部函数)
调 用:RTInputByte() , RTOutputByte()
入口参数:ucAddr: DS1302地址, ucData: 要写的数据
返 回 值:无
void W1302(uchar ucAddr, uchar ucDa)
{
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(uchar ucAddr)
{
uchar ucData;
T_RST = 0;
T_CLK = 0;
T_RST = 1;
RTInputByte(ucAddr); /* 地址,命令 */
ucData = RTOutputByte(); /* 读1Byte数据 */
T_CLK = 1;
T_RST = 0;
return(ucData);
}
DS1302与微处理器进行数据交换时,首先由微处理器向电路发送命令字节,命令字节最高位MSB(D7)必须为逻辑 1,如果D7=0,则禁止写DS1302,即写保护;D6=0,指定时钟数据,D6=1,指定RAM数据;D5~D1指定输入或输出的特定寄存器;最低位LSB(D0)为逻辑0,指定写操作(输入),D0=1,指定读操作(输出) 。
3.3 完整代码
#include<reg52.h>
#include <intrins.h>
#define uint unsigned int
#define uchar unsigned char
char a,miao,shi,fen,ri,yue,nian,keynum;
int temp;//,year1,month1,day1;
#define h1 0x80 //LCD第一行的初始化位置
#define h2 0x80+0x40 //LCD第二行初始化位置
//定义1602相关管脚
sbit rs=P1^2;
sbit en=P1^0;
sbit rw=P1^1;
//DS1302芯片的管脚定义
sbit DSIO=P1^5;
sbit SCLK=P1^4;
sbit RST=P1^6;
sbit ACC0=ACC^0;//设置累加器
sbit ACC7=ACC^7;
//按键
sbit key1=P3^2;
sbit key2=P3^3;
sbit key3=P3^4;
void delay2(uint s)//延时,用于温度程序部分
{
while(s--);//区分i,用s表示
}
void delay(uint z)//延时函数
{
uint x,y;
for(x=z;x>0;x--)
for(y=110;y>0;y--);
}
void writecom(uchar com)//写入指令函数
{
rs=0;
rw=0;
P0=com;
delay2(1);
en=1;
delay2(1);
en=0;
}
void writedata(uchar dat)//写入数据函数
{
rs=1;
rw=0;
P0=dat;
delay2(1);
en=1;
delay2(1);
en=0;
}
void print(uchar a3,uchar *str)//写字符串函数
{
writecom(a3