《电子技术应用》
您所在的位置:首页 > 嵌入式技术 > 解决方案 > DS12C887时钟日历芯片

DS12C887时钟日历芯片

2015-10-15
关键词: DS12C887 时钟芯片

DS12C887时钟日历芯片,是由美国 DALLAS公司生产的新型时钟日历芯片,采用CMOS技术制成。芯片采用24引脚双列直插式封装,内部集成晶振、振荡电路、充电电路和可充电锂电池,组 成一个加厚的集成电路模块,在没有外部电源的情况下可工作10年。具有良好的微机接口、精度高、外围接口简单、工作稳定可靠等优点,可广泛使用于各种需要 较高精度的实时场合。

一、器件特性

·可计算到2100年前的秒、分、小时、星期、日期、月、年七种日历信息并带闰年补偿;
·自带晶体振荡器和锂电池。在没有外部电源的情况下可工作10年;
·对于一天内的时间记录,有12小时制和24小时制两种模式。在12小时制模式中,用AM和PM区分上午和下午;
·可选用夏令时模式
·时间表示方法有两种:一种用二进制数表示,一种用BCD码表示;
·DS12C887中带有128字节RAM,其中11字节用来存储时间信息,4字节RAM用来存储DS12C887的控制信息,称为控制寄存器,113字节RAM供用户使用;
·数据/地址总线复用
·用户可编程以实现多种方波输出
·可应用于MOTOROLA和INTEL两种种线。——我这里只阐述INTEL总线实现方法
·三种可编程中断:定闹中断、时钟更新结束中断、周期性中断

DS12C887各引脚的功能说明

GND、VCC:直流电源,其中VCC接+5V输入,GND接地。
当VCC输入为+5V时,用户可以访问DS12C887内RAM中的数据,并可对其进行读、写操作;
当VCC输入小于+4.25V时,禁止用户对内部RAM进行读、写操作,此时用户不能正确获取芯片内的时间信息;
当VCC输入小于+3V时,DS12C887会自动将电源切换到内部自带的锂电池上,以保证内部的电路能够正常工作。

MOT:模式选择引脚
DS12C887有两种工作模式,即Motorola模式和Intel模式。
当MOT接VCC时,选用的工作模式是Motorola模式;
当MOT接GND或不接时,选用的是Intel模式。本文主要讨论Intel模式。

SQW:方波输出引脚
当供电电压VCC大于4.25V时,SQW引脚可进行方波输出,此时用户可以通过对控制寄存器编程来得到13种方波信号的输出。

AD0~AD7:复用地址/数据总线
该总线采用时分复用技术,在总线周期的前半部分,出现在AD0~AD7上的是地址信息,可用以选通DS12C887内的RAM;总线周期的后半部分出现在AD0~AD7上的是数据信息。

AS:地址选通输入引脚
在进行读写操作时,AS的上升沿将AD0~AD7上出现的地址信息锁存到DS12C887上,而下一个下降沿清除AD0~AD7上的地址信息,不论是否有效,DS12C887都将执行该操作。

DS/RD:数据选择或读输入引脚
该引脚有两种工作模式:
Motorola工作模式中,每个总线周期的后一部分的DS为高电平,被称为数据选通。在读操作中,DS的上升沿使DS12C887将内部数据送往总线AD0~AD7上,以供外部读取。在写操作中,DS的下降沿将使总线 AD0~AD7上的数据锁存在DS12C887中;
Intel工作模式中,DS被称作RD。该引脚是读允许输入脚,即Read Enable。是读(RD)信号输入端。当他有效时表示DS12C887正往总线输出数据。RD信号线在存储器芯片上被称作OE信号线。

R/W:读/写输入端
该引脚也有2种工作模式:
Motorola工作模式中,该引脚的作用是区分进行的是读操作还是写操作,当R/W为高电平时为读操作,R/W为低电平时为写操作;
Intel工作模式中,此时该作为写允许输入,即Write Enable。是写(WR)信号输入端。

CS:片选输入,低电平有效。

IRQ:中断请求输入,低电平有效,该引脚有效对DS12C887内的时钟、日历和RAM中的内容没有任何影响,仅对内部的控制寄存器有影响,在典型的应用中,RESET可以直接接VCC,这样可以保证DS12C887在掉电时,其内部控制寄存器不受影响。

RESET:复位端
在典型的应用中,RESET直接接VCC

NC:空引脚

下面讲解一下DS12C887的控制和状态寄存器。

DS12C887有四个控制和状态寄存器:A、B、C、D

