单片机与高精度时钟芯片DS3231的接口应用

合集下载

使用STM32和DS3231 RTC:设置并获取时间和日期

使用STM32和DS3231 RTC:设置并获取时间和日期

使用STM32和DS3231 RTC:设置并获取时间和日期——笔记在本文中,将使用STM32开发一个驱动程序,用于在DS3231中设置和获取时间存储。

在本文中,将介绍以下内容:DS3231模块。

与STM32F411核-64的连接。

源文件。

产品图片DS3231模块DS3231是一款低成本、极其精确的I 2 C实时时钟(RTC),集成温度补偿晶体振荡器(TCXO)和晶体。

该器件集成了电池输入,并在器件的主电源中断时保持精确的计时。

晶体谐振器的集成提高了设备的长期精度,并减少了生产线中的零件数量。

RTC 维护秒、分钟、小时、星期、日期、月份和年份信息。

对于少于31 天的月份,月底的日期会自动调整,包括闰年的更正。

时钟以24 小时制或12 小时制运行,带有AM/PM 指示器。

提供两个可编程时间闹钟和一个可编程方波输出。

地址和数据通过I 2 C双向总线串行传输。

该模块可在3.3 或5 V 电压下工作,适用于许多开发平台或微控制器。

电池输入为3V,典型的CR2032 3V电池可以为模块供电并保持信息超过一年。

与STM32F411核-64的连接:在开始开发驱动器之前,需要I2C多读和多写才能使DS3231工作。

我们首先创建名称为ds3231.h 的新头文件。

在头文件中,我们将声明一个结构如下:该结构将包含以下内容:秒。

分。

小时。

月中的某天。

月。

年。

计算所需的其他数据。

此外,声明以下三个函数:首先是设置时间和数据,并以结构为参数。

第二个是从DS3231读取时间,并获取指向结构的指针。

第三个功能将打印时间。

因此,整个头文件如下所示:创建一个名称为ds3231.c 的新源代码。

在此声明以下宏:此外,还有两个功能:第一个将 dec 转换为 BCD 的方法:第二个是将 BCD 转换为 dec :为了设置时间和日期:由于我们已经超过了2000 年,因此我们将世纪位设置为1:并从给定年份中减去2000。

然后将变量转换为BCD,并将变量发送到DS3231,以设置时间和日期。

MAXIM DS3231M 数据手册

MAXIM DS3231M 数据手册
300
Standby Supply Current (I2C Inactive: Includes Temperature Conversion Current)
Temperature Conversion Current (I2C Inactive)
ICCS
VCC = +3.63V VCC = VCCMAX
Fs
0
Fs
250 300
ms
3
DS3231M
±5ppm、I2C实时时钟
AC ELECTRICAL CHARACTERISTICS—I2C INTERFACE
(VCC or VBAT = +2.3V to +5.5V, TA = -40NC to +85NC, unless otherwise noted. Typical values are at VCC = +3.3V, VBAT = +3.0V, and TA = +25NC, unless otherwise noted.) (Note 5, Figure 1)
(VCC = 0V, VBAT = +2.3V to +5.5V, TA = -40NC to +85NC, unless otherwise noted. Typical values are at VCC = 0V, VBAT = +3.0V,
and TA = +25NC, unless otherwise noted.)
CONDITIONS VBAT = +3.63V VBAT = VBATMAX VBAT = +3.63V, EN32KHZ = 0 VBAT = VBATMAX, EN32KHZ = 0 VBAT = +3.63V VBAT = VBATMAX

C8051F120与DS3231(高精度内置温补RTC实时时钟)的硬件IIC通信子程序(扫描方式)

C8051F120与DS3231(高精度内置温补RTC实时时钟)的硬件IIC通信子程序(扫描方式)

D S3231.t x t;************************************************************************************ ;作用:I I C通信(D S3231时钟芯片),扫描方式.;单片机型号:C8051F120;通信器件:D S3231内置温补R T C高精度时钟;作者:C Z M3000;占用资源:A C C,R0,R2,R3,R7;************************************************************************************ ;R3:D S3231的内部寄存器地址;************************************************************************************ D S3231W:;写入程序!S E T B S T A;发送起始D W1:M O V A,S M B0S T A;状态查询C J N E A,#08H,D W1;起始条件是否发出C L R S I;清中断标志C L R S T A;清起始条件位M O V W D T C N,#0A5H;喂狗M O V S M B0D A T,#11010000B;器件地址(D S3231)+读写状态位发送D W2:M O V A,S M B0S T A;状态查询C J N E A,#18H,D W2;器件地址+读写状态位是否成功发送并收到A C KM O V W D T C N,#0A5H;喂狗M O V S M B0D A T,R3;待写数据目标地址发送C L R S I;清中断标志D W3:M O V A,S M B0S T A;状态查询C J N E A,#28H,D W3;数据目标地址是否成功发送并收到A C KM O V W D T C N,#0A5H;喂狗C L R S I;清中断标志D W X:M O V S M B0D A T,@R0;数据发送D W4:M O V A,S M B0S T A;状态查询C J N E A,#28H,D W4;数据是否成功发出并收到A C KC L R S I;清中断标志I N C R0;数据指针加一M O V W D T C N,#0A5H;喂狗D J N Z R2,D W X;数据是否全部发送完毕S E T B S T O;发送结束条件L C A L L D E L A Y;调延时程序C L R S I;清中断标志R E T;************************************************************************************* ;R2:读取器件(D S3231)寄存器数据个数.;************************************************************************************* D S3231R:;读取程序!S E T B A A;开应答标志位S E T B S T A;发送起始条件D R1:M O V A,S M B0S T A;状态查询C J N E A,#08H,D R1;起始条件是否发出M O V W D T C N,#0A5H;喂狗M O V S M B0D A T,#11010001B;器件地址+读写状态位发送C L R S T A;清起始条件位C L R S I;清中断标志D R2:M O V A,S M B0S T A;状态查询C J N E A,#40H,D R2;器件地址+读写状态位是否成功发送并收到A C KD R:M O V W D T C N,#0A5H;喂狗C L R S I;清中断标志C J N E R2,#01H,D R3;数据接收是否还剩一个字节C L R A A;清应答标志位D R4:M O V A,S M B0S T A;状态查询C J N E A,#58H,D R4;数据是否接收完毕并返回N A C KM O V W D T C N,#0A5H;喂狗L J M P D R5;跳转D R3:M O V W D T C N,#0A5HM O V A,S M B0S T A;状态查询C J N E A,#50H,D R3;数据是否接收完毕并返回N A C KD R5:第 1页D S3231.t x tM O V A,S M B0D A T;数据载入M O V W D T C N,#0A5H;喂狗M O V@R0,A;数据转存I N C R0;数据指针加一D J N Z R2,D R;数据是否全部接受完毕S E T B S T O;发送结束条件L C A L L D E L A Y;调延时程序C L R S I;清中断标志位R E T;************************************************************************************** ;R2:欲读取器件地址的前一个地址(如:欲读取02H地址以后的数据,则R2为01H).;************************************************************************************** D S3231Z:;地址发送程序!S E T B S T A;发送起始条件D Z1:M O V A,S M B0S T A;状态查询C J N E A,#08H,D Z1;起始条件是否发出M O V W D T C N,#0A5H;喂狗C L R S T A;清起始条件位C L R S I;清中断标志M O V S M B0D A T,#11010000B;器件地址+读写状态位发送D Z2:M O V A,S M B0S T A;状态查询C J N E A,#18H,D Z2;器件地址+读写状态位是否成功发送并收到A C KM O V W D T C N,#0A5H;喂狗C L R S IM O V S M B0D A T,R2;器件寄存器地址发送D Z3:M O V A,S M B0S T A;状态查询C J N E A,#28H,D Z3;器件寄存器地址是否成功发送并收到A C KM O V W D T C N,#0A5H;喂狗C L R S I;清中断标志S E T B S T O;发送结束条件L C A L L D E L A Y;调延时程序C L R S I;清中断标志R E T;***************************************************************************************D E L A Y:;延时程序!M O V R7,#00HD E L A Y1:N O PN O PD J N Z R7,DE L A Y1M O V W D T C N,#0A5H;喂狗R E T;1284周期,25M时钟时约50微秒.;*************************************************************************************** ;初始化程序!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!;*************************************************************************************** R e s e t_S o u r c e s_I n i t:m o v W D T C N,#007hr e tT i m e r_I n i t:m o v S F R P A G E,#T M R2_P A G Em o v T M R2C N,#004hm o v T M R2C F,#008hm o v R C A P2L,#082hm o v R C A P2H,#0F D hr e tU A R T_I n i t:m o v S F R P A G E,#U A R T0_P A G Em o v S C O N0,#050hm o v S S T A0,#015hr e tS M B u s_I n i t:m o v S F R P A G E,#S M B0_P A G Em o v S M B0C N,#040hm o v S M B0C R,#0E C hr e t第 2页D S3231.t x t P o r t_I O_I n i t:;P0.0-T X0(U A R T0),O p e n-D r a i n,D i g i t a l;P0.1-R X0(U A R T0),O p e n-D r a i n,D i g i t a l;P0.2-S D A(S M B u s),O p e n-D r a i n,D i g i t a l;P0.3-S C L(S M B u s),O p e n-D r a i n,D i g i t a l;P0.4-I N T0(T m r0),O p e n-D r a i n,D i g i t a l;P0.5-U n a s s i g n e d,O p e n-D r a i n,D i g i t a l;P0.6-U n a s s i g n e d,O p e n-D r a i n,D i g i t a l;P0.7-U n a s s i g n e d,O p e n-D r a i n,D i g i t a l;P1.0-U n a s s i g n e d,O p e n-D r a i n,D i g i t a l;P1.1-U n a s s i g n e d,O p e n-D r a i n,D i g i t a l;P1.2-U n a s s i g n e d,O p e n-D r a i n,D i g i t a l;P1.3-U n a s s i g n e d,O p e n-D r a i n,D i g i t a l;P1.4-U n a s s i g n e d,O p e n-D r a i n,D i g i t a l;P1.5-U n a s s i g n e d,O p e n-D r a i n,D i g i t a l;P1.6-U n a s s i g n e d,O p e n-D r a i n,D i g i t a l;P1.7-U n a s s i g n e d,O p e n-D r a i n,D i g i t a l;P2.0-U n a s s i g n e d,O p e n-D r a i n,D i g i t a l;P2.1-U n a s s i g n e d,O p e n-D r a i n,D i g i t a l;P2.2-U n a s s i g n e d,O p e n-D r a i n,D i g i t a l;P2.3-U n a s s i g n e d,O p e n-D r a i n,D i g i t a l;P2.4-U n a s s i g n e d,O p e n-D r a i n,D i g i t a l;P2.5-U n a s s i g n e d,O p e n-D r a i n,D i g i t a l;P2.6-U n a s s i g n e d,O p e n-D r a i n,D i g i t a l;P2.7-U n a s s i g n e d,O p e n-D r a i n,D i g i t a l;P3.0-U n a s s i g n e d,O p e n-D r a i n,D i g i t a l;P3.1-U n a s s i g n e d,O p e n-D r a i n,D i g i t a l;P3.2-U n a s s i g n e d,O p e n-D r a i n,D i g i t a l;P3.3-U n a s s i g n e d,O p e n-D r a i n,D i g i t a l;P3.4-U n a s s i g n e d,O p e n-D r a i n,D i g i t a l;P3.5-U n a s s i g n e d,O p e n-D r a i n,D i g i t a l;P3.6-U n a s s i g n e d,O p e n-D r a i n,D i g i t a l;P3.7-U n a s s i g n e d,O p e n-D r a i n,D i g i t a lm o v S F R P A G E,#C O N F I G_P A G Em o v X B R0,#005hm o v X B R1,#004hm o v X B R2,#040hr e tO s c i l l a t o r_I n i t:m o v S F R P A G E,#C O N F I G_P A G Em o v O S C I C N,#083hr e tI n t e r r u p t s_I n i t:m o v I E,#091hr e t;I n i t i a l i z a t i o n f u n c t i o n f o r d e v i c e,;C a l l I n i t_D e v i c e f r o m y o u r m a i n p r o g r a mI n i t_D e v i c e:l c a l l R e s e t_S o u r c e s_I n i tl c a l l T i m e r_I n i tl c a l l U A R T_I n i tl c a l l S M B u s_I n i tl c a l l P o r t_I O_I n i tl c a l l O s c i l l a t o r_I n i tl c a l l I n t e r r u p t s_I n i tr e te n d第 3页。

