历史上的今天
返回首页

历史上的今天

今天是:2024年11月11日(星期一)

正在发生

2019年11月11日 | [嵌入式开发模块]DS3231时钟芯片 驱动程序

2019-11-11 来源:eefocus

刚刚写完DS3231时钟芯片的驱动程序。这里开源出来供大家使用。需要的自取。

先简单介绍下这个芯片,然后直接给驱动代码以及示例代码。


DS3231简介


简介


DS3231是一款低成本、高精度I2C实时时钟(RTC),具有集成的温补晶体振荡器(TCXO)和晶体。该器件包含电池输入端,断开主电源时认可保持精确的计时。其提供年、月、日、星期、时、分、秒信息,提供有效期到2100年的闰年补偿。


其带有两个提供不同精度的日历闹钟,可在指定时刻在引脚上产生中断信号。


支持快速(400kHz)I2C接口通讯。


时钟精度在0℃到+40℃为±2ppm,即一个月可能偏离5s多;在-40℃到+85℃为±3.5ppm。


除了时钟外,还提供精度为±3℃的数字温度传感器输出,内部会使用这个温度传感器自动进行补偿以保证时间精度。


典型工作电路

框图

寄存器


DS3231提供如下寄存器:


与DS3231的控制和交互就是通过存取这几个寄存器来实现的,驱动代码中提供了所有寄存器的结构体以及对寄存器的存取函数。


具体寄存器的意义请自己参照数据手册。


与芯片的I2C通讯


I2C通讯的基本原理可以见我的上一个文章https://blog.csdn.net/lin_strong/article/details/80259571,翻译的MC9S12XEP100的数据手册,里头有对I2C通讯的详细描述。



DS3231的主叫地址固定为0b1101000,其内部存在一个寄存器指针,指向下一次读/写的寄存器,每次读/写一次后指针都会自增1,到最后一个寄存器后再指向第一个寄存器。

进行写操作时第一个数据字节会对指针值进行修改。


驱动中提供的函数即封装了这个过程。


代码及测试


驱动代码


DS3231Driver.h


/*

*******************************************************************************************

*

*

*                                   DS3231 DRIVER MODULE

*                                  Freescale MC9S12XEP100

*                                      DS3231驱动模块

*

* File : DS3231Driver.h

* By   : Lin Shijun(http://blog.csdn.net/lin_strong)

* Date:  2018/05/14

* version: V1.0

* History: 2018/05/14  V1.0   the prototype

*********************************************************************************************

*/


#ifndef   DS3231_DRIVER_H

#define   DS3231_DRIVER_H


/*

********************************************************************************************

*                                   MISCELLANEOUS

********************************************************************************************

*/


#ifndef  FALSE

#define  FALSE    0

#endif


#ifndef  TRUE

#define  TRUE     1

#endif


/*

******************************************************************************************

*                                    CONSTANT

******************************************************************************************

*/

// address of register

typedef enum{

  RegAddr_Sec,    // Seconds              00-59

  RegAddr_Min,    // Minutes              00-59

  RegAddr_Hour,   // Hours                1–12 + AM/PM 00–23

  RegAddr_Day,    // Day                  1 - 7

  RegAddr_Date,   // Data                 01-31

  RegAddr_CMon,   // Century and month    Century + 01–12

  RegAddr_Year,   // Year                 00 - 99

  RegAddr_Sec_A1, // Alarm 1 Seconds      00-59

  RegAddr_Min_A1, // Alarm 1 Minutes      00-59

  RegAddr_Hour_A1,// Alarm 1 Hours        1–12 + AM/PM 00–23

  RegAddr_Da_A1,  // Alarm 1 Day/Date     1 - 7 / 1 – 31

  RegAddr_Min_A2, // Alarm 2 Minutes      00-59

  RegAddr_Hour_A2,// Alarm 2 Hours        1–12 + AM/PM 00–23

  RegAddr_Da_A2,  // Alarm 2 Day/Date     1 - 7 / 1 – 31

  RegAddr_Control,// Control

  RegAddr_CtlStat,// Control/Status

  RegAddr_AgOfset,// Aging offset

  RegAddr_TempMSB,// MSB of Temp

  RegAddr_TempLSB,// LSB of Temp

}DS3231REG_ADDR;