寄存器A

更新位UIP:用来标志芯片是否即将进行更新。
当UIP位为1时,表示芯片正处于更新周期或即将开始更新周期。此时不准读/写时标寄存器;
当它为0时,表示在至少244us后才开始更新周期(即在这244us内,芯片不会更新)。此时,时钟、日历和闹钟信息可以通过读写相应的字节获得和设置。
UIP位为只读位且不受复位信号(RESET)的影响。通过把寄存器B中的SET位设置为1,可以禁止更新并将UIP位清0。

大头爸爸:因此,在读/写前应该检测UIP位。比如在1602液晶上显示秒


while(从DS12C887读(0x0A)&0x80);//这句意思就是如果UIP位为1,则等待。为0则退出
秒值=从DS12C887读(0)//读秒数据
向1602写入秒值

DV0,DV1,DV2

这3位是用来开关晶体振荡器和复位分频器。
当[DV0 DV1 DV2]=[010]时,晶体振荡器开启并且保持时钟运行;
当[DV0 DV1 DV2]=[01X]时,晶体振荡器开启,但分频器保持复位状态。<---不太明白,如果设置01X时,有什么作用呢?

RS3,RS2,RS1,RS0

作用:
1、设置周期中断允许位(PIE);
2、设置方波输出允许位(SQWE);
3、两位同时设置为有效并且设置频率;
4、全部禁止。
下表列出了可通过RS寄存器选择的周期中断的频率和方波的频率。这四个可读写的位不受复位信号的影响。

寄存器B

SET:当该位为0时,芯片处于正常工作状态,每秒产生一个更新周期来更新时标寄存器;该位为1时,芯片停止工作,程序在此期间可初始化芯片的各个时标寄存器。
SET位可读写,并不会受到复位信号的影响。

PIE——周期中断
当PIE=0:禁止周期中断输出到IRQ;
当PIE=1:允许周期中断输出到IRQ。

AIE——闹钟中断
当AIE=0:禁止闹钟中断输出到IRQ;
当AIE=1:允许闹钟中断输出到IRQ。

UIE——更新结束中断
当UIE=0:禁止更新结束中断输出到IRQ;
当UIE=1:允许更新结束中断输出到IRQ。
此位在复位或设置SET为高时清0

SQWE——方波输出允许位
当SQWE=0:SQW脚保持低电平;
当SQWE=1:按寄存器A输出 速率选择位 所确定的频率方波。

DM——格式选择位
DM=0:BCD格式;
DM=1:二进制格式。
此位不受复位信号影响

24/12——小时模式设置位
为1—24小时制;为0—12小时制

DSE——夏令时允许标志
DSE=1,夏令制设置有效,夏时制结束可自动刷新恢复时间;DES=0,无效。
夏令时:在四月的第一个星期日的1:59:59AM,时钟调到3:00:00AM;在十用的最后一个星期日的1:59:59AM,时钟调到1:00:00AM。

寄存器C

该寄存器的特点是:程序访问该寄存器或复位后,该寄存器的内容将自动清0,从而使IRQF标志位变为高电平(大头爸爸:是低电平吧?不理解这句),否则,芯片将无法向CPU申请下一次中断。

2010-5-14 16:18 上次将本文章打印出来,昨晚在看一遍时,对上面红色部分重新理解内容如下:

IRQF为高电平时,引脚变为低电平引起中断申请。假设,我开放闹钟中断,寄存器B中的AIE需要置 1,当 当前时间与所设置的闹钟时间吻合时,寄存器C中的AF位被硬件置1(详见下面的:更新周期的基本功能),此时根据IRQF的逻辑表达 式:IRQF=PF·PIE+AF·AIE+UF·UIE可得知:IRQF的值为1,当IRQF位变为1时,引脚变为低电平引起中断申请(如果采用外部中断1,则初始化时使IT1=1,通过他的下降沿来引起中断)。

在中断申请中,要读一次寄存器C,目的就是使寄存器C中的内容自动清0。IRQF为0,则不再引起中断申请。目的就是使下一次闹钟时间与当前时间符合时,可以再次申请中断。

另一个理解:如果在中断服务程序中不读寄存器C,即,不使寄存器C中的各位清0的话,那么就会不断的申请中断。因为IRQF值为1。——我这个理解未做测试,以后将测试结果放上。

IRQF:中断申请标志位。该位的逻辑表达式为:IRQF=PF·PIE+AF·AIE+UF·UIE。当IRQF位变为1时,引脚变为低电平引起中断申请。