maxim ds3231实时时钟应用笔记使用指南faq全集

maxim ds3231实时时钟应用笔记使用指南faq全集

Maxim DS3231实时时钟应用笔记、使用指南、FAQ全集Maxim DS3231实时时钟应用笔记、使用指南、FAQ全集2013-03-14 07:11:00分享到:标签:DS3231Maxim实时时钟RTC<a target='_blank'href='/www/delivery/ck.php?n=9ac65 e3'><img border='0' alt=''src='/www/delivery/avw.php?zoneid= 212&n=9ac65e3'/></a&a mp;amp;amp;gt;编者按:Maxim Integrated新型实时时钟(RTC) DS3231,内部集成了TCXO、RTC和32.768kHz晶体,并采用低成本、标准型、16引脚SOIC封装。

在-40°C 至+85°C温度范围内,计时精度为±2分钟/年。

这一出色性能使DS3231成为当前要求高计时精度应用的最佳解决方案。

而RTC的其它集成功能也扩展了系统应用领域,适合那些对计时精度要求极高的应用。

应用包括:服务器、电表、安防及门禁控制系统、车队管理、远程信息处理系统、GPS导航装置、POS终端以及ATM。

除计时精度高之外,DS3231还具有一些其它功能, 这些功能扩展了系统主机的附加功能和选择范围。

该器件内部集成了一个非常精确的数字温度传感器,可通过I2C* 接口对其进行访问(如同时间一样)。

这个温度传感器的精度为±3°C。

DS3231高精度时钟模块程序

DS3231高精度时钟模块程序

模块参数:1.尺寸:38mm(长)*22mm(宽)*14mm(高)2.重量:8g3.工作电压:3.3--5.5V4.时钟芯片:高精度时钟芯片DS32315.时钟精度:0-40℃范围内,精度2ppm,年误差约1分钟6.带2个日历闹钟7.可编程方波输出8.实时时钟产生秒、分、时、星期、日期、月和年计时,并提供有效期到2100年的闰年补偿9.芯片内部自带温度传感器,精度为±3℃10.存储芯片:AT24C32(存储容量32K)11.IIC总线接口,最高传输速度400KHz(工作电压为5V时)12.可级联其它IIC设备,24C32地址可通过短路A0/A1/A2修改,默认地址为0x5713.带可充电电池LIR2032,保证系统断电后,时钟任然正常走动接线说明,以Arduino uno r3为例:SCL→A5SDA→A4VCC→5VGND→GND代码部分:#include <reg51.h>#include <intrins.h>#define uchar unsigned char#define uint unsigned intsbit SDA=P3^6; //模拟I2C数据传送位SDAsbit SCL=P3^7; //模拟I2C时钟控制位SCLsbit INT=P3^2;sbit RESET=P3^3;sbit led0=P1^0;sbit led1=P1^1;sbit led2=P1^2;sbit led3=P1^3;sbit led4=P1^4;sbit led5=P1^5;sbit led6=P1^6;sbit led7=P1^7;bit ack; //应答标志位#define DS3231_WriteAddress 0xD0 //器件写地址#define DS3231_ReadAddress 0xD1 //器件读地址#define DS3231_SECOND 0x00 //秒#define DS3231_MINUTE 0x01 //分#define DS3231_HOUR 0x02 //时#define DS3231_WEEK 0x03 //星期#define DS3231_DAY 0x04 //日#define DS3231_MONTH 0x05 //月#define DS3231_YEAR 0x06 //年//闹铃1#define DS3231_SALARM1ECOND 0x07 //秒#define DS3231_ALARM1MINUTE 0x08 //分#define DS3231_ALARM1HOUR 0x09 //时#define DS3231_ALARM1WEEK 0x0A //星期/日//闹铃2#define DS3231_ALARM2MINUTE 0x0b //分#define DS3231_ALARM2HOUR 0x0c //时#define DS3231_ALARM2WEEK 0x0d //星期/日#define DS3231_CONTROL 0x0e //控制寄存器#define DS3231_STATUS 0x0f //状态寄存器#define BSY 2 //忙#define OSF 7 //振荡器停止标志#define DS3231_XTAL 0x10 //晶体老化寄存器#define DS3231_TEMPERATUREH 0x11 //温度寄存器高字节(8位)#define DS3231_TEMPERATUREL 0x12 //温度寄存器低字节(高2位)uchar code dis_code[11]={0xc0,0xf9,0xa4,0xb0, // 0,1,2,30x99,0x92,0x82,0xf8,0x80,0x90, 0xff}; // 4,5,6,7,8,9,offuchar data dis_buf[8];uchar data dis_index;uchar data dis_digit;uchar BCD2HEX(uchar val) //BCD转换为Byte{uchar temp;temp=val&0x0f;val>>=4;val&=0x0f;val*=10;temp+=val;return temp;}uchar HEX2BCD(uchar val) //B码转换为BCD码{uchar i,j,k;i=val/10;j=val;k=j+(i<<4);return k;}void delayus(uint us){while (us--);}void Start_I2C(){SDA=1; //发送起始条件的数据信号delayus(1);SCL=1;delayus(5); //起始条件建立时间大于4.7us,延时SDA=0; //发送起始信号delayus(5); // 起始条件锁定时间大于4μsSCL=0; //钳住I2C总线,准备发送或接收数据delayus(2);}void Stop_I2C(){SDA=0; //发送结束条件的数据信号delayus(1); //发送结束条件的时钟信号SCL=1; //结束条件建立时间大于4usdelayus(5);SDA=1; //发送I2C总线结束信号delayus(4);}void SendByte(uchar c){uchar BitCnt;for(BitCnt=0;BitCnt<8;BitCnt++) //要传送的数据长度为8位 {if((c<<BitCnt)&0x80)SDA=1;//判断发送位elseSDA=0;delayus(1);SCL=1;//置时钟线为高,通知被控器开始接收数据位delayus(5); //保证时钟高电平周期大于4μsSCL=0;}delayus(2);SDA=1;//8位发送完后释放数据线,准备接收应答位delayus(2);SCL=1;delayus(3);if(SDA==1)ack=0;elseack=1;//判断是否接收到应答信号SCL=0;delayus(2);}uchar RcvByte(){uchar retc;uchar BitCnt;retc=0;SDA=1; //置数据线为输入方式for(BitCnt=0;BitCnt<8;BitCnt++){delayus(1);SCL=0; //置时钟线为低,准备接收数据位delayus(5); //时钟低电平周期大于4.7μsSCL=1; //置时钟线为高使数据线上数据有效delayus(3);retc=retc<<1;if(SDA==1)retc=retc+1; //读数据位,接收的数据位放入retc中delayus(2);}SCL=0;delayus(2);return(retc);}void Ack_I2C(bit a){if(a==0)SDA=0; //在此发出应答或非应答信号 elseSDA=1;delayus(3);SCL=1;delayus(5); //时钟低电平周期大于4μsSCL=0; //清时钟线,钳住I2C总线以便继续接收delayus(2);}uchar write_byte(uchar addr, uchar write_data){Start_I2C();SendByte(DS3231_WriteAddress);if (ack == 0)return 0;SendByte(addr);if (ack == 0)return 0;SendByte(write_data);if (ack == 0)return 0;Stop_I2C();delayus(10);return 1;}uchar read_current(){uchar read_data;Start_I2C();SendByte(DS3231_ReadAddress);if(ack==0)return(0);read_data = RcvByte();Ack_I2C(1);Stop_I2C();return read_data;}uchar read_random(uchar random_addr) {Start_I2C();SendByte(DS3231_WriteAddress);if(ack==0)return(0);SendByte(random_addr);if(ack==0)return(0);return(read_current());}void ModifyTime(uchar yea,uchar mon,uchar da,uchar hou,uchar min,uchar sec) {uchar temp=0;temp=HEX2BCD(yea);write_byte(DS3231_YEAR,temp); //修改年temp=HEX2BCD(mon);write_byte(DS3231_MONTH,temp); //修改月temp=HEX2BCD(da);write_byte(DS3231_DAY,temp); //修改日temp=HEX2BCD(hou);write_byte(DS3231_HOUR,temp); //修改时temp=HEX2BCD(min);write_byte(DS3231_MINUTE,temp); //修改分temp=HEX2BCD(sec);write_byte(DS3231_SECOND,temp); //修改秒}void TimeDisplay(uchar Dhour,uchar Dmin,uchar Dsec){dis_buf[7]=dis_code[Dhour / 10]; // 时十位dis_buf[6]=dis_code[Dhour % 10]; // 时个位dis_buf[4]=dis_code[Dmin / 10]; // 分十位dis_buf[3]=dis_code[Dmin % 10]; // 分个位dis_buf[1]=dis_code[Dsec / 10]; // 秒十位dis_buf[0]=dis_code[Dsec % 10]; // 秒个位dis_buf[2]=0xbf; // 显示"-"dis_buf[5]=0xbf;}void DateDisplay(uchar Dyear,uchar Dmonth,uchar Dday){dis_buf[7]=dis_code[Dyear / 10]; // 年十位dis_buf[6]=dis_code[Dyear % 10]; // 年个位dis_buf[4]=dis_code[Dmonth / 10]; // 月十位dis_buf[3]=dis_code[Dmonth % 10]; // 月个位dis_buf[1]=dis_code[Dday / 10]; // 天十位dis_buf[0]=dis_code[Dday % 10]; // 天个位dis_buf[2]=0xbf; // 显示"-"dis_buf[5]=0xbf;}void get_show_time(void){uchar Htemp1,Htemp2,Mtemp1,Mtemp2,Stemp1,Stemp2;Htemp1=read_random(DS3231_HOUR); //时 24小时制Htemp1&=0x3f;Htemp2=BCD2HEX(Htemp1);Mtemp1=read_random(DS3231_MINUTE); //分Mtemp2=BCD2HEX(Mtemp1);Stemp1=read_random(DS3231_SECOND); //秒Stemp2=BCD2HEX(Stemp1);TimeDisplay(Htemp2,Mtemp2,Stemp2);}void get_show_date(void){uchar Ytemp1,Ytemp2,Mtemp1,Mtemp2,Dtemp1,Dtemp2;Ytemp1=read_random(DS3231_YEAR); //年Ytemp2=BCD2HEX(Ytemp1);Mtemp1=read_random(DS3231_MONTH); //月Mtemp2=BCD2HEX(Mtemp1);Dtemp1=read_random(DS3231_DAY); //日Dtemp2=BCD2HEX(Dtemp1);DateDisplay(Ytemp2,Mtemp2,Dtemp2);}void get_show_Temperature(void){uchar Ttemp1,Ttemp2,Ttemp3,Ttemp4;Ttemp1=read_random(DS3231_TEMPERATUREH); //温度高字节 Ttemp2=BCD2HEX(Ttemp1);Ttemp3=read_random(DS3231_TEMPERATUREL); //温度低字节Ttemp4=BCD2HEX(Ttemp3);DateDisplay(0,Ttemp2,Ttemp4);}void timer0() interrupt 1{TH0=0xFC;TL0=0x17;P2=0xff; // 先关闭所有数码管P0=dis_buf[dis_index]; // 显示代码传送到P0口P2=dis_digit;if (dis_digit & 0x80)dis_digit=(dis_digit << 1) | 0x1;elsedis_digit=(dis_digit << 1);dis_index++;dis_index&=0x07; // 8个数码管全部扫描完一遍之后,再回到第一个开始下一次扫描}void main(){uint ii = 0;RESET=0x1; //DS3231复位操作,正常操作下不需要每次都复位delayus(5000);led0=0;led1=0;led2=0;led3=0;led4=0;P0=0xff;P2=0xff;dis_digit=0xfe;dis_index=0;TimeDisplay(12, 5, 18);TMOD=0x11; // 定时器0, 1工作模式1, 16位定时方式 TH0=0xFC;TL0=0x17;TCON=0x01;IE=0x82; // 使能timer0,1 中断TR0=1;if (write_byte(DS3231_CONTROL, 0x1C) == 0)led0=1;if (write_byte(DS3231_STATUS, 0x00) == 0)led1=1;ModifyTime(10,6,13,15,30,00); //初始化时钟,2010/6/13,15/30/00//小时采用24小时制while(1){//get_show_date(); //显示日期//get_show_Temperature(); //显示温度get_show_time(); //显示时间delayus(50000);}}。

