在許多電子設(shè)備中,通常會(huì)進(jìn)行一些與時(shí)間有關(guān)的控制,如果用系統(tǒng)的定時(shí)器來(lái)設(shè)計(jì)時(shí)鐘的話,偶然的掉電或晶振的誤差都會(huì)造成時(shí)間的錯(cuò)亂,更糟糕的是,若完全用程序設(shè)計(jì)時(shí)鐘還會(huì)占用大量的系統(tǒng)資源,從而嚴(yán)重影響系統(tǒng)的其他功能。為此,很多芯片制造公司都設(shè)計(jì)出了各種各樣的實(shí)時(shí)時(shí)鐘芯片。 常見(jiàn)的時(shí)鐘芯片有兩種。 一種是體積非常小的表貼是元件,通常用在高端小型手持式儀器或設(shè)備中。這種芯片在使用時(shí)需要外接備份電池和外部晶振,電池用來(lái)保持主系統(tǒng)在意外時(shí)為時(shí)鐘芯片供電,外部晶振用來(lái)給時(shí)鐘芯片所必須的震蕩來(lái)源。 另一種體積相對(duì)較大,一般為直插式,它的內(nèi)部有可充電鋰電池,同時(shí)內(nèi)部還集成了32.768KHZ的標(biāo)準(zhǔn)晶振。 DS18B20是由DALLAS公司生產(chǎn)的,采用普通的32.768KHZ。 DS18B20的內(nèi)部結(jié)構(gòu): DS18B20的讀數(shù)據(jù)時(shí)序: ? 如圖的數(shù)據(jù)序列,左邊是低位,右邊是高位,在負(fù)跳變沿進(jìn)行讀數(shù)據(jù),上升沿進(jìn)行寫(xiě)數(shù)據(jù)。 DS18B20的寫(xiě)數(shù)據(jù)時(shí)序: 數(shù)據(jù)在SCLK在上升沿輸入,前8位指定訪問(wèn)地址命令,在之后的時(shí)鐘周期,讀操作時(shí)輸出的數(shù)據(jù),寫(xiě)操作時(shí)輸入數(shù)據(jù)。時(shí)鐘脈沖的個(gè)數(shù)在單字節(jié)方式下為8個(gè)地址加8個(gè)數(shù)據(jù)。 DS18B20的控制字: 日歷時(shí)鐘寄存器與控制字對(duì)照: 日歷時(shí)鐘寄存器: 寄存器功能說(shuō)明: 萬(wàn)年歷程序: #include <reg52.h> #define uchar unsigned char #define uint unsigned int uint i; sbit SCLK = P1^3; sbit IO = P1^4; sbit RST = P1^5; sbit RS = P1^0; sbit RW = P1^1; sbit E = P1^2; uchar Time_Data[]={'0','1','2','3','4','5','6','7','8','9'}; void delay(uint t){ int i,j; for(i = 0; i < t; i++) for(j = 10; j > 0; j--) ; } void lcd_com(uchar s){ RS = 0; //低電平,寫(xiě)指令 P2 = s; //傳數(shù)據(jù) delay(14); //看時(shí)序圖,數(shù)據(jù)需要穩(wěn)定一段時(shí)間 E = 1; //給一個(gè)高脈沖,發(fā)送命令 delay(14); //如圖,高脈沖延時(shí)一段時(shí)間,確保命令發(fā)送 E = 0; //發(fā)送結(jié)束E置為低電平 } void lcd_data(uchar s){ RS = 1; P2 = s; delay(14); E = 1; delay(14); E = 0; } uchar DS_Read(uchar command){ uchar value; RST = 0; SCLK = 0; RST = 1; value = 0x0; for(i = 0; i < 8; i++){ IO = command & 0x01; //寫(xiě)入控制字 SCLK = 0; SCLK = 1; command >>= 1; } for(i = 0; i < 8; i++){ SCLK = 1; SCLK = 0; if(IO) value |= (0x01<<i); //如果那位是1則value置1 } RST = 0; value = value/16*10 + value%16; //BCD碼到十進(jìn)制的轉(zhuǎn)換 return value; } void DS_Write(uchar command,uchar value){ RST = 0; SCLK = 0; RST = 1; for(i = 0; i < 8; i++){ //寫(xiě)控制字 IO = command & 0x01; SCLK = 0; SCLK = 1; command >>= 1; } for(i = 0; i < 8; i++){ //向IO引腳寫(xiě)數(shù)據(jù) IO = value & 0x01; SCLK = 0; SCLK = 1; value >>= 1; } } void Init_ds(){ RST = 0; SCLK = 0; RST = 1; DS_Write(0x8E,0x00); //打開(kāi)寫(xiě)保護(hù),WP位置0,這樣就可以寫(xiě)數(shù)據(jù)了 DS_Write(0x84,0x00); //對(duì)日歷時(shí)鐘寄存器的初始化 DS_Write(0x8c,0x10); DS_Write(0x8a,0x05); DS_Write(0x88,0x10); DS_Write(0x86,0x01); DS_Write(0x84,0x04); DS_Write(0x82,0x22); DS_Write(0x80,0x00); //啟動(dòng)時(shí)鐘 DS_Write(0x8e,0x80); //禁止寄存器寫(xiě) } void Init_lcd(){ RS = 1; //先發(fā)指令,在初始時(shí)刻RS是高,E和RW是低 E = 0; RW = 0; lcd_com(0x38); //設(shè)置為16*2顯示,5*7點(diǎn)陣,8位數(shù)據(jù)接口 lcd_com(0x0f); //開(kāi)顯示,顯示光標(biāo),光標(biāo)閃爍 lcd_com(0x06); //讀寫(xiě)一個(gè)字符后地址指針加一 lcd_com(0x01); } void Display_lcd(uchar y, uchar x, uchar value){ if(y) lcd_com(0x80+0x40+x); //如果y為1,寫(xiě)在第二行 else lcd_com(0x80+x); lcd_data(value); //寫(xiě)到LCD602上 } void main(){ Init_ds(); Init_lcd(); while(1){ Display_lcd(0,0,'2'); Display_lcd(0,1,'0'); Display_lcd(0,2,Time_Data[DS_Read(0x8D)/10]); Display_lcd(0,3,Time_Data[DS_Read(0x8D)%10]); Display_lcd(0,4,'-'); Display_lcd(0,5,Time_Data[DS_Read(0x89)/10]); Display_lcd(0,6,Time_Data[DS_Read(0x89)%10]); Display_lcd(0,7,'-'); Display_lcd(0,8,Time_Data[DS_Read(0x87)/10]); Display_lcd(0,9,Time_Data[DS_Read(0x87)%10]); Display_lcd(0,10,'D'); Display_lcd(0,11,'a'); Display_lcd(0,12,'y'); Display_lcd(0,13,':'); Display_lcd(0,14,Time_Data[DS_Read(0x8b)/10]); Display_lcd(0,15,Time_Data[DS_Read(0x8b)%10]); Display_lcd(1,0,'C'); Display_lcd(1,1,'a'); Display_lcd(1,2,'n'); Display_lcd(1,3,'u'); Display_lcd(1,4,'t'); Display_lcd(1,5,'e'); Display_lcd(1,6,' '); Display_lcd(1,7,Time_Data[DS_Read(0x85)/10]); Display_lcd(1,8,Time_Data[DS_Read(0x85)%10]); Display_lcd(1,9,':'); Display_lcd(1,10,Time_Data[DS_Read(0x83)/10]); Display_lcd(1,11,Time_Data[DS_Read(0x83)%10]); Display_lcd(1,12,':'); Display_lcd(1,13,Time_Data[DS_Read(0x81)/10]); Display_lcd(1,14,Time_Data[DS_Read(0x81)%10]); } } //2010-10-1 Day:5 //Canute 04:22:00 DS1302中的RAM: 李萬(wàn)鵬 |