#define DS3231REG_ADDR_MAX  RegAddr_TempLSB

/*

*******************************************************************************************

*                               CONFIGURE 主配置

*******************************************************************************************

*/

#define DS3231_CALLADDR     0b1101000       // DS32331的主叫地址


/*

****************************************************************************************

*                                  ERROR CODES

****************************************************************************************

*/


#define DS3231_ERR_NULL   0      // if success

#define DS3231_ERR_COMM   1      // any error in communication

#define DS3231_ERR_REG    2      // wrong register 

#define DS3231_ERR_ARG    3      // if wrong argument



/*

******************************************************************************************

*                                  TYPE DEFINE

******************************************************************************************

*/


// struct of DS3231 register 

typedef struct {

  unsigned int sec_sd: 4; // ones digit of second  秒的个位

  unsigned int sec_td: 3; // tens digit of second  秒的十位

  unsigned int       : 1;

} REG_SEC;


typedef struct {

  unsigned int min_sd: 4; // ones digit of minute 分的个位

  unsigned int min_td: 3; // tens digit of minute   分的十位

  unsigned int       : 1;

} REG_MIN;


typedef union {

  struct{

    unsigned int hour_sd:4; // ones digit of hour 分的个位

    unsigned int hour_td:1; // tens digit of hour 分的个位

    unsigned int isPM   :1; // whether is pm

    unsigned int is12sys:1; // whether is 12 hours system. 

    unsigned int        :1;

  }SYS12;

  struct{

    unsigned int hour_sd:4; // ones digit of hour 分的个位

    unsigned int hour_td:2; // tens digit of hour   分的个位

    unsigned int is12sys:1; // whether is 12 hours system. 

    unsigned int        :1;

  }SYS24;

} REG_HOUR;


typedef struct {

  unsigned int day    : 3; // the day of the week 

  unsigned int        : 5;

} REG_DAY;


typedef struct {

  unsigned int date_sd: 4; // ones digit of second  秒的个位

  unsigned int date_td: 2; // tens digit of second  秒的十位

  unsigned int        : 2;

} REG_DATE;


typedef struct {

  unsigned int mon_sd: 4; // ones digit of month 月的个位

  unsigned int mon_td: 1; // tens digit of month 月的个位

  unsigned int       : 2; 

  unsigned int century:1; // hundreds digit of year

} REG_CMON;


typedef struct {

  unsigned int year_sd: 4; // ones digit of year 月的个位

  unsigned int year_td: 4; // tens digit of year 月的个位

} REG_YEAR;



typedef struct {

  unsigned int sec_sd: 4; // ones digit of second  秒的个位

  unsigned int sec_td: 3; // tens digit of second  秒的十位

  unsigned int A1M1  : 1;

} REG_SEC_A1;


typedef struct {

  unsigned int min_sd: 4; // ones digit of minute 分的个位

  unsigned int min_td: 3; // tens digit of minute   分的十位

  unsigned int A1M2  : 1;

} REG_MIN_A1;


typedef union {

  struct{

    unsigned int hour_sd:4; // ones digit of hour 分的个位

    unsigned int hour_td:1; // tens digit of hour 分的个位

    unsigned int isPM   :1; // whether is pm

    unsigned int is12sys:1; // whether is 12 hours system. 

    unsigned int A1M3   :1;

  }SYS12;

  struct{

    unsigned int hour_sd:4; // ones digit of hour 分的个位

    unsigned int hour_td:2; // tens digit of hour 分的个位

    unsigned int is12sys:1; // whether is 12 hours system. 

    unsigned int A1M3   :1;

  }SYS24;

} REG_HOUR_A1;