在有以下情况中的一种或几种发生时,中断请求标志位IRQF置高:

PF=PIE=1
AF=AIE=1
UF=UIE=1
IRQF=PF·PIE+AF·AIE+UF·UIE
IRQF一旦为高,IRQ引脚输出低。

PF:周期中断标志位。
AF:闹钟中断标志位。
UF:更新周期结束中断标志位。

寄存器C的低三位:未定义的保留位。不能写入,读出值始终为0。

寄存器D

寄存器D为只读寄存器。

当VRT=0时表示内置电池能量耗尽,此时RAM中的数据正确性无法保证。低6位无用,只读,读出值恒为0。

DS12C887的中断和更新周期

DS12C887处于正常工作状态时,每秒钟将产生一个更新周期。芯片片于更新周期的标志是寄存器A中的UIP位为1。在更新周期内,芯片内部时标寄存器的数据处于更新阶段。所以,在这个阶段微处理器不能读时标寄存器的内容,否则将得到不确定数据。

更新周期的基本功能主要是:

1、刷新各个时标寄存器中的内容,同时秒时标寄存器内容加1,并检查其他时标寄存器内容是否有溢出,如果有溢出则相应进位分、时、日、月、年。
2、检查3个——时、分、秒闹钟时标寄存器的内容是否与对应时标寄存器的内容相符。如果相符,则寄存器C中的AF位置1;如果闹钟时标寄存器的内容为C0H~FFH之间数据,则为不关心状态。

那什么是不关心状态?设置闹钟时标寄存器为不关心状态有什么作用呢?

DS12C887共有三个闹钟单元,分别为时、分、秒闹钟单元。在其中写入闹钟时间值并且在时钟中断允许的情况下,每天到该时刻就会产生中断申请信 号。但这种方式每天只提供一次中断信号。如果每小时都产生中断申请信号,或每分钟产生中断申请信号怎么办呢?这时就要用到“不关心码”,即:
在“时闹钟”单元写入C0H~FFH之间数据,可每小时产生一次中断;
在“时闹钟”单元和“分闹钟”单元写入C0H~FFH之间数据,可每分钟产生一次中断。
在“时闹钟”单元、“分闹钟”单元和“秒闹钟”单元都写入C0H~FFH之间数据,则每秒产生一次中断。
但 这种方式也只能在整点、整分或每秒产生一次中断。若控制系统要求的定时间隔不是整数时,应该通过软件来调整实现。比如每3分钟实现一次中断。大头爸爸:在 “时闹钟”单元写入C0H~FFH之间数据,在“分闹钟”单元写入3,在“秒闹钟”单元写入C0H~FFH之间数据即可。

下面在讲讲关于DS12C887的初始化

DS12C887采用连续工作制,一般无需每次都初始化,即使是系统复位时也是如此。一般是新产品买回来,第一次使用的时候初始化;或者你想要初始化的时候。那么如何初始化DS12C887呢?

1、首先应禁止芯片内部的更新周期操作。所以应先将DS12C887状态寄存器B中的SET位置1。
2、然后初始化00H到09H时标参数寄存器的值和状态寄存器A
3、再通过读状态寄存器C,清除寄存器C中的周期中断标志位PF、闹钟中断标志位AF、更新周期结束中断标志位UF。
4、《新编MCS-51单片机应用设计》一书,在第4步,还需通过读取寄存器D。(读寄存器D后,VRT位自动置1)——他所针对的是DS12887。关于这个内容,以后确定在补充。
5、将状态寄存器B中的SET位置0,芯片开始计时工作。

下面是关于DS12C887读/写时序

下面是关于DS12C887的操作函数

//向某地址写数据
void DS12C887_Write(uint8 _address,uint8 _data)
{
  DS12C887_CS=0;
  DS12C887_DS=1;
  DS12C887_WR=1;
  DS12C887_AS=1;
  P0=_address;
  DS12C887_AS=0;
  DS12C887_WR=0;
  P0=_data;
  DS12C887_WR=1;
  DS12C887_AS=1;
  DS12C887_CS=1;
}
//读某地址的数据
uint8 DS12C887_Read(uint8 _address)
{
  uint8 tmpData;
  DS12C887_CS=0;
  DS12C887_AS=1;
  DS12C887_DS=1;
  DS12C887_WR=1;
  P0=_address;
  DS12C887_AS=0;
  DS12C887_DS=0;
  P0=0xff;//单片机从I/O口读取数据之前先给I/O口赋个高。
  tmpData=P0;
  DS12C887_DS=1;
  DS12C887_AS=1;
  DS12C887_CS=1;
  return(tmpData);
}