DS3231数据资料,应用笔记,技术文章,使用问题全集

DS3231数据资料,应用笔记,技术文章,使用问题全集

DS3231数据资料,应用笔记,技术文章,使用问题全集DS3231实时时钟在宽工作温度范围内具有±2分钟/年的出色精度编者按:新型实时时钟(RTC) DS3231,内部集成了TCXO、RTC和32.768kHz晶体,并采用低成本、标准型、16引脚SOIC封装。

在-40°C至+85°C温度范围内,计时精度为±2分钟/年。

这一出色性能使DS3231成为当前要求高计时精度应用的最佳解决方案。

而RTC的其它集成功能也扩展了系统应用领域。

【数据手册】DS3231超高精度、I²C接口、集成RTC/TCXO/晶体(中文版)DS3231是低成本、高精度I²C实时时钟(RTC),具有集成的温补晶振(TCXO)和晶体。

该器件包含电池输入端,断开主电源时仍可保持精确的计时。

集成晶振提高了器件的长期精确度,并减少了生产线的元件数量。

【应用笔记】DS323x系列实时时钟性能比较Maxim是实时时钟(RTC)产品的引领者, 多数情况下,RTC的精度主要取决于晶振频率随温度的变化。

因此,对晶体进行高精度的温度补偿能够提高这些器件的时钟精度。

本文列出了几款RTC (DS3231、DS3232、DS3234、DS32B35和DS32C35)的性能差异,帮助用户查找合适的器件。

本还重点讨论了内置MEMS谐振器的DS3231M,用于替代晶振方案。

DS323x高精度实时时钟的功耗考虑DS3231/DS3232通过设置温度更新周期,能够在保持较高时钟精度的同时大大降低器件的电流损耗。

DS3231在整个工业温度范围内(-40°C至+85°C)提供±3.5ppm的精度。

器件每隔64秒(64s)测量一次温度,通过调节晶体的负载电容,使其在指定温度达到0ppm的精度,最终达到提高时钟精度的目的。

DS3231与8051微控制器的接口本应用笔记介绍了DS3231与8051微控制器的连接方式,并提供了一个基本的接口程序。

DS3231高精度时钟模块程序

DS3231高精度时钟模块程序

模块参数:1.尺寸:38mm(长)*22mm(宽)*14mm(高)2.重量:8g3.工作电压:3.3--5.5V4.时钟芯片:高精度时钟芯片DS32315.时钟精度:0-40℃范围内,精度2ppm,年误差约1分钟6.带2个日历闹钟7.可编程方波输出8.实时时钟产生秒、分、时、星期、日期、月和年计时,并提供有效期到2100年的闰年补偿9.芯片内部自带温度传感器,精度为±3℃10.存储芯片:AT24C32(存储容量32K)11.IIC总线接口,最高传输速度400KHz(工作电压为5V时)12.可级联其它IIC设备,24C32地址可通过短路A0/A1/A2修改,默认地址为0x5713.带可充电电池LIR2032,保证系统断电后,时钟任然正常走动接线说明,以Arduino uno r3为例:SCL→A5SDA→A4VCC→5VGND→GND代码部分:#include <reg51.h>#include <intrins.h>#define uchar unsigned char#define uint unsigned intsbit SDA=P3^6; //模拟I2C数据传送位SDAsbit SCL=P3^7; //模拟I2C时钟控制位SCLsbit INT=P3^2;sbit RESET=P3^3;sbit led0=P1^0;sbit led1=P1^1;sbit led2=P1^2;sbit led3=P1^3;sbit led4=P1^4;sbit led5=P1^5;sbit led6=P1^6;sbit led7=P1^7;bit ack; //应答标志位#define DS3231_WriteAddress 0xD0 //器件写地址#define DS3231_ReadAddress 0xD1 //器件读地址#define DS3231_SECOND 0x00 //秒#define DS3231_MINUTE 0x01 //分#define DS3231_HOUR 0x02 //时#define DS3231_WEEK 0x03 //星期#define DS3231_DAY 0x04 //日#define DS3231_MONTH 0x05 //月#define DS3231_YEAR 0x06 //年//闹铃1#define DS3231_SALARM1ECOND 0x07 //秒#define DS3231_ALARM1MINUTE 0x08 //分#define DS3231_ALARM1HOUR 0x09 //时#define DS3231_ALARM1WEEK 0x0A //星期/日//闹铃2#define DS3231_ALARM2MINUTE 0x0b //分#define DS3231_ALARM2HOUR 0x0c //时#define DS3231_ALARM2WEEK 0x0d //星期/日#define DS3231_CONTROL 0x0e //控制寄存器#define DS3231_STATUS 0x0f //状态寄存器#define BSY 2 //忙#define OSF 7 //振荡器停止标志#define DS3231_XTAL 0x10 //晶体老化寄存器#define DS3231_TEMPERATUREH 0x11 //温度寄存器高字节(8位)#define DS3231_TEMPERATUREL 0x12 //温度寄存器低字节(高2位)uchar code dis_code[11]={0xc0,0xf9,0xa4,0xb0, // 0,1,2,30x99,0x92,0x82,0xf8,0x80,0x90, 0xff}; // 4,5,6,7,8,9,off uchar data dis_buf[8];uchar data dis_index;uchar data dis_digit;uchar BCD2HEX(uchar val) //BCD转换为Byte{uchar temp;temp=val&0x0f;val>>=4;val&=0x0f;val*=10;temp+=val;return temp;uchar HEX2BCD(uchar val) //B码转换为BCD码{uchar i,j,k;i=val/10;j=val;k=j+(i<<4);return k;}void delayus(uint us){while (us--);}void Start_I2C(){SDA=1; //发送起始条件的数据信号delayus(1);SCL=1;delayus(5); //起始条件建立时间大于4.7us,延时SDA=0; //发送起始信号delayus(5); // 起始条件锁定时间大于4μsSCL=0; //钳住I2C总线,准备发送或接收数据 delayus(2);}void Stop_I2C(){SDA=0; //发送结束条件的数据信号delayus(1); //发送结束条件的时钟信号SCL=1; //结束条件建立时间大于4usdelayus(5);SDA=1; //发送I2C总线结束信号delayus(4);}void SendByte(uchar c){uchar BitCnt;for(BitCnt=0;BitCnt<8;BitCnt++) //要传送的数据长度为8位{if((c<<BitCnt)&0x80)SDA=1; //判断发送位 elseSDA=0;delayus(1);SCL=1; //置时钟线为高,通知被控器开始接收数据位delayus(5); //保证时钟高电平周期大于4μsSCL=0;}delayus(2);SDA=1; //8位发送完后释放数据线,准备接收应答位delayus(2);SCL=1;delayus(3);if(SDA==1)ack=0;elseack=1; //判断是否接收到应答信号SCL=0;delayus(2);}uchar RcvByte(){uchar retc;uchar BitCnt;retc=0;SDA=1; //置数据线为输入方式for(BitCnt=0;BitCnt<8;BitCnt++){delayus(1);SCL=0; //置时钟线为低,准备接收数据位delayus(5); //时钟低电平周期大于4.7μsSCL=1; //置时钟线为高使数据线上数据有效delayus(3);retc=retc<<1;if(SDA==1)retc=retc+1; //读数据位,接收的数据位放入retc中 delayus(2);}SCL=0;delayus(2);return(retc);}void Ack_I2C(bit a){if(a==0)SDA=0; //在此发出应答或非应答信号elseSDA=1;delayus(3);SCL=1;delayus(5); //时钟低电平周期大于4μsSCL=0; //清时钟线,钳住I2C总线以便继续接收delayus(2);}uchar write_byte(uchar addr, uchar write_data){Start_I2C();SendByte(DS3231_WriteAddress);if (ack == 0)return 0;SendByte(addr);if (ack == 0)return 0;SendByte(write_data);if (ack == 0)return 0;Stop_I2C();delayus(10);return 1;}uchar read_current(){uchar read_data;Start_I2C();SendByte(DS3231_ReadAddress);if(ack==0)return(0);read_data = RcvByte();Ack_I2C(1);Stop_I2C();return read_data;}uchar read_random(uchar random_addr) {Start_I2C();SendByte(DS3231_WriteAddress);if(ack==0)return(0);SendByte(random_addr);if(ack==0)return(0);return(read_current());}void ModifyTime(uchar yea,uchar mon,uchar da,uchar hou,uchar min,uchar sec){uchar temp=0;temp=HEX2BCD(yea);write_byte(DS3231_YEAR,temp); //修改年temp=HEX2BCD(mon);write_byte(DS3231_MONTH,temp); //修改月temp=HEX2BCD(da);write_byte(DS3231_DAY,temp); //修改日temp=HEX2BCD(hou);write_byte(DS3231_HOUR,temp); //修改时temp=HEX2BCD(min);write_byte(DS3231_MINUTE,temp); //修改分temp=HEX2BCD(sec);write_byte(DS3231_SECOND,temp); //修改秒}void TimeDisplay(uchar Dhour,uchar Dmin,uchar Dsec){dis_buf[7]=dis_code[Dhour / 10]; // 时十位dis_buf[6]=dis_code[Dhour % 10]; // 时个位dis_buf[4]=dis_code[Dmin / 10]; // 分十位dis_buf[3]=dis_code[Dmin % 10]; // 分个位dis_buf[1]=dis_code[Dsec / 10]; // 秒十位dis_buf[0]=dis_code[Dsec % 10]; // 秒个位dis_buf[2]=0xbf; // 显示"-"dis_buf[5]=0xbf;}void DateDisplay(uchar Dyear,uchar Dmonth,uchar Dday){dis_buf[7]=dis_code[Dyear / 10]; // 年十位dis_buf[6]=dis_code[Dyear % 10]; // 年个位dis_buf[4]=dis_code[Dmonth / 10]; // 月十位dis_buf[3]=dis_code[Dmonth % 10]; // 月个位dis_buf[1]=dis_code[Dday / 10]; // 天十位dis_buf[0]=dis_code[Dday % 10]; // 天个位dis_buf[2]=0xbf; // 显示"-"dis_buf[5]=0xbf;}void get_show_time(void){uchar Htemp1,Htemp2,Mtemp1,Mtemp2,Stemp1,Stemp2;Htemp1=read_random(DS3231_HOUR); //时 24小时制Htemp1&=0x3f;Htemp2=BCD2HEX(Htemp1);Mtemp1=read_random(DS3231_MINUTE); //分Mtemp2=BCD2HEX(Mtemp1);Stemp1=read_random(DS3231_SECOND); //秒Stemp2=BCD2HEX(Stemp1);TimeDisplay(Htemp2,Mtemp2,Stemp2);}void get_show_date(void){uchar Ytemp1,Ytemp2,Mtemp1,Mtemp2,Dtemp1,Dtemp2;Ytemp1=read_random(DS3231_YEAR); //年Ytemp2=BCD2HEX(Ytemp1);Mtemp1=read_random(DS3231_MONTH); //月Mtemp2=BCD2HEX(Mtemp1);Dtemp1=read_random(DS3231_DAY); //日Dtemp2=BCD2HEX(Dtemp1);DateDisplay(Ytemp2,Mtemp2,Dtemp2);}void get_show_Temperature(void){uchar Ttemp1,Ttemp2,Ttemp3,Ttemp4;Ttemp1=read_random(DS3231_TEMPERATUREH); //温度高字节Ttemp2=BCD2HEX(Ttemp1);Ttemp3=read_random(DS3231_TEMPERATUREL); //温度低字节Ttemp4=BCD2HEX(Ttemp3);DateDisplay(0,Ttemp2,Ttemp4);}void timer0() interrupt 1{TH0=0xFC;TL0=0x17;P2=0xff; // 先关闭所有数码管P0=dis_buf[dis_index]; // 显示代码传送到P0口P2=dis_digit;if (dis_digit & 0x80)dis_digit=(dis_digit << 1) | 0x1;elsedis_digit=(dis_digit << 1);dis_index++;dis_index&=0x07; // 8个数码管全部扫描完一遍之后,再回到第一个开始下一次扫描}void main(){uint ii = 0;RESET=0x1; //DS3231复位操作,正常操作下不需要每次都复位delayus(5000);led0=0;led1=0;led2=0;led3=0;led4=0;P0=0xff;P2=0xff;dis_digit=0xfe;dis_index=0;TimeDisplay(12, 5, 18);TMOD=0x11; // 定时器0, 1工作模式1, 16位定时方式TH0=0xFC;TL0=0x17;TCON=0x01;IE=0x82; // 使能timer0,1 中断TR0=1;if (write_byte(DS3231_CONTROL, 0x1C) == 0)led0=1;if (write_byte(DS3231_STATUS, 0x00) == 0)led1=1;ModifyTime(10,6,13,15,30,00); //初始化时钟,2010/6/13,15/30/00//小时采用24小时制while(1){//get_show_date(); //显示日期//get_show_Temperature(); //显示温度get_show_time(); //显示时间delayus(50000);} }。

