精华内容
下载资源
问答
  • 使用stm32 i2c读取ds3231例程
  • DS3231时钟芯片全功能测试代码,测试DS3231功能是否正常。
  • DS3231M_cn_DS3231M_源码

    2021-10-01 12:01:11
    DS3231MPMB1外设模块提供了连接DS3231M实时时钟(RTC)所需的硬件电路,适用于采用可配置成I2C通信Pmod?扩展端口的系统。IC为低成本和高精度I2C RTC。该器件包含电池输入端,断开主电源时仍可保持精确计时。集成微机电...
  • 使用arduino 控制DS3231时钟模块获取实时时间
  • OLED+DS3231时钟显示,实现显示时钟,万年历功能,自动亮度,温度湿度显示
  • ds3231

    千次阅读 2018-07-16 21:12:51
    I2C_BOARD_INFO("ds3231rtc", (I2C_ADDR_DS3231>>1)), }; static int i2cdev_read(char *buf, unsigned int count,  unsigned int reg_addr_num, unsigned int data_byte_num) {  int ret;  unsigned char ...

    #include <linux/kernel.h>
    #include <linux/module.h>
    #include <linux/interrupt.h>
    #include <linux/i2c.h>
    #include <linux/rtc.h>
    #include <linux/bcd.h>
    #include <linux/workqueue.h>
    #include <linux/slab.h>
    #include <linux/dma-mapping.h>
    #include <asm/delay.h>
    #include <linux/delay.h>


    #define MODULE_VERSION_STRING    "RTC-DS3231"
    #define DS3232_DRIVER_VERSION    "v1.0.0"

    #define DS3231_REG_SECONDS    0x00
    #define DS3231_REG_MINUTES    0x01
    #define DS3231_REG_HOURS    0x02
    #define DS3231_REG_AMPM        0x02
    #define DS3231_REG_DAY        0x03
    #define DS3231_REG_DATE        0x04
    #define DS3231_REG_MONTH    0x05
    #define DS3231_REG_CENTURY    0x05
    #define DS3231_REG_YEAR        0x06
    #define DS3231_REG_ALARM1         0x07    /* Alarm 1 BASE */
    #define DS3231_REG_ALARM2         0x0B    /* Alarm 2 BASE */
    #define DS3231_REG_CR        0x0E    /* Control register */
    #define DS3231_REG_CR_nEOSC        0x80
    #define DS3231_REG_CR_INTCN        0x04
    #define DS3231_REG_CR_A2IE        0x02
    #define DS3231_REG_CR_A1IE        0x01

    #define DS3231_REG_SR    0x0F    /* control/status register */
    #define DS3231_REG_SR_OSF   0x80
    #define DS3231_REG_SR_BSY   0x04
    #define DS3231_REG_SR_A2F   0x02
    #define DS3231_REG_SR_A1F   0x01

    #define DEVICE_NAME            "ds3231rtc"
    #define I2C_ADDR_DS3231        0xD0
    #ifdef DS3231_DEBUG
    #define HI_MSG(x...) \
    do { \
        printk("%s->%d: ", __FUNCTION__, __LINE__); \
        printk(x); \
        printk("\n"); \
    } while (0)    
    #else
    #define HI_MSG(args...) do { } while (0)
    #endif

    #define HI_ERR(x...) \
    do { \
        printk(KERN_ALERT "%s->%d: ", __FUNCTION__, __LINE__); \
        printk(KERN_ALERT x); \
        printk(KERN_ALERT "\n"); \
    } while (0)

    #ifdef DS3231_DEBUG
    static void display_rtc_time_in_bcd(struct rtc_time *rtime)
    {
        printk("tm_sec: %u\n", rtime->tm_sec);
        printk("tm_min: %u\n", rtime->tm_min);
        printk("tm_hour: %u\n", rtime->tm_hour);
        printk("tm_mday: %u\n", rtime->tm_mday);
        printk("tm_mon: %u\n", rtime->tm_mon);
        printk("tm_year: %u\n", rtime->tm_year);
        printk("tm_wday: %u\n", rtime->tm_wday);
        printk("tm_yday: %u\n", rtime->tm_yday);
        printk("tm_isdst: %u\n", rtime->tm_isdst);
    }
    #endif

    struct i2c_client *rtc_client;
    struct rtc_time *time;
    struct rtc_device *rtc;
    struct ds3231rtc {
        struct i2c_client *client;
        struct rtc_device *rtc;
        struct work_struct work;

        /* The mutex protects alarm operations, and prevents a race
         * between the enable_irq() in the workqueue and the free_irq()
         * in the remove function.
         */
        struct mutex mutex;
        bool suspended;
        int exiting;
    };

    extern int hi_i2c_dma_read(const struct i2c_client *client, unsigned int data_addr,
            unsigned int reg_addr, unsigned int reg_addr_num,
            unsigned int length);
    extern int hi_i2c_dma_write(const struct i2c_client *client, unsigned int data_addr,
            unsigned int reg_addr, unsigned int reg_addr_num,
            unsigned int length);
    const struct i2c_device_id ds3231_id[]=
    {

    {"ds3231rtc",2},
    {}
    };

    static struct i2c_board_info i2c_ds3231rtc=
    {
    //参数一 名称
    //参数二 从设备地址
    I2C_BOARD_INFO("ds3231rtc", (I2C_ADDR_DS3231>>1)),
    };
    static int i2cdev_read(char *buf, unsigned int count,
            unsigned int reg_addr_num, unsigned int data_byte_num)
    {
        int ret;
        unsigned char tmp_buf0[4];
        unsigned char tmp_buf1[4];
        struct i2c_msg msg[2];
        int idx = 0;
        struct i2c_client * client;
        client=rtc_client;
        msg[0].addr = (I2C_ADDR_DS3231>>1);
        msg[0].flags = client->flags & I2C_M_TEN;
        msg[0].len = reg_addr_num;
        msg[0].buf = tmp_buf0;
        if(reg_addr_num == 1)
        {
            tmp_buf0[idx++] = buf[0]&0xff;
        }
        else
        {
            tmp_buf0[idx++] = (buf[0] >> 8)&0xff;
            tmp_buf0[idx++] = buf[0]&0xff;
        }
        msg[1].addr = (I2C_ADDR_DS3231>>1);
        msg[1].flags = client->flags & I2C_M_TEN;
        msg[1].flags |= I2C_M_RD;
        msg[1].len = data_byte_num;
        msg[1].buf = tmp_buf1;
        ret = i2c_transfer(client->adapter, msg, 2);
        if (ret == 2)
        {
            if (data_byte_num == 2)
            {
                buf[1] = tmp_buf1[1];
                buf[0] = tmp_buf1[0];
            }
            else
            {
                buf[0] = tmp_buf1[0];
            }
        }
        else
        {
            return 0;
        }
        return 1;
    }
    static int ds3231_i2c_readbyte(struct i2c_client *client, unsigned char reg_addr)
    {
        int ret = 0;
        unsigned char buf[2];

        buf[0] = reg_addr;
        ret = i2cdev_read(buf, 1, 1, 1);
        if (ret < 0)
        {
            dev_err(&client->dev, "ds3231_i2c_readbyte fail...\n");
            return ret;
        }
        
        return buf[0];
    }
    static int ds3231_i2c_writebyte(struct i2c_client *client,unsigned char reg_addr,
        unsigned char value)
    {
        int ret = 0;
        unsigned char buf[2];

        buf[0] = reg_addr;
        buf[1] = value;

        ret = i2c_master_send(client, buf, 2);
        return ret;
    }

    static int ds3231_i2c_dma_read(struct i2c_client *client, unsigned char reg_addr, 
            unsigned char len, unsigned char *buffer)
        {
            int ret;
            dma_addr_t dma_handle;
            unsigned char *p;
        
            p = dma_alloc_coherent(NULL, len, &dma_handle, GFP_KERNEL);
            if(p == NULL)
            {
                printk("dma_alloc_coherent fail\n");
                return -1;
            }
            
            ret = hi_i2c_dma_read(client, dma_handle, reg_addr, 1, len);
            if(ret)
                printk("dma_write fail:%d.\n", ret);
        
            memcpy(buffer, p, len);
            dma_free_coherent(NULL, len, p, dma_handle);
            return 0;
        }
    static int ds3231_i2c_dma_write(struct i2c_client *client,unsigned char reg_addr,
                unsigned char len,unsigned char *buffer)
        {
                int ret;
                dma_addr_t dma_handle;
                unsigned char *p;
            
                p = dma_alloc_coherent(NULL, len, &dma_handle, GFP_KERNEL);
                if(p == NULL)
                {
                    printk("dma_alloc_coherent fail\n");
                    return -1;
                }
                memcpy(p, buffer, len);
                
                ret = hi_i2c_dma_write(client, dma_handle, reg_addr, 1, len);
                if(ret)
                    printk("dma_write fail:%d.\n", ret);
            
                dma_free_coherent(NULL, len, p, dma_handle);
                return 0;
        }
    static int ds3231_read_time(struct device *dev,struct rtc_time *time)
        {
            struct i2c_client *client = rtc_client;
            int ret;
            u8 buf[7];
            unsigned int year, month, day, hour, minute, second;
            unsigned int week, twelve_hr, am_pm;
            unsigned int century, add_century = 0;
        
            ret = ds3231_i2c_dma_read(client, DS3231_REG_SECONDS, 7, buf);
        
            if (ret < 0) {
                dev_warn(&client->dev, "ds3231_i2c_dma_read read time error!ret = %d\n", ret);
                return ret;
            }
        
            second = buf[0];
            minute = buf[1];
            hour = buf[2];
            week = buf[3];
            day = buf[4];
            month = buf[5];
            year = buf[6];
                                    
            /* Extract additional information for AM/PM and century */
            twelve_hr = hour & 0x40;
            am_pm = hour & 0x20;
            century = month & 0x80;
    #ifdef DS3231_DEBUG
        {
        int i;
        printk("read from rtc-ds3231m: ");
        for (i = 0; i < 7; i++) {
            printk("0x%02x ", buf[i]);
        }
        printk("\n");
                                            
        }
    #endif
        /* Write to rtc_time structure */
                                    
        time->tm_sec = bcd2bin(second);
        time->tm_min = bcd2bin(minute);
        if (twelve_hr) {
        /* Convert to 24 hr */
        if (am_pm)
        time->tm_hour = bcd2bin(hour & 0x1F) + 12;
        else
        time->tm_hour = bcd2bin(hour & 0x1F);
        } else {
        time->tm_hour = bcd2bin(hour);
        }
                                    
        /* Day of the week in linux range is 0~6 while 1~7 in RTC chip */
        time->tm_wday = bcd2bin(week) - 1;
        time->tm_mday = bcd2bin(day);
        /* linux tm_mon range:0~11, while month range is 1~12 in RTC chip */
        time->tm_mon = bcd2bin(month & 0x7F) - 1;
        if (century)
        add_century = 100;
                                    
        time->tm_year = bcd2bin(year) + add_century;
                                    
        ret = rtc_valid_tm(time); 
        if (ret < 0) {
        dev_err(&client->dev, "rtc_valid_tm return ret: %d\n", ret);
        }
        return ret;
    }
    static int ds3231_set_time(struct device *dev, struct rtc_time *time)
    {
        struct i2c_client *client = to_i2c_client(dev);
        u8 buf[7];
        int ret;
        /* Extract time from rtc_time and load into ds3231*/

        buf[0] = bin2bcd(time->tm_sec);
        buf[1] = bin2bcd(time->tm_min);
        buf[2] = bin2bcd(time->tm_hour);
        /* Day of the week in linux range is 0~6 while 1~7 in RTC chip */
        buf[3] = bin2bcd(time->tm_wday + 1);
        buf[4] = bin2bcd(time->tm_mday); /* Date */
        /* linux tm_mon range:0~11, while month range is 1~12 in RTC chip */
        buf[5] = bin2bcd(time->tm_mon + 1);
        if (time->tm_year >= 100) {
            buf[5] |= 0x80;
            buf[6] = bin2bcd(time->tm_year - 100);
        }
        else 
        {
            buf[6] = bin2bcd(time->tm_year);
        }

    #ifdef DS3231_DEBUG
        {
            int i = 0;
            display_rtc_time_in_bcd(time);
            printk("write buffer: ");
            for (i = 0; i < 7; i++) {
                printk("0x%02x ", buf[i]);
            }
            printk("\n");
        }
    #endif
        ret = ds3231_i2c_dma_write(client,
                              DS3231_REG_SECONDS, 7, buf);
        
        if (ret < 0) {
            dev_err(&client->dev, "ds3231_i2c_dma_write set time failed, ret: %d\n", ret);
        } else {
            /* take some sleep to fix bug read immendiately after set */
            udelay(500);
        }
        return ret;
    }
    static int ds3231_check_rtc_status(struct i2c_client *client)
    {
        int ret = 0;
        int control, stat;

        stat = ds3231_i2c_readbyte(client, DS3231_REG_SR);
        if (stat < 0) {
            dev_err(&client->dev, "ds3231_i2c_readbyte failed!stat = 0x%08x\n", stat);
            return stat;
        }

        if (stat & DS3231_REG_SR_OSF)
            dev_warn(&client->dev,
                    "oscillator discontinuity flagged, "
                    "time unreliable\n");

        stat &= ~(DS3231_REG_SR_OSF | DS3231_REG_SR_A1F | DS3231_REG_SR_A2F);

        ret = ds3231_i2c_writebyte(client, DS3231_REG_SR, stat);
        if (ret < 0) {
            dev_warn(&client->dev, "ds3231_i2c_writebyte error!\n");
            return ret;
        }

        /* If the alarm is pending, clear it before requesting
         * the interrupt, so an interrupt event isn't reported
         * before everything is initialized.
         */

        control = ds3231_i2c_readbyte(client, DS3231_REG_CR);
        if (control < 0) {
            dev_warn(&client->dev, "ds3231_i2c_readbyte read control error!control = 0x%08x\n", control);
            return control;
        }

        control &= ~(DS3231_REG_CR_A1IE | DS3231_REG_CR_A2IE);
        control |= DS3231_REG_CR_INTCN;

        ret = ds3231_i2c_writebyte(client, DS3231_REG_CR, control);
        if (ret < 0) {
            dev_warn(&client->dev, "ds3231_i2c_writebyte write control error!ret = 0x%08x\n", ret);
            return control;
        }
        return ret;
    }

    static const struct rtc_class_ops ds3231_rtc_ops = {
        .read_time = ds3231_read_time,
        .set_time = ds3231_set_time,
    //    .read_alarm = ds3231_read_alarm,
    //    .set_alarm = ds3231_set_alarm,
    //    .alarm_irq_enable = ds3231_alarm_irq_enable,
    };
    int ds3231rtc_probe(struct i2c_client *client,const struct i2c_device_id *id)
    {        
            int ret;
            printk("enter ds3231_probe\n");
            ret = ds3231_check_rtc_status(client);
            if (ret < 0) {
            dev_err(&client->dev, "ds3231_check_rtc_status failed! ret = %d\n", ret);
            return ret;
            }
            rtc = devm_rtc_device_register(&client->dev, client->name,
                                      &ds3231_rtc_ops, THIS_MODULE);
            return 0;
    }
    int ds3231rtc_remove(struct i2c_client *client)
    {


            return 0; 
    }


    struct i2c_driver  ds3231_driver=
    {
            .driver =
            {
            .name="ds3231rtc",
            .owner=THIS_MODULE,
                    
            },
            .probe =ds3231rtc_probe,
            .remove=ds3231rtc_remove,
            /*i2c match 会使用到*/
            .id_table=ds3231_id,
    };
            


    int __init ds3231rtc_init(void)
    {        
            int ret;
            struct i2c_adapter* i2c_adap;
    #if 0
            reg_gpio_base_va = ioremap(GPIO_ADRESS_BASE,0x10000);
            GPIO_WRITE_REG(I2C1_CTRL_REG6, 1);//设置GPIO1_6复用
            GPIO_WRITE_REG(I2C1_CTRL_REG7, 1);//设置GPIO1_7复用
            GPIO_WRITE_REG(GPIO9_CTRL_REG6, 0);//设置GPIO1_7复用
            GPIO_RST(GPIO9_DIR6, 6);//按键为输出
            /*配置中断*/
            GPIO_RST(GPIO9_IS6, 6);
            GPIO_RST(GPIO9_IEV6,6);
            GPIO_RST(GPIO9_IBE6,6);
            GPIO_SET(GPIO9_IC6, 6);
            GPIO_SET(GPIO9_IE6, 6);


            /*注册中断*/
            ret=request_irq(76,ds3231_isr,IRQF_SHARED,"interrupt_demo",(void*)0x01);
            if(ret==0)
            {
            printk("success\n");
            }
            else
            {    
            printk("%d",ret);
            }
    #endif    
            i2c_adap   = i2c_get_adapter(2);//I2C2
            rtc_client = i2c_new_device(i2c_adap, &i2c_ds3231rtc);
            i2c_put_adapter(i2c_adap);
            i2c_add_driver(&ds3231_driver);

            return 0;
    }

    void __exit ds3231rtc_exit(void)
    {
        //    iounmap(GPIO_ADRESS_BASE);
        //    free_irq(76,(void *)0x01);
            i2c_unregister_device(rtc_client);
            i2c_del_driver(&ds3231_driver);
            printk("ds3231 driver unregistered\n");
    }
    module_init(ds3231rtc_init);
    module_exit(ds3231rtc_exit);
    MODULE_LICENSE("GPL");


     

    展开全文
  • DS3231.rar

    2019-12-17 10:24:11
    DS3231时钟模块的库文件,网上常见的有两种库,一种是Eric Ayars的,下载后的库文件夹是:DS3231_TEST一种是Henning Karlsen的,下载后的库文件夹是DS3231.这个库是第二种
  • DS3231.txt

    2019-08-14 10:06:33
    STM32 模拟IIC 驱动DS3231程序,直接移植ds3231文件,里面都有封装好的函数库,到时候直接用就可以了
  • DS1302_DS3231_DS1307实时时钟模块.rar
  • DS3231.zip

    2019-08-19 19:13:44
    除去含DS3231的库(DS3231.h和DS3231.cpp)外还有四个现成代码,代码例子适用于Arduino和chipkit
  • 前一段在做时钟的过程中写了两篇关于DS3231的文章,具体见链接 《8266+DS3231开发个时钟遇到的N个坑》 《arduino官网发布的DS3231库的分析》 今天有点时间,具体在DS3231库的基础上,把实现过程代码呈现出来。我会把...

    这个时钟系列目前五篇分别是:

    《8266+DS3231时钟之开发个时钟遇到的N个坑【一】》
    《8266+ds3231时钟之arduino官网发布的DS3231库的分析【二】》
    《8266+DS3231时钟之DS3231具体实现及代码【三】》
    《8266+DS3231时钟之显示TM1638的使用【四】上》
    《8266+DS3231时钟之显示TM1638的使用【四】下》
    《8266+DS3231时钟之语音MP3-TF-16P模块使用【五】》
    有兴趣的可以去看看,如果觉得对你有帮助,请点个赞。

    前一段在做时钟的过程中写了两篇关于DS3231的文章,具体见链接
    《8266+DS3231时钟之开发个时钟遇到的N个坑【一】》
    《8266+ds3231时钟之arduino官网发布的DS3231库的分析【二】》

    有兴趣的可以去看看,如果觉得对你有帮助,请点个赞。
    今天有点时间,具体在DS3231库的基础上,把实现过程代码呈现出来。我会把整个钟的制作过程,分析及代码几往篇写出来,是对自已制作的一个总结,也希望能帮助到和我一样对嵌入式系统有兴趣的人。
    上一篇对DS3231库的分析里,对每一个函数及作用进行了分析。但在实际写代码的过程中,其实还是有不少地方需要注意的,因此这里根据时钟的使用过程顺序,分析一下具体的实现。

    概述

    我的时钟的主要功能:
    1、时钟的显示(主要显示日期和时分)
    2、时钟的自动对时
    3、闹钟一的设置与取消
    4、闹钟二的设置与取消

    1、首先当然是硬件连接

    在这里插入图片描述

    2、其次当然是软件环境配置

    要用DS3231,配置DS3231的相应使用环境 ,首先当然是需要引入相关的头文件,生成对象。具体代码如下:

    #include <Wire.h>
    #include <DS3231.h>
    //时钟管脚定义
    #define SCL 5    //GPIO5 对应NODEMCU的d1      I2C-SCL
    #define SDA 4    //GPIO4 对应NODEMCU的d2       I2C-SDA   
    #define INT_SQW 14   //GPIO14 对应NODEMCU的 D5     中断及方波1HZ
    //.......
    
    DS3231 RTC;      //创建DT3231时钟对象
    
    

    3、闹钟数据结构的设置

    /对应APP状态的各类数据结构///
    struct AlarmSet_type{    //闹钟设置数据结构
        byte flag=0;
        byte ADay=0;
        byte AHour=0;
        byte AMinute=0;
        byte ASecond=1;//怀疑没有0秒,所以设一个1秒
        byte AlarmBits1=0x08;   //闹钟一控制字的设置,详见我上一篇《arduino官网发布的DS3231库的分析》
        byte AlarmBits2=0x40;  //闹钟二控制字的设置,详见我上一篇《arduino官网发布的DS3231库的分析》
        
        bool ADy=false;//日期以月日格式。
        bool AH12=false; //24小时制
        bool APM=false; //
        
    };
    AlarmSet_type Alarm1;   //建立闹钟一 
    AlarmSet_type Alarm2;  //建立闹钟二  
    AlarmSet_type NowAlarm;//暂存现在的闹钟设置
    

    Alarm1 、Alarm2 、NowAlarm 用于接下来设置闹钟或同步APP与闹钟的数据时用。这里需要先定义一下。

    4、初始化

    void setup(){
    //....................
        Wire.begin();  //启动I2c总线
     时钟初始化   同步闹钟///
       
       //enableOscillator(bool TF, bool battery, byte frequency)
       //当第一位TF为true 控制寄存器的 ~EOSC to 0  and INTCN to 0.,
       //注意该函数把EOSC置0则启动振荡器,同时把把INTCN置0(第二位battery为true VCC<VPF时会输出1HZ方波)
       //使用时要用turnOnAlarm()把INTCN打开,否则会一直输出方波中断
       RTC.enableOscillator(true,false,0);
       RTC.checkIfAlarm(1);  //该函数检测完后状态寄存器A1F或A2F就把标志位清0
       RTC.checkIfAlarm(2);
       RTC.turnOnAlarm(1); //置INTCN为1,否则在INT/SQW会一直输出1HZ方波
       RTC.turnOnAlarm(2); 
    
     /设置闹钟中断输出设置秒闪功能///
       pinMode(INT_SQW,INPUT_PULLUP); 
       interrupts();
       attachInterrupt(digitalPinToInterrupt(INT_SQW),alarm_interrupt,FALLING);  
       
        //8266经过实践发现,只支持CHANGE RISING FALLING 。DS3231在闹钟启动时,会在int/sqw接口处输出一个低电平做为中断信号。
         secondTicker.attach(1,second_interrupt,SecondInterruptMode);//每秒触发一次带参数的中断程序
        //...................
    }
    

    经过以上几个步骤,DS3231就可以正常我们的要求开始工作了。接下来的大量工作就是和具体的显示,设置,以及其它辅助功能相关了。

    5、显示

    由于我搭的实验环境用的是某宝上买的基于TM1638显示驱动的一个现成模块。下一篇文章我会具体介绍这个模块的使用,这里只需要知道这部分是针对DS3231的具体显示功能就行了。下面先上一张该 模块的图,有个直观的认识:
    在这里插入图片描述
    由于是实验环境,为了省事,我用的这个8数码管的显示模块,把前四个数码管定义成月日的显示。后四个数码管定义为时分的显示。
    因此对应的显示函数如下:

    void GetTime(){    //给显示变量赋值
          showtime[0]=RTClib::now().month()/10;     //月 
          showtime[1]=RTClib::now().month()%10;     
          showtime[2]=RTClib::now().day()/10;      //日
          showtime[3]=RTClib::now().day()%10;
          showtime[4]=RTClib::now().hour()/10;      //时
          showtime[5]=RTClib::now().hour()%10;
          showtime[6]=RTClib::now().minute()/10;    //分
          showtime[7]=RTClib::now().minute()%10; 
    }
    

    上面这段代码只是把对应的DS3231赋值给showtime[]数组,该 数组用于对应TM1638的显示,由于要显示秒的功能,因此在设计时有一个秒中断函数负责具体的时间显示:

    
    ICACHE_RAM_ATTR void second_interrupt(int mode){ //时钟每秒中断
      if (mode==0){        //模式0 用于秒闪灯工作以及显示时间。模式1可能是显示提示正在配网等
    
       //显示时间
        if ( showtime[7]!=RTClib::now().minute()%10 ) {   //只要比较,分不同就重新显示
    
          GetTime();                   //获取DS3231的时间
          TM1638.Disp8(showtime);     //显示
        }  
      }
    
    }
    

    6、对时函数

     void autoAdjust(){    //自动对时
      
         Serial.println("<<<<<<<如果联网了,才执行自动对时功能>>>>>>>>>>");
         if (WiFi.status() == WL_CONNECTED){
            RTC.setClockMode(false);  // set to 24h
            RTC.setYear((Blinker.year()%100));  //取年的最后两位
            RTC.setMonth(Blinker.month());
            RTC.setDate(Blinker.mday());
            RTC.setDoW(Blinker.wday());
            RTC.setHour(Blinker.hour());
            RTC.setMinute(Blinker.minute());
            RTC.setSecond(Blinker.second());
         }
     
     }
    

    由于我用的是blinker点灯科技的APP,所以自动对时我就不需要去写复杂的NTP授时程序 了,直接从Blinker的对应时间函数里读需出来就行了。因为BLINKER的时间函数了是从NTP相关函数封装来的,所有也是用的互联网授时网站的标准时间。

    7、闹钟设置

    功能上,我取消了复杂又难以理解的按键设置功能,取而代之的是用APP上的操作来设置闹钟。这些具体实现在以后介绍,这里只需要知道 一下在APP上设置好时分后,把设置下载到DC3231。这此代码是放在对应的BLINKER的回设函数上

    void btnOne_callback(const String & state){
     RTC.setA1Time(Alarm1.ADay,Alarm1.AHour,Alarm1.AMinute,Alarm1.ASecond,Alarm1.AlarmBits1,Alarm1.ADy,Alarm1.AH12,Alarm1.APM);
      RTC.turnOnAlarm(1);
      if (RTC.checkAlarmEnabled(1)){ //检测控制寄存器中的A1IE位置1否
        texOne.print("每天响铃"+String(Alarm1.AHour)+"时"+String(Alarm1.AMinute)+"分");
       
      };    
    }
    

    8、闹钟取消

    void btnCancel1_callback(const String & state){
      
      RTC.turnOffAlarm(1); //只设置了控制寄存器中的A1IE位置0,INTCN位不变
       
    }
    

    9、闹钟中断触发

    ICACHE_RAM_ATTR void alarm_interrupt(){
     Serial.println("alarm 中断启动。。。。。。。");
     ReadData(EEPROMBase3,Mp3Data);
     if (Mp3Data.flag=1){   //有设置就播设置的音乐,没有的话默认播第一首
       //循环播放
        mp3.SetCmdByte(0x06,CMD_assign_cyclic,0x00,(uint8_t)Mp3Data.music>>8,(uint8_t)(Mp3Data.music&0x00FF));
     }else{
        mp3.SetCmdByte(0x06,CMD_assign_cyclic,0x00,0x00,0x01); 
     }
      
    }
    

    中断程序只要知道是去触发闹铃的语名就行了。

    到这里,时钟相关的功能已都基本实现,上面涉及的到功能对应的关键语句都已完整呈现。

    展开全文
  • #define BRT (65536-FOSC/115200/4) //用于串口 #define DS3231_WriteAddress 0xD0 #define DS3231_ReadAddress 0xD1 #define DS3231_add_second 0x00 #define DS3231_add_minute 0x01 #define DS3231_add_hour 0x02...
  • 51读写DS3231

    2017-06-17 16:16:48
    使用51读写DS3231
  • DS1302 DS3231 资料,包括中英文手册和原理图,有DS1302的c语言程序,其中包括LCD显示和串口显示
  • ds3231-spin 这是P8X32A /螺旋桨, P2X8C4M64P /螺旋桨2 DS3231实时时钟的驱动程序对象。 重要说明:该软件旨在与(P8X32A)一起使用或(P2X8C4M64P) 。在尝试使用此代码之前,请先安装适用的库,否则,您将缺少...
  • DS3231_VHDL.zip

    2021-06-28 14:45:46
    本源码 是使用VHDL语言编写的DS3231驱动程序,能够写入或输出 年 月 日 周 时 分 秒信息,采用IIC通信方式。经过测试,完全可用。 测试时,需要 DS3231 芯片 FPGA开发板,主频40MHz。
  • ds3231中文资料

    2016-04-12 17:34:06
    ds3231中文资料
  • git clone https://github.com/Seeed-Studio/pi-hats.git cd pi-hats/CAN-HAT sudo ./install.sh -u rtc_ds3231 sudo shutdown -h now


      网上有蛮多关于ds3231模块用法的介绍,但是我在树莓派4B上测试的时候,基本上都用不了。折腾了四五个小时,下面分享下自己探索出来的方法。

    主要功能:将DS3231设置成为树莓派的系统时钟,树莓派不联网的情况下,可以自动从DS3231获取系统时间。

    1. 驱动下载及安装

    下载DS3231模块的驱动

    git clone https://github.com/Seeed-Studio/pi-hats.git
    
    cd pi-hats/CAN-HAT
    

    安装驱动

    sudo ./install.sh -u rtc_ds3231
    

    重启电脑

    sudo shutdown -h now
    

    在这里插入图片描述

    2. 设置时间

    将时间设置为 2020年 10月1日 20点35分

    date 100120352020.00     备注:10120352020

    3. 时间测试

    date
    

    4. 其他功能

    读取硬件时钟并打印结果

    sudo hwclock -r
    

    通过硬件时钟设置系统时间

    sudo hwclock -s
    

    从当前系统时间设置硬件时钟

    sudo hwclock -w
    

    访问帮助以获得更多用途

    hwclock --help
    

    参考

    • https://www.seeedstudio.com/blog/2020/07/07/raspberry-pi-rtc-tutorial-using-ds1307-and-ds3231-rtcs-with-raspberry-pi-m/

    • https://shumeipai.nxez.com/2019/05/08/raspberry-pi-configuration-of-ds3231-clock-module-i2c-interface.html

    展开全文
  • ds3231sn.7z

    2019-12-13 13:30:38
    STM32通过模拟IIC,驱动DS3231时钟芯片 DS3231芯片精度高达2ppm,年误差最低在2分钟之内
  • ds3231程序

    2015-09-18 09:37:42
    高精度时钟芯片带补偿ds3231的C语言程序,模块化编程,即添即用
  • arduino DS3231

    2016-05-26 19:46:37
    arduino DS3231库 时钟模块
  • ds3231部分资料压缩包

    2018-10-24 16:09:44
    压缩包内涵DS3231Mcn中文资料中文资料附带,基于Arduino的DS3231驱动程序,DS3231连线图。
  • ds3231时钟stm32文件包

    2020-10-16 18:10:16
    ds3231时钟stm32文件包,包括iic,ds3231读写,简单读取和设置时间,可以通过串口读取和设置时间
  • DS3232RTC:用于Maxim Integrated DS3232和DS3231实时时钟的Arduino库
  • DS3231SN

    2019-11-21 16:33:24
    Maxim Integrated新型实时时钟(RTC)DS3231,内部集成了TCXO、RTC和32.768kHz晶体,并采用低成本、标准型、16引脚SOIC封装DS3231是低成本、高精度I²C实时时钟(RTC),具有集成的温补晶振(TCXO)和晶体。该器件包含电池...

    Maxim Integrated新型实时时钟(RTC) DS3231,内部集成了TCXO、RTC和32.768kHz晶体,并采用低成本、标准型、16引脚SOIC封装DS3231是低成本、高精度I²C实时时钟(RTC),具有集成的温补晶振(TCXO)和晶体。该器件包含电池输入端,断开主电源时仍可保持精确的计时。集成晶振提高了器件的长期精确度,并减少了生产线的元件数量。DS3231提供商用级和工业级温度范围,采用16引脚300mil的SO封装。

    RTC保存秒、分、时、星期、日期、月和年信息。少于31天的月份,将自动调整月末的日期,包括闰年的修正。时钟的工作格式可以是24小时或带/AM/PM指示的12小时格式。提供两个可设置的日历闹钟和一个可设置的方波输出。地址与数据通过I²C双向总线串行传输。

    精密的、经过温度补偿的电压基准和比较器电路用来监视VCC状态,检测电源故障,提供复位输出,并在必要时自动切换到备份电源。另外,/RST监视引脚可以作为产生µP复位的手动输入。

    关键特性

    0°C至+40°C范围内精度为±2ppm
    -40°C至+85°C范围内精度为±3.5ppm
    为连续计时提供电池备份输入
    工作温度范围
    商用级:0°C至+70°C
    工业级:-40°C至+85°C
    低功耗
    实时时钟产生秒、分、时、星期、日期、月和年计时,并提供有效期到2100年的闰年补偿
    两个日历闹钟
    可编程方波输出
    高速(400kHz) I²C接口
    工作在3.3V
    数字温度传感器输出:精度为±3°C
    老化修正寄存器
    /RST输出/按钮复位去抖输入
    做了块板子,用ds3231sn时钟芯片,板子其它部分都做好了,昨天网上找了一个stm32驱动ds3231的程序,我用的430单片机,按照程序修改了一下,却死活读取不到正确时间。貌似通讯不对,可是时序延时是完全按照网上的程序的。为什么会这样?附原理图。
    补充:在仿真时,时间读取函数里面,仿真看到年月日时分秒都是0。/****************************************************/
    把代码贴出来吧:

    ///
    /*
    DS3231.C文件
    */

    #include"ds3231sn.h"
    #define SETIIC_SCL P1OUT |= BIT7 
    #define CLRIIC_SCL P1OUT &=~BIT7 

    #define SETIIC_SDA P1OUT |= BIT6
    #define CLRIIC_SDA P1OUT &=~BIT6

    #define IIC_SDA (P1IN&BIT6)
    _calendar_obj calendar;
    #define DS3231_WriteAddress 0xD0   
    #define DS3231_ReadAddress  0xD1
    //-------------------------------------------------------------------
    unsigned char BCD2HEX(unsigned char val)
    {
        unsigned char i;
        i= val&0x0f;
        val >>= 4;
        val &= 0x0f;
        val *= 10;
        i += val;
        return i;
    }

    unsigned short B_BCD(unsigned char val)
    {
      unsigned char i,j,k;
      i=val/10;
      j=val%10;
      k=j+(i<<4);
      return k;
    }
    //-------------------------------------------------------------------
    void IIC_Init(void)
    {//IIC总线初始化函数
        P1DIR |= BIT7;P1DIR |= BIT6;
        SETIIC_SDA;//释放IIC总线的数据线。
        SETIIC_SCL;//释放IIC总线的时钟线。
    }
    //-------------------------------------------------------------------
    void IIC_start(void)
    {//IIC总线产生起始信号函数
         P1DIR |= BIT6;
         SETIIC_SDA;//拉高数据线
         delay_us(1);
         SETIIC_SCL;//拉高时钟线
         delay_us(5);
         CLRIIC_SDA;//在时钟线为高电平时,拉低数据线,产生起始信号。
         delay_us(5);
         CLRIIC_SCL;//拉低时钟线
         delay_us(2);
    }
    //-------------------------------------------------------------------
    void IIC_stop(void)
    {//IIC总线产生停止信号函数
        P1DIR |= BIT6;
        CLRIIC_SCL;//拉低时钟线
        CLRIIC_SDA;//拉低数据线
        delay_us(4);
        SETIIC_SCL;//拉高时钟线。
        delay_us(5);
        SETIIC_SDA;//时钟时线为高电平时,拉高数据线,产生停止信号。
        delay_us(4);
    }
    //-------------------------------------------------------------------
    unsigned char IIC_Tack(void)
    {//接收应答信号函数
        unsigned char timnu=0;//定义一个位变量,来暂存应答状态。
        P1DIR &=~ BIT6;
        SETIIC_SDA;//释放数据总线,准备接收应答信号。
        delay_us(1);
        SETIIC_SCL;//拉高时钟线。
        delay_us(1);
        while(IIC_SDA==1)//读取应答信号的状态。
        {
          timnu++;
          if(timnu>250)
          {
            IIC_stop();
            return 1;//返回应答信号的状态,0表示应答,1表示非应答。
          }
        }
        CLRIIC_SCL;//拉低时钟线。
        return 0;//返回应答信号的状态,0表示应答,1表示非应答。
    }
    //产生ACK应答
    void IIC_Ack(void)
    {
            P1DIR |= BIT6;
            CLRIIC_SCL;
            CLRIIC_SDA;
            delay_us(2);
            SETIIC_SCL;
            delay_us(2);
            CLRIIC_SCL;
    }
    //不产生ACK应答                    
    void IIC_NAck(void)
    {
            P1DIR |= BIT6;
            CLRIIC_SCL;
            SETIIC_SDA;
            delay_us(2);
            SETIIC_SCL;
            delay_us(2);
            CLRIIC_SCL;
    }                
    //-------------------------------------------------------------------
    void IIC_write_byte(unsigned char Data)
    {//向IIC总线写入一个字节的数据函数
        unsigned char i;
        P1DIR |= BIT6;
        CLRIIC_SCL;//拉低时钟线,允许改变数据线的状态
        for(i=0;i<8;i++)
        {              
                    if((Data&0x80)>>7)
                       SETIIC_SDA;
                    else
                       CLRIIC_SDA;
                    Data<<=1;           
                    delay_us(2);   //对TEA5767这三个延时都是必须的
                    SETIIC_SCL;//拉高时钟线。
                    delay_us(2); 
                    CLRIIC_SCL;//拉低时钟线,允许改变数据线的状态
                    delay_us(2);
        }
    }
    //-------------------------------------------------------------------
    unsigned char IIC_read_byte(unsigned char ack)
    {//从IIC总线读取一个字节的数据函数
        unsigned char i;
        unsigned char Data=0;       //定义一个缓冲寄存器。
        P1DIR &=~ BIT6;
        for(i=0;i<8;i++)//有8位数据
        {
            CLRIIC_SCL;//拉低时钟线,为读取下一位数据做准备。
            delay_us(2);
            SETIIC_SCL;//拉高时钟线,为读取下一位数据做准备。
            Data=Data<<1;//将缓冲字节的数据左移一位,准备读取数据。

            if(IIC_SDA==1)//如果数据线为高平电平。
                Data++;delay_us(1);
        }
         if (!ack)
            IIC_NAck();//发送nACK
        else
            IIC_Ack(); //发送ACK   
        return Data;//返回读取的一个字节数据。
    }
    //-------------------------------------------------------------------
    void IIC_single_byte_write(unsigned char Waddr,unsigned char Data)
    {//向任意地址写入一个字节数据函数
        IIC_start();//产生起始信号
        delay_us(5);
        IIC_write_byte(DS3231_WriteAddress);//写入设备地址(写)
        IIC_Tack();//等待设备的应答.
        delay_us(5);
        IIC_write_byte(Waddr);//写入要操作的单元地址。
        IIC_Tack();//等待设备的应答。
        delay_us(5);
        IIC_write_byte(Data);//写入数据。
        IIC_Tack();//等待设备的应答。
        delay_us(5);
        IIC_stop();//产生停止符号。
    }
    //-------------------------------------------------------------------
    unsigned char IIC_single_byte_read(unsigned char Waddr)
    {//从任意地址读取一个字节数据函数
        unsigned char Data;//定义一个缓冲寄存器。
        IIC_start();//产生起始信号
        IIC_write_byte(DS3231_WriteAddress);//写入设备地址(写)
        IIC_Tack();//等待设备的应答
        delay_us(5);
        IIC_write_byte(Waddr);//写入要操作的单元地址。
        IIC_Tack();//等待设备的应答。
        delay_us(5);
        IIC_start();//产生起始信号
        IIC_write_byte(DS3231_ReadAddress);//写入设备地址(写)
        IIC_Tack();//等待设备的应答
        delay_us(5);
        Data=IIC_read_byte(1);//写入数据。
        IIC_stop();//产生停止符号。
        //-------------------返回读取的数据--------------------
        return Data;//返回读取的一个字节数据。
    }
    void Read_RTC(void)
    {
      calendar.w_year=IIC_single_byte_read(0x06);  
      calendar.w_month=IIC_single_byte_read(0x05);  
      calendar.w_date=IIC_single_byte_read(0x04); 
      calendar.hour=IIC_single_byte_read(0x02);  
      calendar.min=IIC_single_byte_read(0x01);
      calendar.sec=IIC_single_byte_read(0x00);  
    }
    void Set_RTC(unsigned char yea,unsigned char mon,unsigned char da,unsigned char hou,unsigned char min,unsigned char sec)
    {
      unsigned char temp=0;

      temp=B_BCD(yea);
      IIC_single_byte_write(0x06,temp);

      temp=B_BCD(mon);
      IIC_single_byte_write(0x05,temp);

      temp=B_BCD(da);
      IIC_single_byte_write(0x04,temp);

      temp=B_BCD(hou);
      IIC_single_byte_write(0x02,temp);

      temp=B_BCD(min);
      IIC_single_byte_write(0x01,temp);

      temp=B_BCD(sec);
      IIC_single_byte_write(0x00,temp);
    }
    void get_show_time(void)
    {
      calendar.w_year=IIC_single_byte_read(0x06);  
      calendar.w_year=BCD2HEX(calendar.w_year);


      calendar.w_month=IIC_single_byte_read(0x05); 
      calendar.w_month=BCD2HEX(calendar.w_month);


      calendar.w_date=IIC_single_byte_read(0x04);  
      calendar.w_date=BCD2HEX(calendar.w_date);


      calendar.hour=IIC_single_byte_read(0x02); 
      calendar.hour&=0x3f;                   
      calendar.hour=BCD2HEX(calendar.hour);


      calendar.min=IIC_single_byte_read(0x01);
      calendar.min=BCD2HEX(calendar.min);


      calendar.sec=IIC_single_byte_read(0x00);
      calendar.sec=BCD2HEX(calendar.sec);
    }
    void DS3231_Initial()
    {
        IIC_Init();
        IIC_single_byte_write(0x0e,0);
        delay_ms(2);
        IIC_single_byte_write(0x0f,0);
        delay_ms(2);
    }
     
    ————————————————
    版权声明:本文为CSDN博主「m0_37895072」的原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接及本声明。
    原文链接:https://blog.csdn.net/m0_37895072/article/details/102979136

    展开全文
  • DS3231库文件

    2017-10-15 14:15:59
    DS3231的库函数,可以直接使用于esp8266,stm32等。。。。。。。。。。。
  • led+ds3231电子钟

    2018-11-02 15:33:10
    模块化led+ds3231电子钟 ds3231是带温度补偿 的时钟芯片,年误差最大只有120秒, 一般年误差小于60秒
  • ds3231时钟芯片 资料

    2019-04-15 13:42:16
    ds3231时钟芯片 资料,包含芯片介绍以及程序代码,详细的解释
  • STM32 DS3231驱动.zip

    2020-07-16 17:26:43
    资源内有基于STM32的DS3231驱动,分别使用STM32模拟IIC与硬件IIC与DS3231通信,工程可使用Keil5 MDK直接打开,亲测可用。

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 1,271
精华内容 508
关键字:

ds3231