附:下面是通过xbyte操作DS12C887的方法,可学习并吸收掌握。

其中DS12C887的基地址为7F00H,相应的程序采用C51语言编写(以Intel工作模式为例)。

由8031单片机和DS12C887构成的时间获取电路的初始化程序如下:

XBYTE[0x7F00+0x0B]=0x82;
XBYTE[0x7F00+0x0A]=0xA0;
XBYTE[0x7F00+0x0A]=0x20;
XBYTE[0x7F00+0x0B]=0x02;

/*所有的中断禁止,24小时制,BCD码模式*/

以下均获取时间程序:

unsigned char data t-century;
unsigned char data t-year;
unsigned char data t-month;
unsigned char data t-date;
unsigned char data t-week;
unsigned char data t-hour;
unsigned char data t-minute;
unsigned char data t-second;

if((XBYTE[7F00+0x0A]&0x80)!=0){
t-century=XBYTE[0x7F00+0x32];/*读取世纪*/
t-year=XBYTE[Ox7F00+0x09];/*读取年份*/
t-month=XBYTE[Ox7F00+0x08];/*读取月份*/
t-date=XBYTE[Ox7F00+0x07];/*读取日期*/
t-week=XBYTE[Ox7F00+0x06];/*读取星期几*/
t-hour=XBYTE[Ox7F00+0x04];/*读取小时*/
t-minute=XBYTE[DS12887+0x02];/*读取分钟*/
t-second=XBYTE[Ox7F00+0x00];}/*读取秒*/

在网上获得的另一段代码:

需要的,仔细看看资料,一般包括以下几个方面
//硬件地址p2.7接12887的cs

#define p12887_sec   xbyte[0x7f00]
#define p12887_asec  xbyte[0x7f01]
#define p12887_min   xbyte[0x7f02]
#define p12887_amin  xbyte[0x7f03]
#define p12887_hour  xbyte[0x7f04]
#define p12887_ahour xbyte[0x7f05]
#define p12887_week  xbyte[0x7f06]
#define p12887_day   xbyte[0x7f07]
#define p12887_month xbyte[0x7f08]
#define p12887_year  xbyte[0x7f09]
#define p12887_cona  xbyte[0x7f0a]
#define p12887_conb  xbyte[0x7f0b]
#define p12887_irqf  xbyte[0x7f0c]
#define p12887_vf    xbyte[0x7f0d]

//初始化操作
void start12887(void)//启动时钟
{
  u_char i;
  i=p12887_vf;
  p12887_cona=0x70;// 挂起时钟
  p12887_conb=0x86;// noupdate,all int disable, bin,24,normal time
  p12887_conb=0x06;// update
  p12887_cona=0x20;// start
  i=p12887_irqf;
}

下面是从网络上找到的,某网友对xbyte用法的疑问及某网友回复,借鉴:

提问:

在一般的读写外部RAM的程序中,经常看到这样的句子:
    XBYTE[address]=data   写数据
    data=XBYTE[address]   读数据
但是我想问的是,为什么用了XBYTE后,就不用顾及其时序了呢?
就是说,读写数据的时候,WR和RD怎么都不用用程序去控制了呢?
参考了很多读写外部RAM的程序,都找不到其控制WR和RD控制线的语句
哪位大侠能帮忙解释一下这是为什么嘛?
最好还能说说XBYTE具体的用法.....

回答:

在ABSACC中你看一下就明白了
#define CBYTE ((unsigned char volatile code  *) 0)
#define DBYTE ((unsigned char volatile data  *) 0)
#define PBYTE ((unsigned char volatile pdata *) 0)
#define XBYTE ((unsigned char volatile xdata *) 0)

XBYTE [address]=data;
相当于
unsigned char  xdata *p;
p=address;
*p=data;
但是用XBYTE会节省一个指针变量的R

本站内容除特别声明的原创文章之外,转载内容只为传递更多信息,并不代表本网站赞同其观点。转载的所有的文章、图片、音/视频文件等资料的版权归版权所有权人所有。本站采用的非本站原创文章及图片等内容无法一一联系确认版权者。如涉及作品内容、版权和其它问题,请及时通过电子邮件或电话通知我们,以便迅速采取适当措施,避免给双方造成不必要的经济损失。联系电话:010-82306118;邮箱:aet@chinaaet.com。