MAXIM DS3231 说明书

MAXIM DS3231 说明书

_________________________________概述DS3231是低成本、高精度I 2C 实时时钟(RTC),具有集成的温补晶体振荡器(TCXO) 和晶体。

该器件包含电池输入端,断开主电源时仍可保持精确的计时。

集成晶体振荡器提高了器件的长期精确度,并减少了生产线的元件数量。

DS3231提供商用级和工业级温度范围,采用16引脚、300mil 的SO 封装。

RTC 保持秒、分、时、星期、日期、月和年信息。

少于31天的月份,将自动调整月末日期,包括闰年补偿。

时钟的工作格式可以是24小时或带AM /PM 指示的12小时格式。

提供两个可编程日历闹钟和一路可编程方波输出。

地址与数据通过I 2C 双向总线串行传输。

精密的、经过温度补偿的电压基准和比较器用来监视V CC 状态,检测电源故障、提供复位输出,并在必要时自动切换到备用电源。

另外,RST 监视引脚可以作为手动按钮输入以产生外部复位信号。

_________________________________应用服务器电表远程信息处理系统GPS_________________________________特性♦0°C 至+40°C 范围内精度为±2ppm ♦-40°C 至+85°C 范围内精度为±3.5ppm ♦为连续计时提供备用电池输入♦工作温度范围商用级:0°C 至+70°C 工业级:-40°C 至+85°C♦低功耗♦实时时钟提供秒、分、时、星期、日期、月、年信息,并提供有效期到2100年的闰年补偿♦两个日历闹钟♦可编程方波输出♦快速(400kHz) I 2C 接口♦3.3V 工作电压♦数字温度传感器输出:精度为±3°C ♦老化修正寄存器♦RST 输入/输出DS3231高精度、I 2C 集成RTC/TCXO/晶体______________________________________________Maxim Integrated Products1Rev 1; 2/05______________________________定购信息引脚配置在数据资料的最后部分给出。

DS3231在嵌入式环境文件系统中的应用

DS3231在嵌入式环境文件系统中的应用

DS3231在嵌入式环境文件系统中的应用徐健;陈永冰;刘勇;贾玉柱【期刊名称】《单片机与嵌入式系统应用》【年(卷),期】2014(14)11【摘要】为满足嵌入式环境中文件系统精准的提供时间功能,使存储在外部介质SD 卡中的文件包含创建、修改、访问等详细时间信息,提出采用高精度实时时钟芯片 DS3231为文件系统提供连续精准的时间信息的解决方案。

介绍了 SD 卡存储结构,详细探讨了 FAT32文件系统在嵌入式环境中的移植方法,设计了 DS3231与C8051F500单片机进行通信时的硬件接口连接,通过 I2 C 总线实现对 DS3231时间信息的读写。

系统测试表明,DS3231能够连续不断地给嵌入式文件系统提供精准时间信息。

%In order to provide the accurate time information of file system in embedded environment and make files stored in the external SD card contain detailed time information about creation,modification and access.The paper proposes a solution that high-precision real-time clock chip DS323 1 provides continuous accurate time information to the file system.The paper introduces the storage structure of SD card,discusses the transplant method of FAT32 file system in embedded environment,designs hardware connection interface between DS323 1 and microcontroller C805 1F500,and realizes the read/write operation of time information of DS323 1 by I2 C bus.System test shows that DS323 1 can continuously provide accurate time information to the embedded file system.【总页数】4页(P15-17,20)【作者】徐健;陈永冰;刘勇;贾玉柱【作者单位】海军工程大学导航工程系,武汉430033;海军工程大学导航工程系,武汉 430033;海军工程大学导航工程系,武汉 430033;海军工程大学导航工程系,武汉 430033【正文语种】中文【中图分类】TP368.1【相关文献】1.混合文件系统在嵌入式智能车辆控制器中的应用 [J], 周清杰;黄晋英;马航;崔晓静2.嵌入式多媒体应用中的 Flash 文件系统 [J], 谢文辉3.JFFS2文件系统在嵌入式Linux根文件系统中的应用研究 [J], 耿增涛;史永宏4.Sysfs文件系统在嵌入式开发中的应用 [J], 刘江5.Sysfs文件系统在嵌入式开发中的应用 [J], 刘江;因版权原因,仅展示原文概要,查看原文内容请购买。

DIY高精度时钟、温度显示器Ds3231+12864+ds18b20+89c51

DIY高精度时钟、温度显示器Ds3231+12864+ds18b20+89c51

DIY高精度时钟、温度显示器Ds3231+12864+ds18b20+89c51 硬件:程序:#include<reg52.h>#include<intrins.h>#include<stdlib.h>#define uchar unsigned char#define uint unsigned int/*端口定义*/sbit LCD_RS=P2^6;sbit LCD_RW=P2^5;sbit LCD_EN=P2^4;sbit LCD_PSB=P2^3;sbit DQ=P3^7; //18b20sbit SDA=P1^4; //ds32321 //模拟I2C数据传送位SDA sbit SCL=P1^3; //模拟I2C时钟控制位SCL //***按键功能****//////***K1停止时间显示****//////***K2选择修改位置****//////***K3进行加1的修改****//////***K4将修改写入ds3231,同时启动时间显示****//sbit K1=P3^2;sbit K2=P3^3;sbit K3=P3^4;sbit K4=P3^5;//定义变量uchar numbr[10]="0123456789"; //字模uchar dis4[]=" "; // 第四行显示自己添加uchar t[]=" . ℃" ; //18b20uint sdata,xiaoshu1,xiaoshu2; //整数、小数1位、小数2位bit fg=1; //温度正负标志uchar tempL=0,tempH=0; // 变量uchar year,month,date,hour,min,sec; // ds3231uchar a[]="2011年22月33日";uchar b[]="11时22分33秒";///函数//******************延时子程序*******************************//这个延时程序的具体延时时间是time=i*8+10,适用于小于2ms的延时//************************************************************void delay(unsigned char i){for(i;i>0;i--);}//***********************************************************// 延时子程序//************************************************************void delay1ms(uchar j){while(j!=0){uchar i;for(i=124;i>0;i--); //延时124*8+10=1002usj--;}}/**************************12864部分*************************************//**************************12864部分*************************************//*写指令数据到LCDRS=L——表示DB0-DB7为显示指令数据RW=L——表示DB0-DB7数据被write(当E=“H-L”,指令数据被写到IR或DR)E=高脉冲此时DB0-DB7=指令码*/void write_cmd(uchar cmd){LCD_RS=0;LCD_EN=0;P0=cmd;delay1ms(5);LCD_EN=1;delay1ms(5);LCD_EN=0;}/*设定显示位置*/void lcd_pos(uchar X, uchar Y){uchar pos;if(X == 0){X = 0x80;}else if(X == 1){X = 0x90;}else if(X == 2){X = 0x88;}else if(X == 3){X = 0x98;}pos = X + Y;write_cmd(pos); //显示地址}/*写显示数据到LCD*//*RS=H ——表示DB0-DB7为显示数据RW=L ——RW=L,E='H-L',DB0-DB7数据被写到IR或DRE=高脉冲DB0-DB7=显示数据*/void write_dat(uchar dat){LCD_RS=1;LCD_EN=0;P0=dat;delay1ms(5);LCD_EN=1;delay1ms(5);LCD_EN=0;}/*LCD初始化*/void lcd_init(){ uint i;LCD_PSB=1; //并口方式write_cmd(0x30); //基本操作指令delay1ms(5);write_cmd(0x0c); //打开显示,光标关闭delay1ms(5);write_cmd(0x01); //清除LCD显示类容delay1ms(5);lcd_pos(3,0);i=0;while(dis4[i]!='\0'){delay1ms(1);write_dat(dis4[i]);delay1ms(1);i++;}}/**********************************18b20*************************************** *********//**********************************18b20*************************************** *********/void Init_DS18B20(void) //初始化{uchar x=0;DQ=1; //DQ先置高delay(8); //稍延时DQ=0; //发送复位脉冲delay(80); //延时(>480us)DQ=1; //拉高数据线delay(5); //等待(15~60us)x=DQ; //用X的值来判断初始化有没有成功,18B20存在的话X=0,否则X=1delay(20);}//**********读一个字节************//ReadOneChar(void) //主机数据线先从高拉至低电平1us以上,再使数据线升为高电平,从而产生读信号{unsigned char i=0; //每个读周期最短的持续时间为60us,各个读周期之间必须有1us以上的高电平恢复期unsigned char dat=0;for (i=8;i>0;i--) //一个字节有8位{DQ=1;delay(1);DQ=0;dat>>=1;DQ=1;if(DQ)dat|=0x80;delay(4);}return(dat);}//*********************** **写一个字节**************************//void WriteOneChar(unsigned char dat){unsigned char i=0; //数据线从高电平拉至低电平,产生写起始信号。

DS3231高精度时钟程序代码(单片机STC89c52RC与1602显示)

DS3231高精度时钟程序代码(单片机STC89c52RC与1602显示)

//DS3231,经测试,日期,时间,星期,温度可以用1602显示#in elude <reg51.h>#in elude vintrin s.h>#defi ne uchar un sig ned char#defi ne uint un sig ned int#define yh 0x80 //第一行的初始位置#defi ne er 0x80+0x40 // 第二行初始位置sbit wr=P1A1;sbit rs=P1A。

