电子万年历实验 Beta20.docx

上传人:b****6 文档编号:3714957 上传时间:2022-11-24 格式:DOCX 页数:25 大小:346.32KB
下载 相关 举报
电子万年历实验 Beta20.docx_第1页
第1页 / 共25页
电子万年历实验 Beta20.docx_第2页
第2页 / 共25页
电子万年历实验 Beta20.docx_第3页
第3页 / 共25页
电子万年历实验 Beta20.docx_第4页
第4页 / 共25页
电子万年历实验 Beta20.docx_第5页
第5页 / 共25页
点击查看更多>>
下载资源
资源描述

电子万年历实验 Beta20.docx

《电子万年历实验 Beta20.docx》由会员分享,可在线阅读,更多相关《电子万年历实验 Beta20.docx(25页珍藏版)》请在冰豆网上搜索。

电子万年历实验 Beta20.docx

电子万年历实验Beta20

电子万年历实验

实验要求:

在LCD(12864或者1602)上显示:

年月日星期时间

可以自由修改显示的年月日星期时间

实验需求:

硬件需求:

1.需要按键做初始化等需求

2.需要LED作为显示输出。

2需要一款硬件作为实时时钟

器件选型

DS1302  实时时钟芯片,三线接口,带涓流充电。

DS1307  实时时钟芯片,I2C接口。

DS1337  实时时钟芯片,I2C接口,带两个日历闹钟。

PCF8563  实时时钟芯片,I2C接口,带中断输出。

PCF8583  实时时钟芯片,I2C接口,带中断输出,内置的32.768KHz振荡器,256个字节RAM,但性价比较差。

DS1302

DS1302是DALLAS公司推出的涓流充电时钟芯片内含有一个实时时钟/日历和31字节静态RAM

可通过简单的串行接口与单片机进行通信

可提供:

--秒分时日日期月年的信息

--每月的天数和闰年的天数可自动调整

--可通过AM/PM指示决定采用24或12小时格式

--保持数据和时钟信息时功率小于1mW

选型结论:

LCD:

12864

键盘:

4*4矩阵键盘

实时时钟芯片:

DS1302

结构框图

DS1302引脚

X1X232.768KHz晶振管脚

GND地

CE复位脚

I/O数据输入/输出引脚

SCLK串行时钟

Vcc1,Vcc2电源供电管脚

各引脚的功能为:

Vcc1:

主电源;Vcc2:

备份电源。

当Vcc2>Vcc1+0.2V时,由Vcc2向DS1302供电,当Vcc2

SCLK:

串行时钟,输入,控制数据的输入与输出;

I/O:

三线接口时的双向数据线;

CE:

输入信号,在读、写数据期间,必须为高。

该引脚有两个功能:

第一,CE开始控制字访问移位寄存器的控制逻辑;其次,

CE提供结束单字节或多字节数据传输的方法。

参考电路:

如上图所示:

DS1302与单片机的连接也仅需要3条线:

CE引脚、SCLK串行时钟引脚、I/O串行数据引脚,Vcc2为备用电源,外接32.768kHz晶振,为芯片提供计时脉冲。

实际电路:

Vcc_5V:

为电路中的主电源;Vcc2,也就是BT1为备份电源。

当Vcc2>Vcc1+0.2V时,

由Vcc2向DS1302供电,当Vcc2

CLK和I/O虽然和IIC总线接在一条引脚上,但DS1302其实并不是使用IIC总线,而是一种三线式总线,

DS1302内部结构:

DS1302内部包括:

Powercontrol:

电源控制模块

Inputshiftregisters:

输入移位寄存器

Commandandcontrollogic:

通讯与逻辑控制器

Oscillatoranddivider:

晶体振荡器及分频器

DS1302的内部主要组成部分虽然有:

移位寄存器、控制逻辑、振荡器、实时时钟以及RAM。

虽然数据分成两种,但是对单片机的程序而言,其实是一样的,就是对特定的地址进行读写操作。

DS1302控制字:

控制字的最高有效位(位7)必须是逻辑1,如果它为0,则不能把数据写入到DS1302中。

位6:

如果为0,则表示存取日历时钟数据,为1表示存取RAM数据;

位5至位1(A4~A0):

指示操作单元的地址;

位0(最低有效位):

如为0,表示要进行写操作,为1表示进行读操作。

控制字总是从最低位开始输出。

在控制字指令输入后的下一个SCLK时钟的上升沿时,数据被写入DS1302,数据输入从最低位(0位)开始。

同样,在紧跟8位的控制字指令后的下一个SCLK脉冲的下降沿,读出DS1302的数据,读出的数据也是从最低位到最高位。

