外國器件PCF8563I2C實時時鐘/日歷芯片在8051系統(tǒng)中的應用
摘要:PCF8563是PLILIPS公司生產的低功耗CMOS實時時鐘/日歷芯片,文中介紹了PCF8563的結構、功能及工作原理。結合其在8051系統(tǒng)中的應用實例,給出了PCF8563與8051單片機的硬件接口電路和C語言軟件編程程序。
本文引用地址:http://m.butianyuan.cn/article/255593.htm關鍵詞:I2C總線 串行接口 PCF8563 BCD碼 C語言
1 PCF8563簡介
PCF8563是PHILIPS公司生產的低功耗CMOS實時時鐘/日歷芯片,芯片最大總線速度為400kbits/s,每次讀寫數據后,其內嵌的字地址寄存器器會自動產生增量。PCF8563可廣泛應用于移動電話、便攜儀器、傳真機、電池電源等產品中。
PCF8563的引腳排列如圖1所示,各引腳功能說明如表1所列。
PCF8563有16個8位寄存器,其中包括:可自動增量的地址寄存器、內置32.768kHz的振蕩器(帶有一個內部集成電容)、分頻器(用于給實時時鐘RTC提供源時鐘)、可編程時鐘輸出、定時器、報警器、掉電檢測器和400kHz的I2C總線接口。
所有16個寄存器設計成可尋址的8位并行寄存器,但不是所有位都有用。當一個RTC寄存器被讀時,所有計數器的內容將被鎖存,因此,在傳送條件下,可以禁止對時鐘/日歷芯片的錯讀。
表2、表3所列為各寄存器概況及對應的內存地址和功能,同時列出了它們的BCD格式編碼。表中“——”表示無效位,“0”表示此位應置邏輯。表3中的世紀位C=0指定世紀數為20XX,C=1指定世紀數為19XX。當年寄存器中的99變00時,世紀位才會改變。
表1 PCF8563的管腳描述
符 號 | 管腳號 | 描 述 |
OSCI | 1 | 振蕩器輸入 |
OSCO | 2 | 振蕩器輸出 |
INT | 3 | 終端輸出(開漏:低電平有效) |
Vss | 4 | 地 |
SDA | 5 | 串行數據I/O |
SCL | 6 | 串行時鐘輸入 |
CLKOUT | 7 | 時鐘輸出(開漏) |
VDD | 8 | 正電源 |
2 I2C總線
2.1 I2C總線特性
I2C總線用兩條線(SDA和SCL)在芯片和模塊間傳遞信息。SDA為串行數據線,SCL為串行時鐘線,這兩條線必須用一個上拉電阻與正電源相連,其數據只有在總線不忙時才可傳送。I2C總線的系統(tǒng)配置參見圖2,產生信號的設備是傳送器,接收信號的設備是接收器,控制信號的設備是主設備,受控制信號的設備是從設備。
表2 寄存器概況
地址 | 寄存器名稱 | Bit7 | Bit6 | Bit5 | Bit4 | Bit3 | Bit2 | Bit1 | Bit0 |
00H | 控制/狀態(tài)寄存器1 | TEST | 0 | STOP | 0 | TESTC | 0 | 0 | 0 |
01H | 控制/狀態(tài)寄存器2 | 0 | 0 | 0 | TI/TP | AF | TF | AIE | TIE |
0DH | CLKOUT頻率寄存器 | FE | — | — | — | — | — | FD1 | FD0 |
0EH | 定時器控制寄存器 | TE | — | — | — | — | — | TD1 | TD0 |
0FH | 定時器倒計數數值寄存器 | 定時器倒計數數值 |
表3 BCD格式寄存器概況
地 址 | 寄存器名稱 | Bit7 | Bit6 | Bit5 | Bit4 | Bit3 | Bit2 | Bit1 | Bit0 |
01H | 秒 | VL | 00~59BCD碼格式數 | ||||||
03H | 分鐘 | - | 00~59BCD碼格式數 | ||||||
04H | 小時 | - | - | 00~23BCD碼格式數 | |||||
05H | 日 | - | - | 01~31BCD碼格式數 | |||||
06H | 星期 | - | - | - | - | - | 0~6 | ||
07H | 月/世紀 | C | - | - | 01~12BCD碼格式數 | ||||
08H | 年 | 00~99BCD碼格式數 | |||||||
09H | 分鐘報警 | AE | 00~59BCD碼格式數 | ||||||
0AH | 小時報警 | AE | - | 00~23BCD碼格式數 | |||||
0BH | 日報警 | AE | - | 01~31BCD碼格式數 | |||||
0CH | 星期報警 | AE | - | - | - | - | 0~6 |
2.2 啟動和停止條件
總線不忙時,數據線和時鐘線保持在高電平。數據線(SDA)在下降沿而時鐘線(SCL)為高電平時,為起動條件(S);數據線在上升沿而時鐘線為高電平時為停止條件(P),參見圖3。
2.3 位傳送
每個時鐘脈沖傳送一個數據位,SDA線上的數據在時鐘脈沖高電平時應保持穩(wěn)定,否則將成為控制信號,參見圖4。
2.4 標志位
在起動條件和停止條件之間,傳送器傳送給接收器的數據數量沒有限制。在每個8位字節(jié)后加一個標志位,傳送器便產生一個高電平的標志位,這時主設備產生一個附加標志位時鐘脈沖。
從接受器必須在接收到每個字節(jié)后產生一個標志位,主接收器也必須在接收從傳送器傳送的每個字節(jié)后產生一個標志位。在標志位時鐘脈沖出現時,SDA線應保持低電平(應考慮起動和保持時間)。傳送器應在從設備接收到最后一個字節(jié)時變?yōu)榈碗娖剑菇邮掌鳟a生標志位,這時主設備即可產生停止條件。參見圖5。
2.5 I2C總線協議
用I2C總線傳遞數據前,接收的設備應先標明地址,在I2C總線起動后,這個地址與第一個傳送字節(jié)一起被傳送出去。PCF8563可以作為一個從接收器或從傳送器,此時的時鐘信號線SCL只能輸入信號線,數據信號線SDA則為一條雙向信號線。PCF8563的從地址參見圖6。
3 應用概述
圖7所示為PCF8563的具體應用電路圖,對圖中石英晶片頻率的調整,筆者給出3種可行性方法,供參考:
方法1:定值OSCI電容。計算所需的電容平均值,用此值的定值電容,通電后在CLKOUT管腳上測出的頻率應為32.768kHz,測出的頻率值偏差取決于石英晶片本身,電容偏差和器件之間的偏差平均為±5×10 -6。平均偏差可達5分鐘/年。
方法2:OSCI微調電容??赏ㄟ^調整OSCI管腳的微調電容式振蕩器的頻率來獲得更高的精度,此時可測出通電時管腳CLKOUT上的信號頻率為32.768kHz。
方法3:OSCI輸出。直接測量管腳OSCI的輸出。
4 程序范例
以下的C語言源程序是用8051單片機的普通I/O口(如P0.0/P0.4)模擬實現PCF8563的I2C時鐘/日歷芯片的操作,有字節(jié)寫/讀兩種狀態(tài)。程序中從地址的讀地址為0A3H,寫地址為0A2H.所發(fā)送的數據字節(jié)為9個,發(fā)送的初始數據在rom_sed[9]中,rom_sed[9]定義了寄存器中當前發(fā)送的值:控制/狀態(tài)寄存器1為0,控制/狀態(tài)寄存器2為0,秒寄存器為0,分鐘寄存器55,小時寄存器為23,日寄存器為31,星期寄存器為6,月/世紀寄存器為0x12,年寄存器為0x99(即1999年12月31日23點55分0秒),當程序運行一段時間(5分鐘)后,從地址寄存器02H開始讀數據,數據存放在rom_rec7中,發(fā)現變量rom_rec7變?yōu)?000年1月1日0點0分。若外轉帳電路有顯示,則時間可以顯示在面板上。
#included:.h>
#define byte unsigned char
sbit scl=0x81; //定義串行I/O口
sbit sda=0x80;
idata byte rom_sed[9];
idata byte rom_rec[7];
idata byte j,k;
bit flag,flag1;
void delay(void) //延時子程序
{data byte i;
for(i=0;i6;i++);
}
void I_start(void) //發(fā)送I2C總線起始條件子程序
{sda=1;
;
scl=1;
delay();
sda=0;
delay();
scl=0;
;
}
void I_stop(void) //I2C總線停止條件子程序
{sda=0;
;
scl=1;
delay();
sda=1;
delay();
}
bit I_send(byte I_data) //字節(jié)數據傳送子程序
{data byte i;
for(i=0,i8;i++)
{sda-(bit)(I_data0x80);
I_data=I_data1;
;
scl=1;
delay();
scl=0;
}
;;
sda=1; ;; //ready for receiving ACK bit
scl=1; ;; //start receiving ack bit
flag=0;
if(sda= =0)flag=0;
else flag=1; //return(~I_clock());
scl=0;
return(flag);
}
byte I_receive(void) //字節(jié)數據接收子程序
{ data byte i;
byte I_data=0;
sda=1;
for(i=0;I8;i++)
{ I_data*=2;
;
scl=0;
delay();
scl=1; ;;
if(sda= =1)I_data++;
;;
}
scl=0; ;;;
sda=0;
if(flag1= =0){;;scl=1;delay();scl=0;} //not last receic_byte ACK
else{sda=1; ;;scl=1;delay();scl=0;flag1=0;} //the last receive_byte ~ACK
return(I_data);
}
main() //主程序
{data byte i;
rom_sed[0]=0x00; rom_sed[1]=0x00;
rom_sed[2]=0x00; rom_sed[3]=0x55;
rom_sed[4]=0x23; rom_sed[5]=0x31;
rom_sed[6]=0x06; rom_sed[7]=0x92;
rom_sed[8]=0x99;
for(i=0;i255;i++)delay();
I_start();
if(~I_send(rom_sed[i]));
else;
}
I_stop();
}
else;
}
else;
start: I_start();
if(~I_send(0xa2)) //pcf_write address
{if(~I_send(0x02)) //pcf_status register address
{I_start();
if(~I_send(0xa3)) //write status register
{for(i=0;i7;i++)
{if(i= =6)flag1=1;
else flag1=0;
rom_rec[i]=I_receive();
switch(i)
{case 1:rom_rec[i]=rom_rec[i]0x7f;break;
ease2:
case3:rom_rec[i]=rom_rec[i]0x3f;break;
case4:rom_rec[i]=rom_rec[i]0x07;break;
case5:rom_rec[i]=rom_rec[i]0x9f;brealk;default:break;
}
}
I_stop()
}
}
}
goto start;
}
評論