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