;sbit en=卩2人5;sbit SDA=P3A6; //模拟I2C数据传送位 SDAsbit SCL=P3A7; //模拟I2C时钟控制位 SCL sbit INT=P3A2;sbit key1=P1A7; // 功能键,修改键sbitkey2=P3A4;// 上调键sbitkey3=P3A5;// 下调键sbit RESET=P3A3;bit ack;// 应答标志位#define DS3231 _WriteAddress 0xD0 // 器件写地址#define DS3231 _ReadAddress 0xD1// 器件读地址#define DS3231_SECOND 0x00 // 秒#define DS3231 _MINUTE 0x01 // 分#define DS3231 _HOUR 0x02 // 时#define DS3231 _WEEK 0x03 // 星期#define DS3231 _DAY 0x04 // 日#define DS3231_MONTH 0x05 // 月#define DS3231 _YEAR 0x06 // 年// 闹铃 1#define DS3231 _SALARM1ECOND 0x07 // 秒#define DS3231 _ALARM1MINUTE 0x08 // 分#define DS3231 _ALARM1HOUR 0x09 // 时#define DS3231 _ALARM1WEEK 0x0A// 星期 / 日// 闹铃 2#define DS3231 _ALARM2MINUTE 0x0b // 分#define DS3231 _ALARM2HOUR0x0c // 时可编辑#define DS3231_TEMPERATUREH 0x11#define DS3231_TEMPERATUREL 0x12 uchara,miao,shi,fen,ri,yue,nian,week,temp1,temp2,key1n,temp; uchar code tab1[]={"2017- - FRI"}; uchar code tab2[]={" : : ."};uchar HEX2BCD(uchar val) //B 码转换为 BCD 码{uchar k;k=(val)/10*16+(val)%10; return k;}uchar BCD_Decimal(uchar bcd){uchar Decimal; Decimal=bcd>>4;return(Decimal=Decimal*10+(bcd&=0x0F));#define DS3231_ALARM2WEEK #define DS3231_CONTROL #define DS3231_STATUS #define BSY #define OSF0x0d // 星期 / 日0x0e // 控制寄存器 0x0f // 状态寄存器2 // 忙7// 振荡器停止标志#define DS3231_XTAL0x10 // 晶体老化寄存器// 温度寄存器高字节 // 温度寄存器低字节 (8 位 ) (高 2 位 )}void delayus(uint us){while (us--);}void Start_I2C(){SDA=1; // 发送起始条件的数据信号 delayus(1);SCL=1;delayus(5); // 起始条件建立时间大于 4.7us, 延时SDA=0; // 发送起始信号delayus(5); //起始条件锁定时间大于4阳SCL=0; //钳住 I2C 总线,准备发送或接收数据delayus(2);}void Stop_I2C(){SDA=0; // 发送结束条件的数据信号delayus(1); // 发送结束条件的时钟信号SCL=1; // 结束条件建立时间大于 4us delayus(5);SDA=1; // 发送 I2C 总线结束信号delayus(4);}void SendByte(uchar c){uchar BitCnt;for(BitCnt=0;BitCnt<8;BitCnt ++){if((c<<BitCnt)&0x80)SDA=1;elseSDA=0;delayus(1);SCL=1;数据位delayus(5);SCL=0;// 要传送的数据长度为 8 位// 判断发送位// 置时钟线为高,通知被控器开始接收//保证时钟咼电平周期大于 4阳delayus(2);SDA=1; //8 位发送完后释放数据线,准备接收应答位delayus(2);SCL=1;delayus(3);if(SDA==1)ack=0;elseack=1; // 判断是否接收到应答信号SCL=0;delayus(2);}uchar RcvByte(){uchar retc;uchar BitCnt;retc=0;SDA=1; // 置数据线为输入方式for(BitCnt=0;BitCnt<8;BitCnt++)SCL=0;delayus(5);SCL=1;delayus(3);retc=retc<<1;if(SDA==1)retc=retc+1;delayus(2);}SCL=0;delayus(2);return(retc);}// 置时钟线为低,准备接收数据位//时钟低电平周期大于 4.7 Q//置时钟线为高使数据线上数据有效// 读数据位 ,接收的数据位放入 retc 中void Ack_I2C(bit a){if(a==0)SDA=0; else // 在此发出应答或非应答信号SDA=1;SCL=1;delayus(5); //时钟低电平周期大于4阴SCL=0; // 清时钟线,钳住 I2C 总线以便继续接收delayus(2);}uchar write_byte(uchar addr, uchar write_data) {Start_I2C();SendByte(DS3231_WriteAddress);if (ack == 0)return 0;SendByte(addr);if (ack == 0)return 0;SendByte(write_data);if (ack == 0)return 0;Stop_I2C();return 1;}uchar read_current(){uchar read_data;Start_I2C();SendByte(DS3231_ReadAddress);if(ack==0)return(0);read_data = RcvByte();Ack_I2C(1);Stop_I2C();return read_data;}uchar read_random(uchar random_addr) {Start_I2C();SendByte(DS3231_WriteAddress);if(ack==0)SendByte(random_addr);if(ack==0)return(0);return(read_current()); }void ModifyTime(uchar yea,uchar sec,uchar week){uchar temp=0;temp=HEX2BCD(yea);write_byte(DS3231_YEAR,temp);temp=HEX2BCD(mon);write_byte(DS3231_MONTH,temp);temp=HEX2BCD(da);write_byte(DS3231_DAY,temp);temp=HEX2BCD(hou);write_byte(DS3231_HOUR,temp); mon,uchar da,uchar hou,uchar// 修改年// 修改月// 修改日// 修改时min,uchartemp=HEX2BCD(min);write_byte(DS3231_MINUTE,temp); // 修改分temp=HEX2BCD(sec);write_byte(DS3231_SECOND,temp); // 修改秒temp=HEX2BCD(week);write_byte(DS3231_WEEK,temp); // 修改星期}**************** 液晶写入********************** write_1602com(uchar com)// 液晶写入指令函数{ rs=0;// 置为写入命令P0=com;// 送入数据delayus(1000);en=1;// 拉高使能端delayus(1000);en=0;// 完成高脉冲}write_1602dat(uchar dat){rs=1;// 置为写入数据P0=dat;// 送入数据delayus(1000);en=1;delayus(1000);en=0;}*******************over*********************lcd_init()// 液晶初始化函数{ wr=0;write_1602com(0x38);// 设置液晶工作模式write_1602com(0x0c);// 开显示不显示光标write_1602com(0x06);// 整屏不移动,指针加一write_1602com(0x01);write_1602com(yh+1);// 字符写入的位置for(a=0;a<14;a++){write_1602dat(tab1[a]);//delay(3);}write_1602com(er);for(a=0;a<12;a++){//delay(3);}write_1602com(er+14); // 写温度符号write_1602dat(0xdf);write_1602dat(0x43);void write_sfm(uchar add,uchar dat)// 写时分秒及温度{ uchar gw,sw;gw=dat%10;sw=dat/10;write_1602com(er+add);write_1602dat(0x30+sw);write_1602dat(0x30+gw);}void write_nyr(uchar add,uchar dat) // 写日期{ uchar gw,sw;gw=dat%10;sw=dat/10;write_1602com(yh+add);write_1602dat(0x30+sw);write_1602dat(0x30+gw);}void write_week(uchar week)// 写星期函数{write_1602com(yh+0x0c);switch(week){case 1:write_1602dat('M');//delay(5);write_1602dat('O');//delay(5);write_1602dat('N');break;case 2:write_1602dat('T');//delay(5);write_1602dat('U');//delay(5);write_1602dat('E');break;case 3:write_1602dat('W');//delay(5);break;case 4:write_1602dat('T');//delay(5);write_1602dat('H');//delay(5);write_1602dat('U');break;case 5:write_1602dat('F');//delay(5);write_1602dat('R');//delay(5);write_1602dat('I');break;case 6:write_1602dat('S');//delay(5);write_1602dat('T');//delay(5);write_1602dat('A');break;case 7:write_1602dat('S');//delay(5);write_1602dat('U');//delay(5);write_1602dat('N');break;}void keyscan(){if(key1==0)//key1 为功能键{delayus(5000);if(key1==0){while(!key1);key1n++;if(key1n==9)key1n=1;switch(key1n){case 1: TR0=0;// 关闭定时器//TR1=0;write_1602com(er+0x06);// 写入光标位置write_1602com(0x0f);// 设置光标为闪烁break;//write_1602com(0x0f);break;case 3: write_1602com(er+0);//shi//write_1602com(0x0f);break;case 4: write_1602com(yh+0x0d);//week//write_1602com(0x0f);break;case 5: write_1602com(yh+0x09);//ri//write_1602com(0x0f);break;case 6: write_1602com(yh+0x06);//yue//write_1602com(0x0f);break;case 7: write_1602com(yh+0x03);//nian//write_1602com(0x0f);break;case 8: write_1602com(0x0c);// 设置光标不闪烁write_sfm(6,miao);// 写入新的秒数temp=(miao)/10*16+(miao)%10;write_byte(DS3231_SECOND,temp); // 退出时修改秒write_1602com(er+6);temp=(fen)/10*16+(fen)%10;write_byte(DS3231_MINUTE,temp); // 修改分write_1602com(er+3);TR0=1;// 打开定时器break;}}}if(key1n!=0)// 当 key1 按下以下。

单片机与高精度时钟芯片DS3231的接口应用

单片机与高精度时钟芯片DS3231的接口应用

单片机与高精度时钟芯片DS3231的接口应用[1]. 前言在许多单片机的测控系统和家用电器中都含有时钟显示部分,最廉价的是直接使用单片机中的定时器,辅以一定的中断服务程序,构成时钟显示部分,这种方式是几乎不需要增加新的硬件即可实现,缺点是计时误差大,同时电源掉电不能保持时钟继续运行。

在相对要求较高的场合,则使用廉价的时钟芯片(如DS1302等等)辅以备用电池,计时精度略高,可满足一般的要求。

在这篇文章中,我们重点介绍高精度时钟电路DS3231的设计和应用。

在DS1302普及型时钟芯片,晶体均需外置,由于晶体的离散性,很难选择到精度很高的器件,同时也没有温度补偿电路,不同的温度环境下,晶体的特性也在变化,直接影响着时钟的振荡频率,较大的误差在所在所难免。

而DS3231高精度时钟芯片,将晶体和温度补偿均集成在芯片中,为提高计时精度提供了可能,实册证明,使用DS3231时钟芯片,误差可做到一年小于一分钟,甚至部分显示器误差可小于20秒/一年。

这对有相对精确时钟要求的应用场合是个理想的选择。

[2]. DS3231时钟芯片结构原理DS3231是一款高精度I2C实时时钟(RTC)器件,具有集成的温度补偿晶体振荡器(TCXO)。

该器件包含电池输入端,断开主电源时仍可保持精确计时。

集成的晶体振荡器可提高器件的长期精确度。

DS3231的寄存器能保存秒、分、时、星期、日期、月、年和闹钟设置等信息。

少于31天的月份,可自动调整月末日期,包括闰年补偿。

时钟的工作格式为24小时或带AM/PM指示的12小时格式。

DS3231提供两个可编程日历闹钟和一路可编程方波输出。

DS3231与单片机通过I2C双向串行总线传输地址与数据。

下图为DS3231典型应用电路,图中可看出,DS3231几乎不需要外部元件。

[3]. DS3231时钟芯片结构如图1所示,DS3231的主要组成部分有8个模块,划分为4个功能组:TCXO、电源控制、按钮复位和RTC。

单片机与高精度时钟芯片DS3231的接口应用【VIP专享】

单片机与高精度时钟芯片DS3231的接口应用【VIP专享】

普及型时钟一年。

这对有相对精确时钟要求的应。

该的寄存器能保存秒、分、时、星期、小时提供两个可编程日历闹钟和一路可双向串[3]. DS3231时钟芯片结构如图1所示,DS3231的主要组成部分有8个模块,划分为4个功能组:TCXO、电源控制、按钮复位和RTC。

1.32 kHz的TCXOTCXO包括温度传感器、振荡器和控制逻辑。