DS1302时序:

如图,所示

CE输入驱动高启动所有的数据传输。

CE输入有两个功能。

首先,CE打开控制逻辑,允许访问的移位寄存器的地址/命令序列。

其次,CE提供了一个终止单字节或多字节数据传输方法。

一个时钟周期是由一个下降沿之后的上升沿序列。

对于数据传输而言,数据必须在有效的时钟的上升沿输入,在时钟的下降沿输出。

如果CE为低,所有的I/O引脚变为高阻抗状态,数据传输终止。

对于数据输入:

开始的8个SCLK周期,输入写命令字节,数据字节在后8个SCLK周期的上升沿输入。

数据输入位0开始。

对于数据输出:

开始的8个SCLK周期,输入一个读命令字节,数据字节在后8个SCLK周期的下降沿输出。

注意,第一个数据字节的第一个下降沿发生后,命令字的最后一位被写入(Notethatthefirstdatabittobetransmittedoccursonthefirstfallingedgeafterthelastbitofthecommandbyteiswritten.),命令字节的最后一位被写入。

当CE仍为高时。

如果还有额外的SCLK周期,DS1302将重新发送数据字节,这使DS1302具有连续突发读取的能力。

DS1302驱动程序分析

/************************************************

*名称:

ucharDS1302Read()

*说明:

先写地址,后读数据

*功能:

从cmd相应地址中读取一个字节的数据

*调用:

DS1302WriteByte(),DS1302ReadByte()

*输入:

cmd:

要写入的控制字节

*输出:

dat:

读取的数据

*************************************************/

ucharDS1302Read(ucharcmd)

{

uchardat;

RST=0;//初始CE线置为0

SCLK=0;//初始时钟线置为0

RST=1;//初始CE置为1,传输开始

DS1302WriteByte(cmd);//传输命令字,要读取的时间/日历地址

dat=DS1302ReadByte();//读取要得到的时间/日期

SCLK=1;//时钟线拉高

RST=0;//读取结束,CE置为0,结束数据的传输

returndat;//返回得到的时间/日期

}

/************************************************

*名称:

DS1302Write

*说明:

先写地址,后写数据

*功能:

向cmd相应地址中写一个字节的数据

*调用:

DS1302WriteByte()

*输入:

cmd:

要写入的控制字,dat:

要写入的数据

*输出:

*************************************************/

voidDS1302Write(ucharcmd,uchardat)

{

RST=0;//初始CE线置为0

SCLK=0;//初始时钟线置为0

RST=1;//初始CE置为1,传输开始

DS1302WriteByte(cmd);/传输命令字,要写入的时间/日历地址

DS1302WriteByte(dat);//写入要修改的时间/日期

SCLK=1;//时钟线拉高

RST=0;//读取结束,CE置为0,结束数据的传输

}

/************************************************

*名称:

DS1302WriteByte

*说明:

*功能:

写入8bit数据

*调用:

delayus()

*输入:

dat:

要写入的数据

*输出:

*************************************************/

voidDS1302WriteByte(uchardat)

{

uchari;

SCLK=0;//初始时钟线置为0

delayus

(2);

for(i=0;i<8;i++)//开始传输8个字节的数据

{

SDA=dat&0x01;//取最低位,注意DS1302的数据和地址都是从最低位开始传输的

delayus

(2);

SCLK=1;//时钟线拉高,制造上升沿,SDA的数据被传输

delayus

(2);

SCLK=0;//时钟线拉低,为下一个上升沿做准备

dat>>=1;//数据右移一位,准备传输下一位数据

}

}

/************************************************

*名称:

DS1302ReadByte()

*说明:

*功能:

读取8bit的数据

*调用:

delayus()

*输入:

*输出:

dat:

读取的数据

*************************************************/

ucharDS1302ReadByte()

{

uchari,dat;

delayus

(2);

for(i=0;i<8;i++)

{

dat>>=1;//要返回的数据左移一位

if(SDA==1)//当数据线为高时,证明该位数据为1

dat|=0x80;//要传输数据的当前值置为1,若不是,则为0

SCLK=1;//拉高时钟线

delayus

(2);

SCLK=0;//制造下降沿

delayus

(2);

}

returndat;//返回读取出的数据

}

 

对DS1302的操作就是对其内部寄存器的操作,DS1302内部共有12个寄存器,其中有:

7个寄存器与日历、时钟相关,存放的数据位为BCD码形式。

此外,DS1302还有年份寄存器、控制寄存器、充电寄存器、时钟突发寄存器及与RAM相关的寄存器等。

