<meter id="pryje"><nav id="pryje"><delect id="pryje"></delect></nav></meter>
          <label id="pryje"></label>

          新聞中心

          EEPW首頁 > 物聯(lián)網(wǎng)與傳感器 > 設(shè)計(jì)應(yīng)用 > DS1337 時(shí)鐘芯片在 C8051F 上的實(shí)現(xiàn)

          DS1337 時(shí)鐘芯片在 C8051F 上的實(shí)現(xiàn)

          作者: 時(shí)間:2017-10-13 來源:網(wǎng)絡(luò) 收藏

            一、DS1337介紹

            DS1337串行實(shí)時(shí)是一種低功耗、全部采用BCD碼的時(shí)鐘日歷芯片,它帶有兩個(gè)可編程的定時(shí)鬧鐘和一個(gè)可編程的方波輸出。其地址和數(shù)據(jù)可通過I2C總線串行傳輸,能提供秒、分、時(shí)、日、星期、月和年等信息。

          本文引用地址:http://www.ex-cimer.com/article/201710/365833.htm

            1.1 DS1337的引腳說明

            DS1337的引腳排列示意圖如圖1所示。各引腳的功能如下:

            

            圖1 DS1337引腳示意圖

            VCC,GND:直流電源和接地端,VCC的輸入范圍在1.8~5.5V之間。X1,X2:標(biāo)準(zhǔn)的32.768kHz的石英晶振接入端,內(nèi)部晶振電路設(shè)計(jì)要求晶振特定電容負(fù)載為6pF。另外,這兩個(gè)引腳還可以有其它接法,即:X1腳連接外部振蕩信號源,而將X2腳懸空。

            SCL:串行時(shí)鐘輸入,用來在總線上同步數(shù)據(jù)傳輸。

            SDA:串行數(shù)據(jù)輸入輸出,SDA是I2C總線接口的數(shù)據(jù)輸入輸出引腳,開漏輸出,使用時(shí)要求接一個(gè)上拉電阻。

            SQW/INTB:方波/中斷輸出,可通過對DS1337的內(nèi)部控制寄存器進(jìn)行編程來控制這個(gè)引腳是輸出方波還是輸出中斷信號。該引腳是開漏輸出,使用時(shí)要接一個(gè)外部的上拉電阻。

            INTA:中斷輸出端,使能時(shí),如果鬧鐘寄存器的設(shè)定值與當(dāng)前時(shí)間匹配,該腳會輸出一個(gè)低電平。該引腳也是開漏輸出,要接上拉電阻。

            1.2 時(shí)間寄存器

            常用的時(shí)間寄存器地址為00H~06H。設(shè)置和初始化時(shí)間和日歷可通過寫相應(yīng)的寄存器字段來實(shí)現(xiàn),寄存器的數(shù)據(jù)格式以BCD碼表示。DS1337既可以工作在12小時(shí)模式下,也可以工作在24小時(shí)模式下。小時(shí)寄存器的位6被定義為12小時(shí)模式或24小時(shí)模式選擇位,該位為1時(shí),選擇12小時(shí)模式。在12小時(shí)模式時(shí),位5是AM/PM標(biāo)志位,該位為1時(shí)表示PM。當(dāng)在24小時(shí)模式時(shí),位5是第二個(gè)十位(表示20到23小時(shí))。月寄存器的第7位是世紀(jì)位,當(dāng)年寄存器從0到99溢出時(shí),該位發(fā)生變化。

            1.3 控制寄存器和狀態(tài)寄存器

            DS1337中有一個(gè)控制寄存器和一個(gè)狀態(tài)寄存器,可用于控制實(shí)時(shí)時(shí)鐘、鬧鐘和方波的輸出。

            控制寄存器地址為0EH。其中:

            EOSC:振蕩器使能位。該位為0,振蕩器起振;為1,振蕩器停振。剛上電時(shí),該位為0;RS1,RS2:方波輸出頻率選擇位。RS1和RS2共有四種組合,分別對應(yīng)的方波輸出頻率為1Hz,4.096kHz,8.192kHz,32.768kHz。在剛加電時(shí),方波輸出頻率設(shè)置是32.768kHz。

            INTCN:中斷控制位。用于控制兩個(gè)鬧鐘與中斷輸出腳之間的關(guān)系。為1時(shí),兩個(gè)鬧鐘在滿足定時(shí)條件時(shí),各自有獨(dú)立的中斷輸出。為0時(shí),兩個(gè)鬧鐘共用一個(gè)中斷輸出腳INTA,而腳SQW/INTB為方波輸出端。開始上電時(shí),該位為0。

            A1IE:鬧鐘1中斷使能位。為1時(shí),允許狀態(tài)寄存器的A1F位輸出到腳INTA。上電時(shí)該位為0,此時(shí)不能用A1F位初始化INTA信號。

            A2IE:鬧鐘2中斷使能位,該位的作用與A1IE位相同。

            DS1337的狀態(tài)寄存器地址為0FH, 各位的作用如下:

            OSF:振蕩器停止標(biāo)志。該位為1,表示振蕩器已停止。有四種情況能產(chǎn)生這樣的結(jié)果:一是芯片剛上電,二是Vcc引腳電壓不足,三是EOSC位為1,四是晶振受到外部影響(如噪聲等)。

            A1F、A2F:鬧鐘標(biāo)志位。為1時(shí),表示鬧鐘設(shè)定時(shí)間與當(dāng)前時(shí)間匹配,并產(chǎn)生中斷輸出。

            

            圖2 DS1337寄存器

            1.4 對DS1337的讀與寫

            

            圖3 DS1337 寫寄存器

            從上圖中,可以看出,主器件發(fā)起開始條件,發(fā)送從器件的地址和寫命令(0xD0|0x00),等待從器件的應(yīng)答,然后再發(fā)送要寫的寄存器地址,等待從器件的應(yīng)答,然后再發(fā)送要寫的數(shù)據(jù),等待從器件的應(yīng)答,如果寫操作完成,主器件發(fā)送結(jié)束。完成一次寫數(shù)據(jù)過程。

            

            圖4 DS1337 讀寄存器

            從上圖中,可以看出,主器件發(fā)起開始條件,發(fā)送從器件的地址和寫命令(0xD0|0x00),等待從器件的應(yīng)答,然后再發(fā)送要讀的寄存器地址,等待從器件的應(yīng)答,然后主器件再重新發(fā)送開始條件,發(fā)送從器件的地址和讀命令(0xD0|0x01),等待從器件的應(yīng)答,接收從器件發(fā)來的數(shù)據(jù),主器件應(yīng)答。當(dāng)收到最后一個(gè)數(shù)據(jù)后,主器件發(fā)送非應(yīng)答和結(jié)束。完成一次讀數(shù)據(jù)過程。

            二、SMBus總線介紹

            SMBus串行I/O接口是一個(gè)雙線的雙向串行總線,與I2C串行總線兼容。圖 5給出了一個(gè)典型的SMBus 配置。SMBus 接口的工作電壓可以在3.0V和5.0V 之間,總線上不同器件的工作電壓可以不同。SCL(串行時(shí)鐘)和 SDA(串行數(shù)據(jù))線是雙向的。 必須通過上拉電阻或類似電路將它們連到電源電壓。當(dāng)總線空閑時(shí),這兩條線都被拉到高電平。連接在總線上的每個(gè)器件的 SCL 和 SDA 都必須是漏極開路或集電極開路的。

            

            圖5 SMBus 配置

            2.1握手

            SMBus采用多種線路條件作為器件間的握手信號。在一次數(shù)據(jù)傳輸中,SDA只能在SCL為低時(shí)改變電平。在SCL為高電平時(shí)SDA發(fā)生改變則是代表如下的開始和停止信號:

            開始:該條件啟動一次傳輸過程。當(dāng)SCL為高電平時(shí)SDA上出現(xiàn)一個(gè)下降沿。

            結(jié)束:該條件結(jié)束一次傳輸過程。當(dāng)SCL為高電平時(shí)SDA上出現(xiàn)一個(gè)上升沿。

            應(yīng)答:也稱為ACK,接收器件發(fā)送該信號表示確認(rèn)。例如,在器件X收到一個(gè)字節(jié)后,它將發(fā)送一個(gè)ACK確認(rèn)傳輸成功。ACK條件是在SCL為高時(shí)采樣到SDA為低電平。

            非應(yīng)答:也稱為NACK,這是在SCL為高電平時(shí)采樣到SDA為高電平。當(dāng)接收器件不能產(chǎn)生ACK時(shí),發(fā)送器件看到的是NACK。在典型的數(shù)據(jù)傳輸中,收到NACK信號表示所尋址的從器件沒有準(zhǔn)備好或不在總線上。一個(gè)處于接收狀態(tài)的主器件發(fā)送NACK表示這是傳輸?shù)淖詈笠粋€(gè)字節(jié)。圖2給出了握手信號時(shí)序。

            

            圖6 SMBus 時(shí)序

            2.2 傳輸方式

            有兩種可能的傳輸方式:寫(從主器件到從器件)和讀(從從器件到主器件)。在一次傳輸中,任何一個(gè)器件都可以是四種角色之一。這四種角色將在下面說明。注意,從地址+R/W’是指一個(gè)8位傳輸(7位地址,1位R/W)。

            1)主發(fā)送器:在該方式下,器件在SDA上發(fā)送串行數(shù)據(jù),在SCL上輸出時(shí)鐘。器件用一個(gè)起始條件啟動傳輸過程,發(fā)送從地址+W,然后等待從器件的ACK。收到ACK后,器件發(fā)送一個(gè)或多個(gè)字節(jié)數(shù)據(jù),每個(gè)字節(jié)都要由從器件確認(rèn)。在發(fā)送完最后一個(gè)字節(jié)后,器件發(fā)送一個(gè)停止條件。

            2)主接收器:在該方式下,器件在SDA上接收串行數(shù)據(jù),在SCL上輸出時(shí)鐘。器件用一個(gè)起始條件啟動傳輸過程,之后發(fā)送從地址+R。在收到從器件對地址的ACK后,在SCL上輸出時(shí)鐘并在SDA上接收數(shù)據(jù)。在接收完最后一個(gè)字節(jié)后,器件將發(fā)送一個(gè)NACK和一個(gè)停止條件。

            3)從發(fā)送器:在該方式下,器件在SDA上輸出串行數(shù)據(jù),在SCL上接受時(shí)鐘。器件接收一個(gè)起始條件和它自己的從地址+R,然后發(fā)出ACK并進(jìn)入從發(fā)送方式。器件在SDA上發(fā)送數(shù)據(jù),在發(fā)送完每個(gè)字節(jié)后都要收到一個(gè)ACK。在傳輸完最后一個(gè)字節(jié)后,主器件發(fā)送一個(gè)NACK和一個(gè)停止條件。

            4)從接收器:在該方式下,器件收到來自主器件的起始條件和和它自己的從地址+W。然后發(fā)出ACK并進(jìn)入從接收方式。現(xiàn)在器件在SDA上接收串行數(shù)據(jù),在SCL上接收時(shí)鐘。在接收完每個(gè)字節(jié)后都要發(fā)送一個(gè)ACK,在接收到主器件的停止條件后退出從接收方式。

            圖7為典型的寫操作情況。圖8為典型的讀操作情況。

            

            圖7 寫操作

            (1)為一個(gè)成功的傳送過程。在(3)中,主器件在收到一個(gè)ACK后重新發(fā)出起始條件。這一過程允許主器件在不放棄總線的情況下啟動一個(gè)新的傳輸過程(例如,從寫操作切換到讀操作)。重復(fù)起始條件通常在訪問EEPROM時(shí)使用,因?yàn)橐粋€(gè)讀操作前面必須有一個(gè)寫存儲器地址的操作。

            

            圖8 讀操作

            2.3 SMBus特殊功能寄存器

            對 SMBus 串行接口的訪問和控制是通過 5 個(gè)特殊功能寄存器來實(shí)現(xiàn)的:控制寄存器 SMB0CN、時(shí)鐘速率寄存器 SMB0CR、地址寄存器 SMB0ADR、數(shù)據(jù)寄存器 SMB0DAT 和狀態(tài)寄存器 SMB0STA。系統(tǒng)器件可以有一個(gè)或多個(gè) SMBus 串行接口。

            2.3.1 控制寄存器SMB0CN

            SMBus 控制寄存器 SMB0CN 用于配置和控制 SMBus 接口。該寄存器中的所有位都可以 用軟件讀寫。有兩個(gè)控制位還受 SMBus 硬件的影響。當(dāng)發(fā)生一個(gè)有效的串行中斷條件時(shí),串 行中斷標(biāo)志(SI,SMB0CN.3)被硬件設(shè)置為邏輯 1,該標(biāo)志只能用軟件清 0。當(dāng)總線上出現(xiàn) 一個(gè)停止條件時(shí),停止標(biāo)志(STO,SMB0CN.4)被硬件清 0。

            

            

            2.3.2 時(shí)鐘速率寄存器SMB0CR

            在器件工作于主方式時(shí)SMBus時(shí)鐘寄存器用于控制SCL時(shí)鐘速率。SMB0CR中的8位數(shù)決定了時(shí)鐘速率,公式如下:

            

            其中,SMB0CR是一個(gè)負(fù)數(shù)的補(bǔ)碼。因此,對于100kHz的SCL頻率和16MHz的SYSCLK,應(yīng)向SMB0CL裝入-80,即0xB0。

            2.3.3 地址寄存器 SMB0ADR

            SMBus地址寄存器保存器件在從方式時(shí)將要應(yīng)答的從地址。位(7:1)保存從地址;位0是通用呼叫允許。如果位0被置位,器件將應(yīng)答通用呼叫地址(0x00)。

            2.3.4 數(shù)據(jù)寄存器 SMB0DAT

            SMBus數(shù)據(jù)寄存器用于保存將要發(fā)送或剛剛接收的數(shù)據(jù)。只有在SI=1時(shí),從該寄存器讀出的數(shù)據(jù)才是有效的。當(dāng)SI不為1時(shí),SMBus可能處在向SMB0DAT移入數(shù)據(jù)或從SMB0DAT移出數(shù)據(jù)的過程中。注意:在傳輸過程中,從SMB0DAT移出的最高位又移回到最低位,因此在一次傳輸完成后SMB0DAT中仍然保存著原始數(shù)據(jù)。

            1.3.5 狀態(tài)寄存器 SMB0STA

            共有28個(gè)可能的SMBus狀態(tài),每個(gè)狀態(tài)對應(yīng)一個(gè)唯一的狀態(tài)碼。狀態(tài)碼的高5位是可變的,而一個(gè)有效狀態(tài)碼的

            低3位固定為0(當(dāng)SI=1時(shí))。因此所有有效的狀態(tài)碼都是8的整數(shù)倍。

            

            

            

            

            三、在C8051F 上的實(shí)現(xiàn)

            3.1 硬件

            

            3.2 軟件

            1 typedef struct

            2 {

            3 u8 second; // 0 to 59

            4 u8 minute; // 0 to 59

            5 u8 hour; // 0 to 23 (24-hour TIme)

            6 u8 day; // 0 = Sunday, 1 = Monday, etc.

            7 u8 date; // 1 to 31

            8 u8 month; // 1 to 12

            9 u8 year; // 00 to 99

            10 } DS1337_TIme;

            11

            12 xdata DS1337_TIme TIme;

            13

            14 bit SMB_BUSY;

            15 u8 COMMAND;

            16 u8 Mode;

            17 u8 wr_data[2];

            18 u8 wrnumber;

            19 u8 get_data;

            20

            21

            22 void DS1337_Set_time(DS1337_time dt);

            23

            24

            25 char bcd2bin(char bcd_value)

            26 {

            27 char temp;

            28 temp = bcd_value;

            29 temp 》》= 1;

            30 temp = 0x78;

            31 return(temp + (temp 》》 2) + (bcd_value 0x0f));

            32 }

            33

            34

            35 unsigned char bin2bcd(unsigned char value)

            36 {

            37 char retval;

            38 retval = 0;

            39

            40 while(1)

            41 {

            42 if(value 》= 10)

            43 {

            44 value -= 10;

            45 retval += 0x10;

            46 }

            47 else

            48 {

            49 retval += value;

            50 break;

            51 }

            52 }

            53 return(retval);

            第25行的函數(shù)是將BCD碼轉(zhuǎn)化為二進(jìn)制數(shù)。第35行的函數(shù)是將二進(jìn)制數(shù)轉(zhuǎn)化為BCD碼。

            1 void init_iic(void)

            2 {

            3 SMB0CN = 0x44; // Enable SMBus with acknowledge low (AA = 1)

            4 SMB0CR = 146; // SMBus clock rate = 100 kHz 146

            5 EIE1 “= 2; // SMBus interrupt enable

            6 SI = 0;

            7 SMB_BUSY = 1;

            8 }

            9

            10

            11 void Write_DS1337(u8 adrress, u8 data1)

            12 {

            13 Mode = 1;

            14 wrnumber = 2 ;

            15 wr_data[0] = adrress;

            16 wr_data[1] = data1;

            17 SMB0CN = 0x44;

            18 COMMAND = DS1337_ADDR;

            19 STO = 0;

            20 STA = 1;

            21 SMB_BUSY = 1;

            22 while(SMB_BUSY);

            23 }

            24

            25

            26 int Read_DS1337(u8 adrress)

            27 {

            28 Mode=0;

            29 SMB0CN = 0x44;

            30 COMMAND = (DS1337_ADDR | 0x01);

            31 wr_data[0] = adrress;

            32 STO = 0;

            33 STA = 1;

            34 SMB_BUSY = 1;

            35 while(SMB_BUSY);

            36 return get_data;

            37 }

            第1行的函數(shù)初始化SMBus總線。第11行的函數(shù)為DS1337寫操作。第26行的函數(shù)為DS1337讀操作。

            1 void DS1337_init()

            2 {

            3 u8 status;

            4 DS1337_time DT;

            5

            6 DT.second = 30;

            7 DT.minute = 50;

            8 DT.hour = 21;

            9 DT.day = 2;

            10 DT.date = 12;

            11 DT.month = 8;

            12 DT.year = 14;

            13

            14 status = Read_DS1337(DS1337_STATUS_REG);

            15 if((status 0x80) != 0)

            16 {

            17 DS1337_Set_time(DT);

            18 Write_DS1337(DS1337_CONTROL_REG,DS1337_CTRL_REG_INIT_VAL);

            19 Write_DS1337(DS1337_STATUS_REG,DS1337_CLEAR_STATUS_VAL);

            20 }

            21 }

            22

            23 void DS1337_Set_time(DS1337_time dt)

            24 {

            25 u8 bcd_sec,bcd_min,bcd_hrs,bcd_day,bcd_date,bcd_mon,bcd_year;

            26

            27 bcd_sec = bin2bcd(dt.second);

            28 bcd_min = bin2bcd(dt.minute);

            29 bcd_hrs = bin2bcd(dt.hour);

            30 bcd_day = bin2bcd(dt.day);

            31 bcd_date = bin2bcd(dt.date);

            32 bcd_mon = bin2bcd(dt.month);

            33 bcd_year = bin2bcd(dt.year);

            34

            35 Write_DS1337(DS1337_SECONDS_REG,bcd_sec);

            36 Write_DS1337(DS1337_MINUTES_REG,bcd_min);

            37 Write_DS1337(DS1337_HOURS_REG,bcd_hrs);

            38 Write_DS1337(DS1337_DAY_OF_WEEK_REG,bcd_day);

            39 Write_DS1337(DS1337_DATE_REG,bcd_date);

            40 Write_DS1337(DS1337_MONTH_REG,bcd_mon);

            41 Write_DS1337(DS1337_YEAR_REG,bcd_year);

            42 }

            43

            44 void DS1337_Get_time()

            45 {

            46 u8 bcd_sec,bcd_min,bcd_hrs,bcd_day,bcd_date,bcd_mon,bcd_year;

            47

            48 bcd_sec = Read_DS1337(DS1337_SECONDS_REG);

            49 bcd_min = Read_DS1337(DS1337_MINUTES_REG);

            50 bcd_hrs = Read_DS1337(DS1337_HOURS_REG);

            51 bcd_day = Read_DS1337(DS1337_DAY_OF_WEEK_REG);

            52 bcd_date = Read_DS1337(DS1337_DATE_REG);

            53 bcd_mon = Read_DS1337(DS1337_MONTH_REG);

            54 bcd_year = Read_DS1337(DS1337_YEAR_REG);

            55

            56 Time.second = bcd2bin(bcd_sec);

            57 Time.minute = bcd2bin(bcd_min);

            58 Time.hour = bcd2bin(bcd_hrs);

            59 Time.day = bcd2bin(bcd_day);

            60 Time.date = bcd2bin(bcd_date);

            61 Time.month = bcd2bin(bcd_mon);

            62 Time.year = bcd2bin(bcd_year);

            63 }

            第1行的函數(shù)為初始化DS1337,讀取狀態(tài)寄存器,如果最高位不為0,則初始化時(shí)間。第23行的函數(shù)為設(shè)置時(shí)間,包括年月日星期時(shí)分秒。第44行的函數(shù)為讀取時(shí)間。

            1 #ifdef eclipse

            2 void SMBUS_ISR(void)

            3 #else

            4 void SMBUS_ISR (void) interrupt ESMB0_VECTOR

            5 #endif

            6 {

            7 switch (SMB0STA)

            8 {

            9 case SMB_START: //起始條件已發(fā)送

            10 SMB0DAT = (COMMAND 0xFE);

            11 STA = 0;

            12 break;

            13 case SMB_RP_START: //重復(fù)起始條件已發(fā)送

            14 SMB0DAT = COMMAND;

            15 STA = 0;

            16 break;

            17 case SMB_MTADDACK: //地址 + WRITE已發(fā)送,收到ACK

            18 SMB0DAT = wr_data[0];

            19 break;

            20 case SMB_MTADDNACK: //地址 + WRITE已發(fā)送,收到NACK。

            21 STO = 1; //發(fā)送STOP + START重試

            22 STA = 1;

            23 break;

            24 case SMB_MTDBACK: //數(shù)據(jù)字節(jié)已發(fā)送,收到ACK。

            25 switch(Mode)

            26 {

            27 case 1:

            28 wrnumber--;

            29 if(wrnumber)

            30 SMB0DAT = wr_data[1];

            31 else

            32 {

            33 STO = 1;

            34 SMB_BUSY=0;

            35 }

            36 break;

            37 case 0:

            38 STA = 1;

            39 break;

            40 default:

            41 STO = 1;

            42 SMB_BUSY = 0;

            43 break;

            44 }

            45 break;

            46 case SMB_MTDBNACK: //數(shù)據(jù)字節(jié)

            46 case SMB_MTDBNACK: //數(shù)據(jù)字節(jié)已發(fā)送,收到NACK。

            47 STO = 1;

            48 STA = 1;

            49 break;

            50 case SMB_MTARBLOST: //競爭失敗

            51 STO = 1;

            52 STA = 1;

            53 break;

            54 case SMB_MRADDACK: //地址 + READ 已發(fā)送。收到ACK

            55 AA = 0;

            56 break;

            57 case SMB_MRADDNACK: //地址 + READ 已發(fā)送。收到NACK

            58 STO = 0;

            59 STA = 1;

            60 break;

            61 case SMB_MRDBACK: //收到數(shù)據(jù)字節(jié)。ACK已發(fā)送

            62 get_data = SMB0DAT;

            63 SMB_BUSY = 0; //完成

            64 STO = 1;

            65 break;

            66 case SMB_MRDBNACK: //收到數(shù)據(jù)字節(jié)。NACK已發(fā)送

            67 get_data = SMB0DAT;

            68 SMB_BUSY = 0;

            69 STO = 1;

            70 break;

            71 default:

            72 STO = 1;

            73 break;

            74 }

            75 SI = 0;

            76 }

            SMBus中斷,需要手動清除中斷標(biāo)志。

            3.3 實(shí)物

            



          關(guān)鍵詞: ds1337 時(shí)鐘芯片 c8051

          評論


          相關(guān)推薦

          技術(shù)專區(qū)

          關(guān)閉
          看屁屁www成人影院,亚洲人妻成人图片,亚洲精品成人午夜在线,日韩在线 欧美成人 (function(){ var bp = document.createElement('script'); var curProtocol = window.location.protocol.split(':')[0]; if (curProtocol === 'https') { bp.src = 'https://zz.bdstatic.com/linksubmit/push.js'; } else { bp.src = 'http://push.zhanzhang.baidu.com/push.js'; } var s = document.getElementsByTagName("script")[0]; s.parentNode.insertBefore(bp, s); })();