控制器读取片上温度传感器输出,使用查表法确定所需的电容,加上AGE寄存器的老化修正。

然后设置电容选择寄存器。

仅在温度变化或者用户启动的温度转换完成时,才加载包括AGE寄存器变化的新值。

VCC初次上电时就会读取温度值,然后每隔64 s读取一次。

2.DS3231的内部寄存器及功能DS3231寄存器地址为00h~12h,分别用于存放秒、分、时、星期、日期及闹钟设置信息。

在多字节访问期间,如果地址达到RAM空间的结尾12h处,将发生卷绕,此时定位到开始位置即00h单元。

DS3231的时间和日历信息通过读取相应的寄存器来设置和初始化。

用户辅助缓冲区用于防止内部寄存器更新时可能出现的错误。

读取时间和日历寄存器时,用户缓冲区在任何START条件下或者寄存器指针返回到零时与内部寄存器同步。

时间信息从这些辅助寄存器读取,此时时钟继续保持运行状态。

这样在读操作期间发生主寄存器更新时可以避免重新读取寄存器。

以控制寄存器(地址为0EH)为例,可以控制实时时钟、闹钟和方波输出。

其各bit定义如下表。

BIT7位:使能振荡器(EOEC)。

设定为逻辑0时,启动振荡器。

如果设定为逻辑1,在DS3231电源切换至VBAT时,振荡器停止。

初次上电时该位清零(逻辑0) 。

当DS3231由VCC供电时,振荡器与EOSC位的状态无关,始终保持工作状态。

BIT6位:电池备份的方波使能(BBSOW)。

当设定为逻辑1并且DS3231由VBAT引脚供电时,在没有加载VCC的情况下,该位使能方波输出。

当BB-SQW设定为逻辑0时,若VCC降至低于电源故障门限值,则INT/SQW引脚变为高阻抗。

ds3231 i2c上拉电阻

ds3231 i2c上拉电阻

ds3231 i2c上拉电阻DS3231是一款高精度实时时钟芯片,具有I2C接口,广泛应用于各种计时和时间管理系统中。

在使用DS3231时,为了保证I2C通信的可靠性,需要在SDA和SCL线上添加上拉电阻。

上拉电阻是一种电路设计中常用的元件,用于确保信号线的电平稳定。

在I2C通信中,SDA(串行数据线)和SCL(串行时钟线)是双向的,需要通过上拉电阻来确保信号线的电平在逻辑高电平时维持稳定。

DS3231芯片的I2C接口与主控设备(如单片机或微处理器)的I2C 接口相连接。

在I2C总线上,SDA和SCL线是串行传输数据和时钟信号的核心线路。

为了保证数据传输的可靠性,需要在SDA和SCL 线上分别添加上拉电阻。

上拉电阻的作用是将信号线拉高到逻辑高电平。

当总线上没有其他设备输出低电平时,上拉电阻可以确保信号线保持在逻辑高电平状态。

这样可以避免信号线因为没有输入信号而处于浮空状态,减少误差和干扰。

在DS3231芯片的I2C接口上添加上拉电阻的具体方法如下:1.选择合适的电阻值:一般情况下,上拉电阻的阻值通常在2.2kΩ到10kΩ之间。

选择合适的电阻值取决于总线的负载和通信距离。

如果总线上的设备较多或通信距离较长,可以选择较小的电阻值,以确保信号的稳定性。

2.连接上拉电阻:将一端连接到SDA线上,将另一端连接到VCC电源线上。

同样地,将另一根上拉电阻的一端连接到SCL线上,将另一端连接到VCC电源线上。

这样就完成了对SDA和SCL线的上拉电阻连接。

通过添加上拉电阻,可以在DS3231与主控设备之间建立稳定的I2C 通信链路。

上拉电阻能够确保信号线在逻辑高电平时保持稳定,提高了通信的可靠性和抗干扰能力。

需要注意的是,上拉电阻的阻值过小或过大都可能会影响通信的稳定性。

阻值过小会导致电流过大,消耗过多功耗;阻值过大会导致信号线上升时间延长,影响通信速率。

因此,在选择上拉电阻时需要综合考虑总线负载和通信距离等因素。

一种基于DS3231实现的高精度守时应用系统设计

一种基于DS3231实现的高精度守时应用系统设计

• 122•本文介绍了一种对守时指标要求较高的系统设计,提出了采用DS3231芯片,并结合软件时序流程控制的实现方法,从而较好地解决了基于高精度时间加密传输系统的守时问题,具有广泛的应用前景。

基于高精度时间加密传输系统在设计的过程中,需要考虑授时和守时两个方面的需求。

在满足授时条件的情况下,通过北斗授一种基于DS3231实现的高精度守时应用系统设计四川九洲电器集团有限责任公司 昌 畅 曾昱翔 汪国尧 罗 剑 孙 淼图2 系统硬件框图图1 系统授时守时流程时模块进行精准时间数据接收,并同步写入守时芯片,用于修正守时芯片的守时时间;当不满足授时条件的情况下,通过读取守时芯片内的守时时间,也能满足系统对时间精度的使用要求。

设计流程图如图1所示。

本系统硬件架构如图2所示。

守时芯片选用DS3231,芯片内部实现框图如图3所示。

该芯片支持双电源供电和I 2C配置接口,时钟精度 ≤ 6ppm ,待机模式工作电流≤10uA 。

以系统最大守时时间要求8h 计算,最大守时误差δ = 6×10-6 × 8 × 3600 = 0.1728s ,满足 ≤ 0.2s 的系统需求。

DS3231芯片内部关键寄存器描述如图4所示。

由图4所示,该芯片输出时间数据最小单位为秒,如果仅进行简单的寄存器读取,最大的读取误差将高达1s ,根本无法满足使用要求。

在FPGA 读取流程控制中,巧妙的利用DS3231内部闹钟机制,先读取一次时间数据<time1>,然后将<time1+2>秒作为闹钟计时写入DS3231,DS3231将在<time1+2>时刻产生闹钟中断信号INT ,FPGA 以此信号上升沿进行<time1+2>时间数据的加载,即可保证读取误差忽略不计。

FPGA 读取流程如图5所示。

目前,该设计已成功运用到多个产品中,经过不同环境条件下的反复使用表明,本文介绍的基于DS3231实现的高精度守时应用系统设计实现简单、成熟可靠,具有广泛的推广意义。

DS3231时钟芯片给文件系统提供时间问题

DS3231时钟芯片给文件系统提供时间问题

DS3231高精度时钟芯片自己跟单片机通过IIC总线通信,c8051f500单片机自带IIC通信接口,但本次实验中,我采用了通过I/O口模拟IIC总线方法。

出现问题:1.IIC通信本身有时序要求,但改变内部晶振大小后,依然可以正常通信,即数码管正常点亮。

2.在换为外部晶振时,程序总是停止在while((OSCXCN&0x80)==0)?原因是PORT_I/O_Init()没有在OSCILLATOR_init()之前初始化。

3.文件系统通过函数DWORD get_fattime()来给创建的文件提供日期时间。

1) DWORD tmr= 0x34c9a9a1;总共32位2) DWORD tmr=885587968;二者是相等的3) year=0x34;month=0xc9;DWORD tmr=((DWORD)(year)<<24) | ((DWORD)(month)<<16);4) DWORD tmr=((DWORD)(2006-1980)<<25) | (DWORD)(6)<<21) | ((DWORD)(9)<<16) | (DWORD)(0x0f)<<11) | ((DWORD)(0x15)<<5) | (DWORD)(53)>>1); // 2006. 6 .9, 15: 21: 525) DWORD tmr=((DWORD)(Year0+20)<<25) | (DWORD)(Month0)<<21) | ((DWORD)(Day0)<<16) | (DWORD)(Hour0)<<11) | ((DWORD)(Minute0)<<5) | (DWORD)(Second0)>>1); // 2014这里的Year0,Month0,Day0,Hour0。

发个DS3231的简易时钟,1602液晶显示、串口修改时间

发个DS3231的简易时钟,1602液晶显示、串口修改时间

发个DS3231的简易时钟,1602液晶显示、串口修改时间来极客工坊学习一个多月了,收获很大。

以前学过单片机,加上论坛里的各位前辈无私的奉献,现在学arduino很快上手,十分感谢极客工坊这个大家庭。

最近买了一块DS3231时钟模块,测试了3天,发现走时非常准确,一秒不差。

以前学单片机时用ds1302做过一个简易时钟,一天的误差在5秒左右,需要经常去校时。

来上个照片在论坛里搜索了一下关于DS3231的应用,发现不是很多,就打算将原来ds1302的程序移植到arduino上,但是将时钟芯片换成DS3231。

因为DS3231走时比较准确,不需要经常校时,打算程序里去除用按键修改时间的程序部分。

改为用串口发送字符串来修改时间。

另外,我个人认为桌面时钟就是看时间用的,加上闹钟的功能并不实用。

所以程序里也没有闹钟的功能。

简单介绍一下DS3231:1、I2C接口;2、实时时钟产生秒、分、时、星期、日期、月和年计时,并提供有效期到2100年的闰年补偿;3、两个日历闹钟;4、内部集成了一个数字温度传感器采用4线接法,顺便盗个图UNO 与 1602液晶连接6 -> D77 -> D68 -> D59 -> D410 -> EN11 -> RW12 -> RS顺便盗个图UNO 与 DS3231连接A4 -> SDAA5 -> SCL**************************************** 程序部分 ********************************************ARDUINO 代码1.#include <DS3231.h>2.#include <Wire.h>3.4.DS3231 Clock;5.bool Century=false;6.bool h12;7.bool PM;8.byte ADay, AHour, AMinute, ASecond, ABits;9.bool ADy, A12h, Apm;10.11.int year, month, date, DoW,week , hour, minute, second,temperature;12.13.String comdata = "";14.int numdata[7] = {0}, mark = 0;15./*1602液晶与UNO连接引脚16. 6 -> D717.7 -> D618.8 -> D519.9 -> D420.*/21.22.int LCD1602_RS=12;23.int LCD1602_RW=11;24.int LCD1602_EN=10;25.int DB[] = {6, 7, 8, 9};26.27.char dis1[16]={0},dis2[16]={0};28.29.char self_char[]={//1602液晶自定义符号30.0x08,0x0f,0x12,0x0f,0x0a,0x1f,0x02,0x02, //年31.0x0f,0x09,0x0f,0x09,0x0f,0x09,0x13,0x01, //月32.0x0f,0x09,0x09,0x0f,0x09,0x09,0x0f,0x00, //日33.0x18,0x18,0x07,0x08,0x08,0x08,0x07,0x00, //温度标志——摄氏度34.0x00,0x04,0x0E,0x1F,0x0E,0x04,0x00,0x00, //符号◆35.0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff, //全开36.0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, //37.0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 //38.};39.40.void LCD_Command_Write(int command)//写指令41.{42.int i,temp;43.digitalWrite( LCD1602_RS,LOW);44.digitalWrite( LCD1602_RW,LOW);45.digitalWrite( LCD1602_EN,LOW);46.47.temp=command & 0xf0;48.for(i=DB[0]; i <= 9; i++)49.{50.digitalWrite(i,temp & 0x80);51.temp <<= 1;52.}53.54.digitalWrite( LCD1602_EN,HIGH);55.delayMicroseconds(1);56.digitalWrite( LCD1602_EN,LOW);57.58.temp=(command & 0x0f)<<4;59.for(i=DB[0]; i <= 9; i++)60.{62.temp <<= 1;63.}64.65.digitalWrite( LCD1602_EN,HIGH);66.delayMicroseconds(1);67.digitalWrite( LCD1602_EN,LOW);68.}69.70.void LCD_Data_Write(int dat)//写数据71.{72.int i=0,temp;73.digitalWrite( LCD1602_RS,HIGH);74.digitalWrite( LCD1602_RW,LOW);75.digitalWrite( LCD1602_EN,LOW);76.77.temp=dat & 0xf0;78.for(i=DB[0]; i <= 9; i++)79.{80.digitalWrite(i,temp & 0x80);81.temp <<= 1;82.}83.84.digitalWrite( LCD1602_EN,HIGH);85.delayMicroseconds(1);86.digitalWrite( LCD1602_EN,LOW);87.88.temp=(dat & 0x0f)<<4;89.for(i=DB[0]; i <= 9; i++)90.{92.temp <<= 1;93.}94.95.digitalWrite( LCD1602_EN,HIGH);96.delayMicroseconds(1);97.digitalWrite( LCD1602_EN,LOW);98.}99.100.void LCD_SET_XY(int x, int y )//指定坐标,x为列,0~15,y为行,0为第一行,1为第二行。