时钟突发寄存器可一次性顺序读写除充电寄存器以外的寄存器。

如下所示:

DS1302数据地址和传输格式

如图所示,时钟日历包含在7个读/写寄存器内,读/写寄存器中的数据是二——十进制的BCD码。

秒寄存器的BIT7定义为时间暂停位,当BIT1为1时,时钟振荡器停止工作,DS1302进入低功耗模式,电源消耗小于100微安,当BIT1为0时,时钟振荡器启动,DS1302正常工作。

小时寄存器的BIT7定义为12或24小时工作模式选择位,当BIT7为高时,为12小时工作模式,此时BIT5为AM/PM位,低电平标示AM,高电平标示PM,在24小时模式下,BIT5为第二个10小时位标示(20~23时)。

写保护寄存器的BIT7:

WP是写保护位,工作时,出WP外的其他位都置为0,对时钟/日历寄存器或RAM进行写操作之前,WP必须为0,当WP为高电平的时候,不能对任何时钟/日历寄存器或RAM进行写操作。

关于突发模式(burstmode或称多字节传输模式),突发模式可以指定任何的时钟/日历或者RAM寄存器为突发模式,和以前一样,第6位指定时钟或RAM而0位指定读或写。

突发模式的实质是指一次传送多个字节的时钟信号和RAM数据。

如下图所示

在时钟/日历寄存器中的9至31和在RAM寄存器的地址31不能存储数据。

突发模式的读取或写入从地址的位0开始。

如下程序所示:

/*---------------------------------------------------------------------------------------------------

函数名称:

DS1302_NReadRam(unsignedchar*rstr)

函数功能:

多字节突发模式读RAM,

DS1302_NRRAM一次可进行31个片内RAM单元读

输入参数:

*rstr:

存放读到的N个数据

输出参数:

------------------------------------------------------------------------------------------------------*/

voidDS1302_burst_Read(unsignedchar*rstr)

{

unsignedchari;

RST=0;

SCLK=0;

RST=1;//CE拉高,传输开始

DS1302_WriteByte(0XFF);//写0XFF,多字节突发方式读RAM具体细节见上一节

for(i=0;i<31;i++)//连续读取个31字节

{

*rstr=DS1302ReadByte(address);//此处的ADDRESS指的是你需要进行连续读取的地址

rstr++;

}

RST=0;//CE信号拉低,传输结束

CLK=1;

}

/*---------------------------------------------------------------------------------------------------------

函数名称:

DS1302_NReadRam(unsignedchar*rstr)

函数功能:

多字节突发模式写RAM,

DS1302_NRRAM一次可进行31个片内RAM单元写

输入参数:

*wstr:

要被写入的N个数据

输出参数:

---------------------------------------------------------------------------------------------------------------*/

voidDS1302_burstWrite(unsignedchar*wstr)

{

unsignedchari;

unsignedchar*tmpstr;

tmpstr=wstr;

DS1302Write(0x8e,0x00);//写保护关

RST=0;

SCLK=0;

RST=1;

DS1302_WriteByte(0XFE);//写0XFE,多字节突发方式写RAM,具体细节见上节for(i=0;i<31;i++)//连续写入31字节

{

DS1302_WriteByte(*tmpstr);

tmpstr++;

}

RST=0;

SCLK=1;

DS1302Write(0x8e,0x80);//开写保护

}

此寄存器为DS1302充电模式控制位,结构如下所示

TCS位:

涓流充电选择位(BIT4至7)控制涓流充电器的选择。

为防止偶然的因素使其工作,只有1010模式才能使涓流充电器工作。

所有其它的模式将禁止涓流充电。

在DS1302上电后。

涓流充电将被禁止。

DS位:

该二极管选择(BIT2和3)选择是一个二极管还是两个二极管之间在Vcc2和Vcc1连接。

如果DS为01,则选择一个二极管。

如果DS为10,则两个二极管被选中。

如果DS为00或11,充电器被禁止,与TCS无关。

RS位(BIT0和1):

选择是在Vcc2和Vcc1之间的连接电阻。

电阻的选择如下所示:

程序流程设计

几个数组,用来定义要显示的汉字信息

unsignedcharChinese_1[17]={0xc4,0xea,0xd4,0xc2,0xc8,0xd5,0xca,0xb1,0xb7,0xd6,0xc3,0xeb,0xd0,0xc7,0xc6,0xda,''};//年月日时分秒星期

unsignedcharChinese_2[15]={0xd2,0xbb,0xb6,0xfe,0xc8,0xfd,0xcb,0xc4,0xce,0xe5,0xc1,0xf9,0xcc,0xec,''};//一二三四五六天