typedef union {

  struct{

    unsigned int day    : 4; // the day of the week 

    unsigned int        : 2;

unsigned int isDY   : 1; // day selected

unsigned int A1M4   : 1;

  }DAY;

  struct{

    unsigned int date_sd: 4; // ones digit of date

    unsigned int date_td: 2; // tens digit of date

unsigned int isDY   : 1; // day selected

unsigned int A1M4   : 1;

  }DATE;

} REG_DA_A1;


typedef struct {

  unsigned int min_sd: 4; // ones digit of minute 分的个位

  unsigned int min_td: 3; // tens digit of minute   分的十位

  unsigned int A2M2  : 1;

} REG_MIN_A2;


typedef union {

  struct{

    unsigned int hour_sd:4; // ones digit of hour 分的个位

    unsigned int hour_td:1; // tens digit of hour 分的个位

    unsigned int isPM   :1; // whether is pm

    unsigned int is12sys:1; // whether is 12 hours system. 

    unsigned int A2M3   :1;

  }SYS12;

  struct{

    unsigned int hour_sd:4; // ones digit of hour 分的个位

    unsigned int hour_td:2; // tens digit of hour 分的个位

    unsigned int is12sys:1; // whether is 12 hours system. 

    unsigned int A2M3   :1;

  }SYS24;

} REG_HOUR_A2;


typedef union {

  struct{

    unsigned int day    : 4; // the day of the week 

    unsigned int        : 2;

unsigned int isDY   : 1; // day selected

unsigned int A2M4   : 1;

  }DAY;

  struct{

    unsigned int date_sd: 4; // ones digit of date

    unsigned int date_td: 2; // tens digit of date

unsigned int isDY   : 1; // day selected

unsigned int A2M4   : 1;

  }DATE;

} REG_DA_A2;