AVR单片机与串行时钟器件DS3231的接口设计

AVR单片机与串行时钟器件DS3231的接口设计

AVR单片机与串行时钟器件DS3231的接口设计
高美珍;毛欲民;刘进军
【期刊名称】《国外电子元器件》
【年(卷),期】2007(000)005
【摘要】介绍了美国Dallas公司推出的低功耗时钟器件DS3231的结构和工作原理,DS3231能对年、月、日、时、分、秒计时,且具有温度补偿、闰年补偿等多种功能.给出了AVR单片机ATmega8与DS3231的软、硬件接口设计.
【总页数】5页(P47-51)
【作者】高美珍;毛欲民;刘进军
【作者单位】湖北师范学院,物理系,湖北,黄石,435002;湖北师范学院计算机科学系,湖北,黄石,435002;湖北师范学院计算机科学系,湖北,黄石,435002
【正文语种】中文
【中图分类】TP335
【相关文献】
1.AVR单片机与串行A/D的SPI接口设计 [J], 王红亮;杨晓
2.基于DS3231的高精度时钟接口设计 [J], 方洁;陈伟
3.单片机与串行时钟DS1307的接口设计 [J], 顾曙敏;朱幼莲
4.时钟芯片SD2200ELP与AVR单片机的接口设计 [J], 李浩;谭超;卢舟燕
5.实时钟芯片S-35180A的原理及其串行接口设计 [J], 毛欲民;高美珍
因版权原因,仅展示原文概要,查看原文内容请购买。

51单片机使用ds3231模块

51单片机使用ds3231模块

//DS3231某宝买的模块,5块不到的样子。

麻烦大家下载一下,不要直接复制。

89c52不能用1t的单片机。

//此修正版的文件可以解决之前的word下载后不能打开的蛋疼问题。

1602数据端口是P2如果需要修改,只有2个地方需要改。

#include <reg51.h>#include <intrins.h>#define uchar unsigned char#define uint unsigned int#define yh 0x80 //第一行的初始位置#define er 0x80+0x40 //第二行初始位置sbitrs=P0^7;//1602的3个端口sbitwr=P0^6;sbit en=P0^5;sbit SDA=P1^6; //模拟I2C数据传送位SDA 模块只使用了2个端口sbit SCL=P1^7; //模拟I2C时钟控制位SCL//sbit INT=P3^2;sbit key1=P3^5; //功能键,修改键这是3个按键,低电平有效,串联个4到10千欧的电阻到按键开关上,然后接地就行sbit key2=P3^4; //上调键sbit key3=P3^3; //下调键//sbit RESET=P3^3;bit ack; //应答标志位#define DS3231_WriteAddress 0xD0 //器件写地址#define DS3231_ReadAddress 0xD1 //器件读地址#define DS3231_SECOND 0x00 //秒#define DS3231_MINUTE 0x01 //分#define DS3231_HOUR 0x02 //时#define DS3231_WEEK 0x03 //星期#define DS3231_DAY 0x04 //日#define DS3231_MONTH 0x05 //月#define DS3231_YEAR 0x06 //年//闹铃1#define DS3231_SALARM1ECOND 0x07 //秒#define DS3231_ALARM1MINUTE 0x08 //分#define DS3231_ALARM1HOUR 0x09 //时#define DS3231_ALARM1WEEK 0x0A //星期/日//闹铃2#define DS3231_ALARM2MINUTE 0x0b //分#define DS3231_ALARM2HOUR 0x0c //时#define DS3231_ALARM2WEEK 0x0d //星期/日#define DS3231_CONTROL 0x0e //控制寄存器#define DS3231_STATUS 0x0f //状态寄存器#define BSY 2 //忙#define OSF 7 //振荡器停止标志#define DS3231_XTAL 0x10 //晶体老化寄存器#define DS3231_TEMPERATUREH 0x11 //温度寄存器高字节(8位) #define DS3231_TEMPERATUREL 0x12 //温度寄存器低字节(高2位)uchar a,miao,shi,fen,ri,yue,nian,week,temp1,temp2,key1n,temp;uchar code tab1[]={"2017- - FRI"};uchar code tab2[]={" : : ."};/*uchar HEX2BCD(ucharval) //B码转换为BCD码{uchar k;k=(val)/10*16+(val)%10;return k;}*/ucharBCD_Decimal(ucharbcd){uchar Decimal;Decimal=bcd>>4;return(Decimal=Decimal*10+(bcd&=0x0F));}void delayus(uint us){while (us--);}void Start_I2C(){SDA=1; //发送起始条件的数据信号delayus(1);SCL=1;delayus(5); //起始条件建立时间大于4.7us,延时SDA=0; //发送起始信号delayus(5); // 起始条件锁定时间大于4μsSCL=0; //钳住I2C总线,准备发送或接收数据delayus(2);}void Stop_I2C(){SDA=0; //发送结束条件的数据信号delayus(1); //发送结束条件的时钟信号SCL=1; //结束条件建立时间大于4usdelayus(5);SDA=1; //发送I2C总线结束信号delayus(4);}void SendByte(uchar c){ucharBitCnt;for(BitCnt=0;BitCnt<8;BitCnt++) //要传送的数据长度为8位{if((c<<BitCnt)&0x80)SDA=1; //判断发送位elseSDA=0;delayus(1);SCL=1; //置时钟线为高,通知被控器开始接收数据位delayus(5); //保证时钟高电平周期大于4μsSCL=0;}delayus(2);SDA=1; //8位发送完后释放数据线,准备接收应答位delayus(2);SCL=1;delayus(3);if(SDA==1)ack=0;elseack=1; //判断是否接收到应答信号SCL=0;delayus(2);}ucharRcvByte()ucharretc;ucharBitCnt;retc=0;SDA=1; //置数据线为输入方式for(BitCnt=0;BitCnt<8;BitCnt++){delayus(1);SCL=0; //置时钟线为低,准备接收数据位delayus(5); //时钟低电平周期大于4.7μsSCL=1; //置时钟线为高使数据线上数据有效delayus(3);retc=retc<<1;if(SDA==1)retc=retc+1; //读数据位,接收的数据位放入retc中delayus(2);}SCL=0;delayus(2);return(retc);}void Ack_I2C(bit a){if(a==0)SDA=0; //在此发出应答或非应答信号elseSDA=1;delayus(3);SCL=1;delayus(5); //时钟低电平周期大于4μsSCL=0; //清时钟线,钳住I2C总线以便继续接收delayus(2);}ucharwrite_byte(ucharaddr, ucharwrite_data){Start_I2C();SendByte(DS3231_WriteAddress);if (ack == 0)return 0;SendByte(addr);if (ack == 0)return 0;SendByte(write_data);if (ack == 0)return 0;Stop_I2C();delayus(10);return 1;}ucharread_current(){ucharread_data;Start_I2C();SendByte(DS3231_ReadAddress);if(ack==0)return(0);read_data = RcvByte();Ack_I2C(1);Stop_I2C();return read_data;}ucharread_random(ucharrandom_addr) {Start_I2C();SendByte(DS3231_WriteAddress);if(ack==0)return(0);SendByte(random_addr);if(ack==0)return(0);return(read_current());}/*void ModifyTime(ucharyea,ucharmon,ucharda,ucharhou,ucharmin,ucharsec,uchar week) {uchar temp=0;temp=HEX2BCD(yea);write_byte(DS3231_YEAR,temp); //修改年temp=HEX2BCD(mon);write_byte(DS3231_MONTH,temp); //修改月temp=HEX2BCD(da);write_byte(DS3231_DAY,temp); //修改日temp=HEX2BCD(hou);write_byte(DS3231_HOUR,temp); //修改时temp=HEX2BCD(min);write_byte(DS3231_MINUTE,temp); //修改分temp=HEX2BCD(sec);write_byte(DS3231_SECOND,temp); //修改秒temp=HEX2BCD(week);write_byte(DS3231_WEEK,temp); //修改星期}*//******************液晶写入************************/void write_1602com(uchar com)//液晶写入指令函数{rs=0;//置为写入命令P2=com;//送入数据delayus(1000);en=1;//拉高使能端delayus(1000);en=0;//完成高脉冲}void write_1602dat(uchardat){rs=1;//置为写入数据P2=dat;//送入数据delayus(1000);en=1;delayus(1000);en=0;}/*********************over***********************/ void lcd_init()//液晶初始化函数{ wr=0;write_1602com(0x38);//设置液晶工作模式write_1602com(0x0c);//开显示不显示光标write_1602com(0x06);//整屏不移动,指针加一write_1602com(0x01);write_1602com(yh+1);//字符写入的位置for(a=0;a<14;a++){write_1602dat(tab1[a]);//delay(3);}write_1602com(er);for(a=0;a<12;a++){write_1602dat(tab2[a]);//delay(3);}write_1602com(er+14); //写温度符号write_1602dat(0xdf);write_1602dat(0x43);}void write_sfm(ucharadd,uchardat)//写时分秒及温度{uchargw,sw;gw=dat%10;sw=dat/10;write_1602com(er+add);write_1602dat(0x30+sw);write_1602dat(0x30+gw);}void write_nyr(ucharadd,uchardat) //写日期{uchargw,sw;gw=dat%10;sw=dat/10;write_1602com(yh+add);write_1602dat(0x30+sw);write_1602dat(0x30+gw);}void write_week(uchar week)//写星期函数{write_1602com(yh+0x0c);switch(week){case 1:write_1602dat('M');//delay(5);write_1602dat('O');//delay(5);write_1602dat('N');break;case 2:write_1602dat('T');//delay(5);write_1602dat('U');//delay(5);write_1602dat('E');break;case 3:write_1602dat('W');//delay(5);write_1602dat('E');//delay(5);write_1602dat('D');break;case 4:write_1602dat('T');//delay(5);write_1602dat('H');//delay(5);write_1602dat('U');break;case 5:write_1602dat('F');//delay(5);write_1602dat('R');//delay(5);write_1602dat('I');break;case 6:write_1602dat('S');//delay(5);write_1602dat('T');//delay(5);write_1602dat('A');break;case 7:write_1602dat('S');//delay(5);write_1602dat('U');//delay(5);write_1602dat('N');break;}}void keyscan(){if(key1==0)//key1为功能键{delayus(5000);if(key1==0){while(!key1);key1n++;if(key1n==9)key1n=1;switch(key1n){case 1: TR0=0;//关闭定时器//TR1=0;write_1602com(er+0x06);//写入光标位置write_1602com(0x0f);//设置光标为闪烁break;case 2: write_1602com(er+3);//fen//write_1602com(0x0f);break;case 3: write_1602com(er+0);//shi//write_1602com(0x0f);break;case 4: write_1602com(yh+0x0d);//week//write_1602com(0x0f);break;case 5: write_1602com(yh+0x09);//ri//write_1602com(0x0f);break;case 6: write_1602com(yh+0x06);//yue//write_1602com(0x0f);break;case 7: write_1602com(yh+0x03);//nian//write_1602com(0x0f);break;case 8: write_1602com(0x0c);//设置光标不闪烁write_sfm(6,miao);//写入新的秒数temp=(miao)/10*16+(miao)%10;write_byte(DS3231_SECOND,temp); //退出时修改秒write_1602com(er+6);write_sfm(0x03,fen);temp=(fen)/10*16+(fen)%10;write_byte(DS3231_MINUTE,temp); //修改分write_1602com(er+3);TR0=1;//打开定时器break;}}}if(key1n!=0)//当key1按下以下。

  1. 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
  2. 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
  3. 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。

