资源描述
课程设计报告
设计课题: 电子钟 (串口)
专业班
学生姓名:
指导教师:
设计时间:
电子钟(二)
一、 课程设计目的:
通过对设计电子钟的设计了解89C51,PCF8563及液晶显示的工作原理与编程方法.
二、 课程设计要求:
通过单片机控制应用时钟芯片8563和串口液晶,实现电子钟。要求显示年、月、日、时、分、秒。
三、 系统分析与设计:
1:系统总体设计
本实验中的器件:PCB开发板一块;
89C51模块;
PCF8563时钟芯片一片;
串口液晶一个;
MAX232芯片一片;
该电子钟分为数据产生,数据传输和数据显示三个部分.其中数据产生的是PCF8563模块,数据传输的是89C52和74HC573模块。数据显示的是在串口液晶上。
89C51模块:实验中利用89C52模块的P3.4及P3.5引脚向PCF8563的6脚和5脚即SCL和SDA传输数据,来对PCF8563进行初始化,在利用采来的数据将数据地址锁存在74HC573内并在串口液晶上显示。
PCF8563模块:该模块是时钟芯片,是低功耗的CMOS时钟芯片,其所有的地址和数据都是通过I2C总线接口串行传递的。每次读写数据后,内嵌的地址寄存器会自动产生增量。本实验就是利用该芯片传来的数据进行显示。
串口液晶LCD:该液晶有两行地址,将要显示的数据分别放在这两行中进行显示。
2:系统详细设计
系统总体框架:系统的总体电路图如图1所示:
图1 系统电路图
图2 74HC573与单片机连接图 图3 GAL16V8与单片机连接图
图4 单片机与外接器件连接图
3:系统流程图:
开始
8563初始化,LCD初始化
向8563写入初始化值
读回数据并锁存
将数据送入串口液晶
显示时间
4:原程序清单
#include<intrins.h>
#include<absacc.h>
#include<REG51.h>
#define uchar unsigned char
#define uint unsigned int
#define ulong unsigned long
#include <Dis_slcd.h>
#define PCF8563_W 0xa2
#define PCF8563_R 0xa3
#define WRADDR 0x00
#define RDADDR 0x02
#define _Nop() _nop_();
/*********************************/
#define PCF8563_CONTROL_STATE0 0x00 //控制状态寄存器1
#define PCF8563_CONTROL_STATE1 0x01 //控制状态寄存器2
#define PCF8563_CLKOUT 0x0d //CLKOUT频率寄存器
#define PCF8563_TIMER_CONTROL 0x0e //定时器控制寄存器
#define PCF8563_TIMER_DATA 0x0f //定时器倒计数数值寄存器
#define PCF8563_MINUTE 0x02 //秒
#define PCF8563_SECOND 0x03 //分
#define PCF8563_HOUR 0x04 //时
#define PCF8563_DATE 0x05 //日
#define PCF8563_WEEK 0x06 //星期
#define PCF8563_MONTH 0x07 //月/世纪
#define PCF8563_YEAR 0x08 //年
#define PCF8563_MINUTE_ALARM 0x09 //分钟报警
#define PCF8563_SECOND_ALARM 0x0a //小时报警
#define PCF8563_YEAR_ALARM 0x0b //日报警
#define PCF8563_WEEK_ALARM 0x0c //星期报警
uchar b[16];
/***************************************/
uchar code CS1[2]={
0x00,
0x28
};
uchar code CS2[2]={
0x12,
0x02
};
uchar code CLKOUT[4]={
0x80,
0x81,
0x82,
0x83
};
/*************************************/
sbit SDA=P3^5;
sbit SCL=P3^4;
/*****************************/
sbit bflag=ACC^7;
uchar FUNC(uchar a,uchar b);//右循环n,m位
/************************************/
bit ack;
//起动IIC
void Start_I2c()
{
SDA=1; /*发送起始条件的数据信号*/
_Nop();
SCL=1;
_Nop(); /*起始条件建立时间大于4.7us,延时*/
_Nop();
_Nop();
_Nop();
_Nop();
SDA=0; /*发送起始信号*/
_Nop(); /* 起始条件锁定时间大于4μs*/
_Nop();
_Nop();
_Nop();
_Nop();
SCL=0; /*钳住I2C总线,准备发送或接收数据 */
_Nop();
_Nop();
}
/**********************************/
//停止IIC
void Stop_I2c()
{
SDA=0; /*发送结束条件的数据信号*/
_Nop(); /*发送结束条件的时钟信号*/
SCL=1; /*结束条件建立时间大于4μs*/
_Nop();
_Nop();
_Nop();
_Nop();
_Nop();
SDA=1; /*发送I2C总线结束信号*/
_Nop();
_Nop();
_Nop();
_Nop();
}
//写1BYTE数据(上传数据、释放IIC、ack确认)
void SendByte(uchar c)
{
uchar idata BitCnt;
for(BitCnt=0;BitCnt<8;BitCnt++) /*要传送的数据长度为8位*/
{
if((c<<BitCnt)&0x80)SDA=1; /*判断发送位*/
else SDA=0;
_Nop();
SCL=1; /*置时钟线为高,通知被控器开始接收数据位*/
_Nop();
_Nop(); /*保证时钟高电平周期大于4μs*/
_Nop();
_Nop();
_Nop();
SCL=0;
}
_Nop();
_Nop();
SDA=1; /*8位发送完后释放数据线,准备接收应答位*/
_Nop();
_Nop();
SCL=1;
_Nop();
_Nop();
_Nop();
if(SDA==1)ack=0;
else ack=1; /*判断是否接收到应答信号*/
SCL=0;
_Nop();
_Nop();
}
//读1BYTE数据(置输入状态、读数据)
uchar RcvByte()
{
uchar idata retc=0;
uchar idata BitCnt;
SDA=1; /*置数据线为输入方式*/
for(BitCnt=0;BitCnt<8;BitCnt++)
{
_Nop();
SCL=0; /*置时钟线为低,准备接收数据位*/
_Nop();
_Nop(); /*时钟低电平周期大于4.7μs*/
_Nop();
_Nop();
_Nop();
SCL=1; /*置时钟线为高使数据线上数据有效*/
_Nop();
_Nop();
retc=retc<<1;
if(SDA==1)retc=retc+1; /*读数据位,接收的数据位放入retc中 */
_Nop();
_Nop();
}
SCL=0;
_Nop();
_Nop();
return(retc);
}
//确认IIC(输入参数为0表示确认、1表示不确认)
void Ack_I2c(bit a)
{
if(a==0)SDA=0; /*在此发出应答或非应答信号 */
else SDA=1;
_Nop();
_Nop();
_Nop();
SCL=1;
_Nop();
_Nop(); /*时钟低电平周期大于4μs*/
_Nop();
_Nop();
_Nop();
SCL=0; /*清时钟线,钳住I2C总线以便继续接收*/
_Nop();
_Nop();
}
//指定地址写命令/数据(ack==0 --> 失败)
bit ISendByte(uchar sla,uchar c)
{
Start_I2c(); //启动总线
SendByte(sla); //发送器件地址
if(ack==0)return(0);
SendByte(c); //发送数据
if(ack==0)return(0);
Stop_I2c(); //结束总线
return(1);
}
//指定地址写命令/数据(地址=从地址+子地址,no为从指针*s的个数)
bit ISendStr(uchar sla,uchar suba,uchar *s,uchar no)
{
uchar idata i;
Start_I2c(); /*启动总线*/
SendByte(sla); /*发送器件地址*/
if(ack==0)return(0);
SendByte(suba); /*发送器件子地址*/
if(ack==0)return(0);
// reset_wdt();
for(i=0;i<no;i++)
{
SendByte(*s); /*发送数据*/
if(ack==0)return(0);
s++;
}
Stop_I2c(); /*结束总线*/
return(1);
}
//指定地址读状态/数据(地址=从地址+子地址,no为从指针*s的个数)
bit IRcvStr(uchar sla,uchar suba,uchar *s,uchar no)
{
uchar idata i;
Start_I2c(); /*启动总线*/
SendByte(sla); /*发送器件地址*/
if(ack==0)return(0);
SendByte(suba); /*发送器件子地址*/
if(ack==0)return(0);
Start_I2c();
SendByte(sla+1);
if(ack==0)return(0);
for(i=0;i<no-1;i++)
{
*s=RcvByte(); /*发送数据*/
Ack_I2c(0); /*发送应答位*/
s++;
}
*s=RcvByte();
Ack_I2c(1); /*发送非应答位*/
Stop_I2c(); /*结束总线*/
return(1);
}
void main()
{ uchar n,c,d;
uchar a[16],b[7];
uchar init_timer_buf[7]={0x30,0x20,0x00,0x20,0x04,0x01,0x06};
ISendByte(0xa2,c);
ISendStr(0xa2,0x02,init_timer_buf,0x07);
while(1)
{ IRcvStr(0xa2,0x02,b,0x07);
LCD_CLOCK=1;
//****读秒并处理****//
a[0]=(b[0]&0x0f);
b[0]=b[0]>>4;
a[1]=(b[0]&0x0f);
a[2]=34;
//****读分并处理****//
a[3]=(b[1]&0x0f);
b[1]=b[1]>>4;
a[4]=(b[1]&0x0f);
a[5]=34 ;
//****读时并处理****//
a[6]=(b[2]&0x0f);
b[2]=b[2]>>4;
a[7]=(b[2]&0x03);
//****读日并处理****//
a[8]=(b[3]&0x0f);
b[3]=b[3]>>4;
a[9]=(b[3]&0x03);
a[10]=34;
//****读月并处理****//
a[11]=(b[5]&0x0f);
b[5]=b[5]>>4;
a[12]=(b[5]&0x01);
a[13]=34;
//****读年并处理****//
a[14]=(b[6]&0x0f);
b[6]=b[6]>>4;
a[15]=(b[6]&0x0f);
for(n=0;n<8;n++)
{ d=a[7-n];
display_buff[n]=mem[d];
}
display_slcd(8);
delay_ms(0x80);
if(a[0]==5)
{for(n=0;n<8;n++)
{ d=a[15-n];
display_buff[n]=mem[d];
}
display_slcd(8);
delay_ms(0x80);
delay_ms(0xff);
delay_ms(0xff);
delay_ms(0xff);
delay_ms(0xff);
delay_ms(0xff);
delay_ms(0xff);
}
}
}
四、系统调试过程中出现的问题
1:液晶最初是无显示的,必须通过调节电位器才能显示.GAL在显示是出现了问题,对其进行烧制.
2:在显示年月时由于对其有效位未理解透彻,因而出现了显示乱码,在经过改正后得到了结果.
五、系统运行报告
对程序运行下载到单片机后,串口液晶屏上第一行显示出“DATA/2003/12/4。第二行显示TIME/19:59:50。
六、总结
1:在对时钟芯片8563的数据读回时未理解程序的读回命令,其实就是读回命令将数据读回对其进行显示就可以了,尝试一个数进行显示,最终将数据显示在了LCD上。
2:因为串口液晶只能显示ASII码,因此对其进行转换是必须的。在做时直接进行显示,则显示出乱码。经过查资料修正后得出了正确结果。
3:通过本次实验,加深了对电路的整体设计思想。对51单片机的设计流程有了一定的了解。对硬件的调试与软件的修改掌握了一些技巧。对51单片机的C程序设计有了一定的掌握。
七、参考书目
1:马忠梅,《单片机的c语言应用程序设计》,北京航空航天大学出版社
2:王福瑞,《单片微机测控系统设计大全》,北京航空航天大学出版社
3:徐爱钧,《单片机高级语言C51应用程序设计》,电子工业出版社
4:杨振江,《智能仪器与数据采集系统中的新器件及应用》,西安电子科技大学出版社
展开阅读全文