unsignedcharCursor[6]={0x81,0x83,0x85,0x90,0x92,0x94};//定义光标移动的位置

主函数部分

主函数部分只需要按照流程图的需要调用各个模块即可/************************************************

*名称:

voidmain()

*说明:

*功能:

读取8bit的数据

*调用:

delayms()

*输入:

*输出:

dat:

读取的数据

*************************************************/

voidmain()

{

Delayms(50);

EX1=1;//外部中断开

EA=1;//全局中断开

Initialize_device();//初始化CH452LCDDS1302等器件

while

(1)//while中的值只循环显示小时,分钟,秒这几个常变量,有其他需要,可以继续添加

{

Display_Clock();//显示你需要从DS1302中读取的值

Delayms(500);

}

};

}

DS1302的初始化部分

只需要调用一次,写入一个初始值即可

/************************************************

*名称:

voidInit_DS1302(void)

*说明:

给1302写入一个初始的值

*功能:

写入日期,和时钟的值

*调用:

DS1302Write()

*输入:

*输出:

*************************************************/

voidInit_DS1302(void)

{

DS1302Write(0x8e,0x00);//写保护关

DS1302Write(DS1302_SECOND_WRITE,0x00);//初始秒值为0

DS1302Write(DS1302_MINUTE_WRITE,0x20);//初始分钟值为0

DS1302Write(DS1302_HOUR_WRITE,0x09);//初始为24小时模式初始时间为0点

DS1302Write(DS1302_DAY_WRITE,0x25);//2011年1月1日星期6

DS1302Write(DS1302_MONTH_WRITE,0x12);

DS1302Write(DS1302_YEAR_WRITE,0x10);

DS1302Write(DS1302_WEEK_WRITE,0x06);

DS1302Write(0x90,0x01);//充电

DS1302Write(0xc0,0xf0);//初始化一次标示

DS1302Write(0x8e,0x80);

}

/************************************************

*名称:

Initialize_device()

*说明:

*功能:

初始化实验用到的器件

*调用:

delayms(),Init_1602();Dispaly_Menu();Init8259a();

*输入:

*输出:

*************************************************/

VoidInitialize_device()

{

CH452_Write(CH452_SYSON2);//初始化CH452

Init_1602();//初始化LCD

Init8259a();//初始化8259a

Dispaly_Menu();//显示年月日等文字

Delayms(50);

//Init_DS1302();//初始化DS1302,只需要执行一次,设定好后,不需要再次执行

}

由于DS1302的很多数值都是十位数,所以需要把十位数分成2次在LCD12864上显示

//----------------------------------------------------------------

//函数名称:

voidSplit_display()

//函数功能:

把一个十位数分二次显示至传递来的位置

//入口参数:

unsignedcharaddress

//出口参数:

//-----------------------------------------------------------------

voidSplit_display(unsignedcharaddress)

{

unsignedchari;

i=DS1302Read(address);//读取十位

i=i/16+'0';

Write_data(i);//显示十位

Delayms(3);

i=DS1302Read(address);//读取个位

i=i%16+'0';

Write_data(i);//显示个位

Delayms(5);

}

屏幕显示部分

显示屏幕上的文字信息

显示效果为:

20XX年XX月XX日

XX时XX分XX秒

星期X

 

//----------------------------------------------------------------

//函数名称:

voidDispaly_Menu()

//函数功能:

显示屏幕上的所有元素

//入口参数:

//出口参数:

//-----------------------------------------------------------------

voidDispaly_Menu()

{

Write_com(0x01);

Delayms(100);

Write_com(0x80);

Delayms(100);

Write_data('2');

Delayms(5);

Write_data('0');

Delayms

(1);

 

Split_display(DS1302_YEAR_READ);//显示年份

Write_data(Chinese_1[0]);//显示“年”

Delayms(3);

Write_data(Chinese_1[1]);

Delayms(3);

 

Split_display(DS1302_MONTH_READ);//显示月份

Write_data(Chinese_1[2]);//显示“月”

Delayms(3);

Write_data(Chinese_1[3]);

Delayms(3);

 

Split_display(DS1302_DAY_READ);//显示日期

Write_data(Chinese_1[4]);//显示“日”

Delayms(3);

Write_data(Chinese_1[5]);

Delayms(3);

Write_data(Chinese_1[16]);

Delayms(3);

展开阅读全文
相关资源
猜你喜欢
相关搜索

当前位置:首页 > 经管营销 > 财务管理

copyright@ 2008-2022 冰豆网网站版权所有

经营许可证编号:鄂ICP备2022015515号-1