单片机与高精度时钟芯片DS3231的接口应用[1]. 前言在许多单片机的测控系统和家用电器中都含有时钟显示部分,最廉价的是直接使用单片机中的定时器,辅以一定的中断服务程序,构成时钟显示部分,这种方式是几乎不需要增加新的硬件即可实现,缺点是计时误差大,同时电源掉电不能保持时钟继续运行。

在相对要求较高的场合,则使用廉价的时钟芯片(如DS1302等等)辅以备用电池,计时精度略高,可满足一般的要求。

在这篇文章中,我们重点介绍高精度时钟电路DS3231的设计和应用。

在DS1302普及型时钟芯片,晶体均需外置,由于晶体的离散性,很难选择到精度很高的器件,同时也没有温度补偿电路,不同的温度环境下,晶体的特性也在变化,直接影响着时钟的振荡频率,较大的误差在所在所难免。

而DS3231高精度时钟芯片,将晶体和温度补偿均集成在芯片中,为提高计时精度提供了可能,实册证明,使用DS3231时钟芯片,误差可做到一年小于一分钟,甚至部分显示器误差可小于20秒/一年。

这对有相对精确时钟要求的应用场合是个理想的选择。

[2]. DS3231时钟芯片结构原理DS3231是一款高精度I2C实时时钟(RTC)器件,具有集成的温度补偿晶体振荡器(TCXO)。

该器件包含电池输入端,断开主电源时仍可保持精确计时。

集成的晶体振荡器可提高器件的长期精确度。

DS3231的寄存器能保存秒、分、时、星期、日期、月、年和闹钟设置等信息。

少于31天的月份,可自动调整月末日期,包括闰年补偿。

时钟的工作格式为24小时或带AM/PM指示的12小时格式。

DS3231提供两个可编程日历闹钟和一路可编程方波输出。

DS3231与单片机通过I2C双向串行总线传输地址与数据。

下图为DS3231典型应用电路,图中可看出,DS3231几乎不需要外部元件。

[3]. DS3231时钟芯片结构如图1所示,DS3231的主要组成部分有8个模块,划分为4个功能组:TCXO、电源控制、按钮复位和RTC。

1.32 kHz的TCXOTCXO包括温度传感器、振荡器和控制逻辑。

控制器读取片上温度传感器输出,使用查表法确定所需的电容,加上AGE寄存器的老化修正。

然后设置电容选择寄存器。

仅在温度变化或者用户启动的温度转换完成时,才加载包括AGE寄存器变化的新值。

VCC初次上电时就会读取温度值,然后每隔64 s读取一次。

2.DS3231的内部寄存器及功能DS3231寄存器地址为00h~12h,分别用于存放秒、分、时、星期、日期及闹钟设置信息。

在多字节访问期间,如果地址达到RAM空间的结尾12h处,将发生卷绕,此时定位到开始位置即00h单元。

DS3231的时间和日历信息通过读取相应的寄存器来设置和初始化。

用户辅助缓冲区用于防止内部寄存器更新时可能出现的错误。

读取时间和日历寄存器时,用户缓冲区在任何START条件下或者寄存器指针返回到零时与内部寄存器同步。

时间信息从这些辅助寄存器读取,此时时钟继续保持运行状态。

这样在读操作期间发生主寄存器更新时可以避免重新读取寄存器。

以控制寄存器(地址为0EH)为例,可以控制实时时钟、闹钟和方波输出。

其各bit定义如下表。

BIT7位:使能振荡器(EOEC)。

设定为逻辑0时,启动振荡器。

如果设定为逻辑1,在DS3231电源切换至VBAT时,振荡器停止。

初次上电时该位清零(逻辑0) 。

当DS3231由VCC供电时,振荡器与EOSC位的状态无关,始终保持工作状态。

BIT6位:电池备份的方波使能(BBSOW)。

当设定为逻辑1并且DS3231由VBAT引脚供电时,在没有加载VCC的情况下,该位使能方波输出。

当BB-SQW设定为逻辑0时,若VCC降至低于电源故障门限值,则INT/SQW引脚变为高阻抗。

初次上电时,该位清零(逻辑0)。

BIT5位:转换温度(CONV)。

该位置为1时,强制温度传感器将温度转换成数字,并执行TCXO算法更新振荡器的电容阵列。

只在空闲期间有效。

状态位BSY=1时,禁止设定转换温度位。

用户在强制控制器开始新的TCXO操作之前。

应检查状态位BSY。

用户启动的温度转换不影响内部64 s更新周期。

用户启动的温度转换在大约2 ms内不会影响BSY位。

CONV位从写入开始直到转换完成一直保持为1,转换完后,CONV和BSY均变为0。

在监视用户启动转换状态时,应使用CONV位。

BIT4和BIT3位:频率选择(RS2和RS1),初次上电时,BIT4和BIT3设置为逻辑1。

方波使能时用于控制方波输出的频率。

RS1、RS2的逻辑值与方波输出频率的关系如表2所列。

BIT2位:中断控制(INTCN)。

该位控制INT/SQW信号。

INTCN置为0时,INT/SQW引脚输出方波;INTCN置为1时,若计时寄存器与任一个闹钟寄存器相匹配,则会触发INT/SQW信号(如果也使能闹钟的话)。

匹配时相应的闹钟标志总是置位,而与INTCN位的状态无关。

初次上电时,INTCN 位置为逻辑1。

BIT1位:闹钟2中断使能(A2IE)。

该位置为逻辑1时,允许状态寄存器中的闹钟2标志位(A2F)触发INT/SQW信号(当INTCN=1时)。

当A2IE位置为0或者INTCN置为0时,A2F位不启动中断信号。

初次上电时,A2IE位清零(逻辑0)。

BIT0位:闹钟1中断使能(A1IE)。

该位置为逻辑1时,允许状态寄存器中的闹钟1标志位(A1F)触发INT/SQW信号(当INTCN=1时)。

当A1IE位置为0或者INTCN置为0时,A1F位不启动INT/SQW 信号。

初次上电时,A1IE位清零(逻辑0)。

3.DS3231的电源控制电源控制功能由温度补偿电压基准(VPF)和监视VCC电平的比较器电路提供。

当VCC高于VPF时,DS3231由VCC供电,当VCC低于VPF但高于VBAT时,DS3231由VCC供电;当VCC低于VPF并低于VBAT时,DS3231由VBAT供电。

为保护电池,VBAT首次加到器件时振荡器并不启动,除非加载VCC,或者向器件写入一个有效的I2C地址。

典型的振荡器启动时间在1 s以内。

在VCC加电后或者有效的I2C地址写入后大约2 s,器件会测量一次温度,并使用计算的修正值校准振荡器。

一旦振荡器运行,只要电源(VCC或者VBAT)有效就会一直保持工作状态。

器件每隔64 s进行一次温度测量并校准振荡器频率。

4.DS3231的时钟和日历RTC可以通过读取适当的寄存器字节获得时钟和日历信息。

通过写入适当的寄存器字节设定或者初始化时钟和日历数据。

时钟和日历寄存器的内容采用二-十进制编码(BCD)格式。

DS3231运行于12小时或者24小时模式。

小时寄存器的第6位定义为12或24小时模式选择位。

该位为高时,选择12小时模式。

在12小时模式下,第5位为AM/PM指示位,逻辑高时为PM。

5.DS3231的复位按钮DS3231具有连接至RST输出引脚的按钮开关功能。

若DS3231不在复位周期,会持续监视RST 信号的下降沿。

如果检测到一个边沿转换,DS3231通过拉低RST完成开关去抖。

内部定时器定时结束后,DS3231继续监视RST信号。

如果信号依旧保持低电平,DS3231持续监视信号线以检测上升沿。

一旦检测到按钮释放,DS3231强制RST为低电平并保持tRST。

RST还可用于指示电源故障报警情况。

当VCC低于VPF时,产生内部电源故障报警信号,并强制拉低RST引脚。

当VCC返回至超过VPF电平时。

RST保持低电平大约250 ms(tREC),使供电电源达到稳定。

如果在VCC加载时,振荡器不工作,将跳过tREC,RST立刻变为高电平。

6.DS3231的闹钟和报警功能DS3231包含2个定时/日期闹钟。

闹钟1可通过写入寄存器07h~0Ah设定。

闹钟2可通过写入寄存器0Bh~0Dh设定。

可对闹钟进行编程(通过控制寄存器的闹钟使能位和INTCN位),从而在闹钟匹配条件下触发INT/SQW输出。

每个定时/日期闹钟寄存器的第7位是屏蔽位。

当每个闹钟的屏蔽位均为逻辑0时,只有当计时寄存器中的值与存储于定时/日期闹钟寄存器中的对应值相匹配时才会告警。

闹钟也可以编程为每秒、分、时、星期或日期重复告警。

当RTC寄存器值与闹钟寄存器的设定值相匹配时,相应的闹钟标志位A1F或A2F置为逻辑1。

如果对应的闹钟中断使能位A1IE或A2IE也置为逻辑1,并且INTCN位置为逻辑1,闹钟条件将会触发INT/SQW信号。

RTC在时间和日期寄存器每秒更新时都会检测匹配情况。

7.DS3231的I2C 总线时序,数据交换及其格式及编程注意事项DS3231在I2C总线上作为从器件。

通过执行START命令并且在验证器件地址后才可以访问。

然后寄存器可以被访问直到执行一个STOP命令为止。

所有在I2C总线上传输的地址包长度均为9位,它包括7个地址位,1个R/W控制位和1个应答位ACK,如果R/W为1,则执行读操作;如果R/W为0,则执行写操作。

从机寻址后,必须在第9个SCL(ACK)周期通过拉低SDA做出应答,若从机忙或者无法响应主机,则应在ACK周期内保持SDA为高。

然后主机发出STOP状态或者REP START状态重新开始发送。

地址包包括从机地址和称为SLA+R 或者SLA+W的READ或者WRITE位。

地址字节的MSB首先被发送。

所有1111xxxx的地址均保留。

以便将来使用。

所有在I2C总线上传送的数据包长度均为9位,它包括8个数据位和1个应答位。

在数据传送中,主机产生时钟及START与STOP状态,而接收器响应接收。

应答是由ACK在第9个SCL周期拉低SDA 实现的。

如果接收器拉高SDA,则发送NACK信号。

如果接收器由于某种原因不能接收更多数据,应在最后一个数据字节后发出NACK信号告诉发送器停止发送,首先发送数据的MSB。

下图为DS3231与MCUI2C总线数据交换时序:DS3231通过双向数据线SDA和时钟线SCL与外界进行数据交换,从其时序关系可看出,DS3231有两种操作方式:写操作:把SDA数据线上的数据按RAM指定的首地址(Word Address)依次写入N个字节数据。

主器件首先传输从器件的地址字节,紧跟着是一系列数据字节。

从器件每收到一个字节后返回一个应答位ACK。

其格式下图所示。

读操作:按RAM指定的首地址依次读取N个字节数据,主器件首先传送从器件地址。

从器件返回一个应答位。

随后是从器件传输的一系列数据字节。

主器件收到除最后一个字节外的所有字节后返回一个应答位。

在收到最后一个字节后,返回一个“非应答位”NACK。

其格式下图所示。

上述读写操作信号中:S为起始信号(START),1101 000为DS3231的口地址,A为应答信号ACK,A为非应答信号NACK,P为停止信号(STOP)。

相关文档
最新文档