新聞中心

        EEPW首頁 > 物聯網與傳感器 > 設計應用 > DS1337 時鐘芯片在 C8051F 上的實現

        DS1337 時鐘芯片在 C8051F 上的實現

        作者: 時間:2017-10-13 來源:網絡 收藏

          一、DS1337介紹

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

        本文引用地址:http://www.104case.com/article/201710/365833.htm

          1.1 DS1337的引腳說明

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

          

          圖1 DS1337引腳示意圖

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

          SCL:串行時鐘輸入,用來在總線上同步數據傳輸。

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

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

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

          1.2 時間寄存器

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

          1.3 控制寄存器和狀態寄存器

          DS1337中有一個控制寄存器和一個狀態寄存器,可用于控制實時時鐘、鬧鐘和方波的輸出。

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

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

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

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

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

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

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

          A1F、A2F:鬧鐘標志位。為1時,表示鬧鐘設定時間與當前時間匹配,并產生中斷輸出。

          

          圖2 DS1337寄存器

          1.4 對DS1337的讀與寫

          

          圖3 DS1337 寫寄存器

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

          

          圖4 DS1337 讀寄存器

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

          二、SMBus總線介紹

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

          

          圖5 SMBus 配置

          2.1握手

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

          開始:該條件啟動一次傳輸過程。當SCL為高電平時SDA上出現一個下降沿。

          結束:該條件結束一次傳輸過程。當SCL為高電平時SDA上出現一個上升沿。

          應答:也稱為ACK,接收器件發送該信號表示確認。例如,在器件X收到一個字節后,它將發送一個ACK確認傳輸成功。ACK條件是在SCL為高時采樣到SDA為低電平。

          非應答:也稱為NACK,這是在SCL為高電平時采樣到SDA為高電平。當接收器件不能產生ACK時,發送器件看到的是NACK。在典型的數據傳輸中,收到NACK信號表示所尋址的從器件沒有準備好或不在總線上。一個處于接收狀態的主器件發送NACK表示這是傳輸的最后一個字節。圖2給出了握手信號時序。

          

          圖6 SMBus 時序

          2.2 傳輸方式

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

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

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

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

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

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

          

          圖7 寫操作

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

          

          圖8 讀操作

          2.3 SMBus特殊功能寄存器

          對 SMBus 串行接口的訪問和控制是通過 5 個特殊功能寄存器來實現的:控制寄存器 SMB0CN、時鐘速率寄存器 SMB0CR、地址寄存器 SMB0ADR、數據寄存器 SMB0DAT 和狀態寄存器 SMB0STA。系統器件可以有一個或多個 SMBus 串行接口。

          2.3.1 控制寄存器SMB0CN

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

          

          

          2.3.2 時鐘速率寄存器SMB0CR

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

          

          其中,SMB0CR是一個負數的補碼。因此,對于100kHz的SCL頻率和16MHz的SYSCLK,應向SMB0CL裝入-80,即0xB0。

          2.3.3 地址寄存器 SMB0ADR

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

          2.3.4 數據寄存器 SMB0DAT

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

          1.3.5 狀態寄存器 SMB0STA

          共有28個可能的SMBus狀態,每個狀態對應一個唯一的狀態碼。狀態碼的高5位是可變的,而一個有效狀態碼的

          低3位固定為0(當SI=1時)。因此所有有效的狀態碼都是8的整數倍。

          

          

          

          

          三、在C8051F 上的實現

          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行的函數是將BCD碼轉化為二進制數。第35行的函數是將二進制數轉化為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行的函數初始化SMBus總線。第11行的函數為DS1337寫操作。第26行的函數為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行的函數為初始化DS1337,讀取狀態寄存器,如果最高位不為0,則初始化時間。第23行的函數為設置時間,包括年月日星期時分秒。第44行的函數為讀取時間。

          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: //起始條件已發送

          10 SMB0DAT = (COMMAND 0xFE);

          11 STA = 0;

          12 break;

          13 case SMB_RP_START: //重復起始條件已發送

          14 SMB0DAT = COMMAND;

          15 STA = 0;

          16 break;

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

          18 SMB0DAT = wr_data[0];

          19 break;

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

          21 STO = 1; //發送STOP + START重試

          22 STA = 1;

          23 break;

          24 case SMB_MTDBACK: //數據字節已發送,收到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: //數據字節

          46 case SMB_MTDBNACK: //數據字節已發送,收到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 已發送。收到ACK

          55 AA = 0;

          56 break;

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

          58 STO = 0;

          59 STA = 1;

          60 break;

          61 case SMB_MRDBACK: //收到數據字節。ACK已發送

          62 get_data = SMB0DAT;

          63 SMB_BUSY = 0; //完成

          64 STO = 1;

          65 break;

          66 case SMB_MRDBNACK: //收到數據字節。NACK已發送

          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中斷,需要手動清除中斷標志。

          3.3 實物

          



        關鍵詞: ds1337 時鐘芯片 c8051

        評論


        相關推薦

        技術專區

        關閉
        主站蜘蛛池模板: 林口县| 翁牛特旗| 阿城市| 化州市| 绥江县| 中牟县| 阳泉市| 延川县| 利辛县| 芒康县| 北辰区| 简阳市| 乌审旗| 英山县| 甘肃省| 阳城县| 鄂托克旗| 博野县| 登封市| 建阳市| 镇平县| 襄城县| 长兴县| 山东| 荔波县| 黔西县| 夏津县| 河西区| 泸州市| 桐庐县| 昭苏县| 绿春县| 牡丹江市| 通海县| 中阳县| 达孜县| 集安市| 昌邑市| 日土县| 千阳县| 新河县|