一、DS1337介绍
DS1337串行实时时钟芯片是一种低功耗、悉数选用BCD码的时钟日历芯片,它带有两个可编程的守时闹钟和一个可编程的方波输出。其地址和数据可经过I2C总线串行传输,能供给秒、分、时、日、星期、月和年等信息。
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 什物