typedef struct{

  unsigned int A1IE  : 1;

  unsigned int A2IE  : 1;

  unsigned int INTCN : 1;

  unsigned int RS1   : 1;

  unsigned int RS2   : 1;

  unsigned int CONV  : 1;

推荐阅读

史海拾趣

Concurrent Logic公司的发展小趣事

在取得初步成功后,Concurrent Logic开始扩展其产品线。他们不仅开发了多款针对不同应用场景的并行处理芯片,还进军了与并行计算紧密相关的其他硬件领域,如高性能的服务器和存储设备。这些新产品的研发和上市,进一步增强了公司在市场上的竞争力。

BSI公司的发展小趣事

随着电子产品的普及和消费者对产品质量的关注,电子产品测试和认证成为了一个必不可少的环节。BSI作为全球知名的认证机构,为电子产品提供了专业的测试和认证服务。通过严格的测试和认证流程,BSI确保了电子产品符合国际标准和客户需求,提高了产品的市场竞争力和信誉度。同时,BSI还为企业提供了定制化的商检解决方案,帮助企业在国际贸易中解决技术和法规问题,降低了贸易风险。

AverLogic公司的发展小趣事

除了关注业务发展外,AverLogic公司还积极履行企业社会责任,推动可持续发展。公司注重环保和节能,采用环保材料和生产工艺,减少对环境的影响。同时,公司还积极参与公益事业,为社会做出贡献。这些举措不仅提升了公司的社会形象,也为其在电子行业中树立了良好的口碑。

需要注意的是,这些故事是基于一般性的电子行业趋势和公司可能的发展路径构建的,并不代表AverLogic公司的实际发展历程。如需了解AverLogic公司的具体发展故事,建议查阅相关的行业报告、公司年报或新闻报道。

EIC [EIC discrete Semiconductors]公司的发展小趣事

EIC公司自创立之初,就致力于离散半导体技术的研发与创新。在成立初期,公司面临了技术瓶颈和市场接受度的双重挑战。然而,EIC的研发团队通过不懈努力,成功研发出了一款高性能、低功耗的离散半导体产品,这一技术突破不仅为公司赢得了市场认可,也为后续的产品线扩展奠定了坚实的基础。随着技术的不断进步和产品线的不断丰富,EIC逐渐在电子行业中树立起了自己的品牌形象。

General Instrument Corp公司的发展小趣事
通过对比实际转换结果与预期值,检查变换器的性能是否符合要求。
Holy Stone公司的发展小趣事

近年来,Holy Stone不断加大在技术研发和产品创新方面的投入。公司致力于研发适用于节能产品应用所需的被动元件,帮助客户提升产品能源转换效率。在全球汽车电子化发展的背景下,Holy Stone正式跨入车用电子供应链,以提供优质元件的能力协助汽车电子达到最佳数位化。这些技术创新不仅推动了公司产品的升级换代,还为公司开拓了新的市场领域和增长点。

以上五个故事展示了Holy Stone公司在电子行业中的发展历程和成就,每个故事都体现了公司在不同方面的努力和成果。

问答坊 | AI 解惑

山寨机,你买了么?

昨天加到一姑娘,特猛,用两个手机,iphone 和nokia,正当大家唏嘘感慨时,她说其中一个是山寨,让我们猜。 iphone的外壳磨损比较厉害,去除掉其略显华丽的外衣,也许iphone山寨得多的缘故吧,我们一直认定iphone是假的。 但结果却大大出乎我们的 ...…

查看全部问答>

标志三轮电动跑车

这辆未来概念车吸取了四轮跑车的外形特点,但却另辟蹊径采用了三轮设计,看上去很是特别。它宽大的后轮中装有电动机,并采用类似摩托车上使用的单摇臂悬挂系统。此外,当这款车行驶在下坡路时,电机会还会自动充电,充分利用每一分资源。…

查看全部问答>

用tcpDebugShow()查看的结果中第一列的数字是什么含义?

如下,第一列的数字表示什么? -> tcpDebugShow 1665138688  user  CLOSED 1665138688  user  CLOSED 643760896  user  CLOSED 643760896  input  LISTEN ...…

查看全部问答>

使用GetAdaptersAddresses获取DNS遇到的问题

在文件中使用了GetAdaptersAddresses函数,遇到了以下问题: BUILD: [01:0000000089:ERRORE] error C2065: \'PIP_ADAPTER_ADDRESSES\' : undeclared identifier 其中我已经添加了该函数需要的头文件Iptypes.h,其路径在resouces中是正确的. 但是我 ...…

查看全部问答>

plc控制变频器

请教PLC控制变频器,不是太复杂的控制。只需起动与速度设定功能。有一点就是要随时能对变频器进速度变更,无极的。要怎样做?本人看过台达的PLC与变频器,觉得用RS485通讯,可以实现,但是实际动手又觉得不上手,想请高手指点,有例子最好。设定速 ...…

查看全部问答>

STM8单片机外部中断

STM8单片机,PD0口产生中断与PD2口产生中断都转向同一个中断服务函数吗?   若PD0口产生中断与PD2口产生中断都转向同一个中断服务函数,那么如何让单片机区别该中断是PD0口还是PD2口产生的?…

查看全部问答>

【设计工具】《算术逻辑部件设计》(中文)

这篇文章主要介绍寄存器级的算术逻辑部件设计,适合集成电路设计人员参考。大家可以先看看这篇文章的后记,以便对这篇文章的主题有所了解。   …

查看全部问答>

"C2000系列concerto讲座(二)"上线啦!加入学习吧!

\"[url=]C2000系列concerto讲座(二)[/url]\"上线啦!加入学习吧!…

查看全部问答>

FRAM系列添新丁,24WCSP 封装

wolverine大家已经很熟悉了,今天看到这个是MSP430FR5738.它到底有什么特别之处呢?先看看指标,基本是430的标准配置。 重点就在封装上:有一个24WCSP的封装,简单的讲就是一个BGA的封装。ball的间距是0.4m.翻看了手册,这个芯片面积是2mmx2.2mm ...…

查看全部问答>

关于“压采”,能做的项目征集

关于“压采”,能做的项目征集,大家帮忙想想,都能做点儿啥啊,服务三农,造福后代,吼吼,说的有点空了。 。。 最近冀州政府大力支持此类项目,也想搞搞什么滴,大家帮帮忙哇…

查看全部问答>