esp32 操作DS1307时钟芯片

news2024/9/27 2:43:20

电气参数摘要

  • 有VCC供电,IIC活动状态是1.5mA,待机状态200μA,电池电流5nA(MAX=50nA)
  • 无VCC供电的时候,电池电流,300nA(时钟运行),10nA(时钟停止)
  • 供电电压是4.5-5.5V,不支持3.3V
  • IIC频率最大400kHZ。
  • 因为ESP32不支持5V电压,但是DS1307必须用5V供电,因此在IIC上拉电阻的位置,必须上拉到3.3V。否则直接给ESP32的IO灌5V可能会烧掉。可以使用ESP32内部的IO上拉,然后去掉外部的上拉就行。

IIC的通信

  • 访问是通过实施启动条件,并提供设备识别代码,后跟寄存器地址而获得的。可以按顺序访问后续寄存器,直到执行停止条件为止。
  • 芯片iic地址是0x68
  • 配置寄存器,先发送设备地址,发送寄存器地址(比如0),然后发送寄存器的值。可以一次性发送多个字节,芯片会自动偏移寄存器地址。
  • 读取寄存器,先发送寄存器地址,然后读取。支持连续读取多个寄存器。

寄存器

  • RTC寄存器位于地址00h至07h的位置。
  • RAM寄存器位于地址08h至3Fh的位置。

在多字节访问期间,当地址指针达到3Fh,即RAM空间的末尾时,它会环绕到位置00h,即时钟空间的开头。
在这里插入图片描述

  • 在初次上电的时候(指初次装上纽扣电池),CH位是置1的,表示振荡器停止,计时功能处于停止状态。这时候纽扣电池的耗电量位10nA。
  • 所以在初次使用的时候,需要对CH位清零,一般这个清零操作会在设置当前时间到DS1307时同时完成。
  • 当CH位置0后,断开主电,RTC也会继续运行,这时候纽扣电池的耗电量典型值为300nA(无方波输出时)。

计算

  1. 芯片将“年月日时分秒周”存放到地址00-06这7个寄存器里面。每个寄存器相应bit对应的含义,看寄存器列表。
  2. 读取秒的寄存器是00h。先要读取出10倍数的秒(也就是十位数),对应BIT4~bit6.
    然后读取个位数的秒数,BIT0~BIT3.
    在这里插入图片描述
    比如读取到寄存器值为0x59,则对应二进制为00101 1001b。则bit4~bit6=5 ,BIT0~BIT3= 9最终为5*10+9=59秒。
    这个寄存器的CH位是时钟启停控制bit。
    3.比如读小时,小时在芯片里面有12小时表示法和24小时表示法。具体看BIT6。
    当bit6=1,则剩余的bit按照12小时制展开。
    当bit6=0,则剩余的bit按照24小时制展开。
    在这里插入图片描述

DS1307上的RAM

这个RAM是留给用户使用的存储空间,RTC不会用到这部分RAM

DS1307上的RAM(随机存储器)用于存储临时数据,用户自定义的设置以及其他需要在断电时保持的信息。以下是DS1307上RAM的主要用途:

存储用户数据: 用户可以将自定义数据存储在DS1307的RAM中。这可以包括配置参数、计数器值、标志位等。因为这部分RAM是带电池支持的,所以即使在主电源断电时,这些数据也会被保持。

保存配置信息: DS1307的RAM可以用于存储与实时时钟(RTC)和其他功能相关的配置信息。这些配置信息可能包括时钟格式(12小时或24小时制)、日期格式、方波输出频率等。

临时存储: RAM还可用于存储临时性的运行时数据。例如,当进行时钟校准或其他运行时操作时,可能需要在RAM中存储一些中间数据。

断电备份: 由于RAM是带电池支持的,所以它提供了断电备份的功能。即使主电源断电,RAM中的数据仍然会被保存,确保在电源重新连接时可以恢复先前的状态。

总的来说,DS1307上的RAM为用户提供了一块持久存储区域,允许在断电时保留关键的信息。这在需要在系统重新上电时恢复先前状态或保留特定配置和数据时非常有用。

操作时序

设置时钟,比如设置时钟为2024-01-26 10:37:10 周五
在这里插入图片描述发送的字节依次为:设备地址0x68,寄存器地址00,接下来7个字节是要设置进00h-06h这7个寄存器的值。

读取时钟
1.先发送一个数据00,将读取指针只想寄存器0.这个操作在数据手册有说。
在这里插入图片描述2.然后连续读取出数据

在这里插入图片描述## 赋上次芯片的driver代码

#include <stdio.h>
#include "esp_log.h"
#include "ds1307_driver.h"
#include "driver/i2c.h"
#include <string.h>

static const char *TAG = "ds1307-driver";

#define I2C_MASTER_SCL_IO CONFIG_I2C_MASTER_SCL /*!< GPIO number used for I2C master clock */
#define I2C_MASTER_SDA_IO CONFIG_I2C_MASTER_SDA /*!< GPIO number used for I2C master data  */
#define I2C_MASTER_NUM 0                        /*!< I2C master i2c port number, the number of i2c peripheral interfaces available will depend on the chip */
#define I2C_MASTER_FREQ_HZ 100000               /*!< I2C master clock frequency */
#define I2C_MASTER_TX_BUF_DISABLE 0             /*!< I2C master doesn't need buffer */
#define I2C_MASTER_RX_BUF_DISABLE 0             /*!< I2C master doesn't need buffer */
#define I2C_MASTER_TIMEOUT_MS 1000

#define DS1307_I2C_ADDR 0x68 /*!< Slave address of the MPU9250 sensor */

RTC_time_typedef time;

esp_err_t ds1307_init(void)
{
    int ret;

    // 初始化iic
    int i2c_master_port = I2C_MASTER_NUM;

    i2c_config_t conf = {
        .mode = I2C_MODE_MASTER,
        .sda_io_num = I2C_MASTER_SDA_IO,
        .scl_io_num = I2C_MASTER_SCL_IO,
        .sda_pullup_en = GPIO_PULLUP_ENABLE,
        .scl_pullup_en = GPIO_PULLUP_ENABLE,
        .master.clk_speed = I2C_MASTER_FREQ_HZ,
    };

    i2c_param_config(i2c_master_port, &conf);

    ret = i2c_driver_install(i2c_master_port, conf.mode, I2C_MASTER_RX_BUF_DISABLE, I2C_MASTER_TX_BUF_DISABLE, 0);

    ESP_LOGI(TAG, "I2C initialized successfully");

    return ret;
}

esp_err_t ds1307_read_time(date_time_t *p_time)
{
    int ret;
    uint8_t write_buf[8] = {0};
    uint8_t *p = (uint8_t *)p_time;

    // 1.先要发一个字节(write),值为0,
    write_buf[0] = 0;
    ret = i2c_master_write_to_device(I2C_MASTER_NUM, DS1307_I2C_ADDR, write_buf, 1, I2C_MASTER_TIMEOUT_MS / portTICK_PERIOD_MS);

    vTaskDelay(20 / portTICK_PERIOD_MS);

    // 开始读取数据
    ret = i2c_master_read_from_device(I2C_MASTER_NUM, DS1307_I2C_ADDR, (uint8_t *)&time, 7, I2C_MASTER_TIMEOUT_MS / portTICK_PERIOD_MS);

    ESP_LOGI(TAG, "get raw data:%x,%x,%x,%x,%x,%x,%x,", *(p + 0), *(p + 1), *(p + 2), *(p + 03), *(p + 04), *(p + 05), *(p + 06));

    p_time->second = time.seconds.ten_sec * 10 + time.seconds.seconds;
    p_time->minute = time.minutes.ten_min * 10 + time.minutes.minutes;
    p_time->hour = time.hours.ten_hour * 10 + time.hours.hours;
    p_time->week = time.weeks.week;
    p_time->day = time.dates.ten_date * 10 + time.dates.date;
    p_time->month = time.months.ten_month * 10 + time.months.month;
    p_time->year = time.years.ten_year * 10 + time.years.year;

    ESP_LOGI(TAG, "%d-%d-%d %d:%d:%d week=%d", p_time->year, p_time->month, p_time->day, p_time->hour, p_time->minute, p_time->second, p_time->week);

    return ret;
}

/**
 * @brief 设置芯片的时间
 */
esp_err_t ds1307_set_time(date_time_t datetime)
{
    int ret;
    RTC_time_typedef time;
    uint8_t write_buf[9] = {0};
    uint8_t *p = (uint8_t *)&time;

    time.years.ten_year = datetime.year / 10;
    time.years.year = datetime.year % 10;
    time.months.ten_month = datetime.month / 10;
    time.months.month = datetime.month % 10;
    time.dates.ten_date = datetime.day / 10;
    time.dates.date = datetime.day % 10;
    time.weeks.week = datetime.week;
    time.hours.ten_hour = datetime.hour / 10;
    time.hours.hours = datetime.hour % 10;
    time.minutes.ten_min = datetime.minute / 10;
    time.minutes.minutes = datetime.minute % 10;
    time.seconds.ten_sec = datetime.second / 10;
    time.seconds.seconds = datetime.second % 10;
    time.seconds.ch = 0;

    ESP_LOGI(TAG, "set raw data:%x,%x,%x,%x,%x,%x,%x,", *(p + 0), *(p + 1), *(p + 2), *(p + 03), *(p + 04), *(p + 05), *(p + 06));

    memcpy(write_buf + 1, p, 7);

    ret = i2c_master_write_to_device(I2C_MASTER_NUM, DS1307_I2C_ADDR, write_buf, 8, I2C_MASTER_TIMEOUT_MS / portTICK_PERIOD_MS);

    return ret;
}

头文件

#ifndef __DS1307_H_
#define __DS1307_H_

#include "driver/i2c.h"

typedef struct
{
    union
    {
        uint8_t value;
        struct
        {
            uint8_t seconds : 4;
            uint8_t ten_sec : 3;
            uint8_t ch : 1;
        };
    };
} second_data_TypeDef; // 秒

typedef struct
{
    union
    {
        uint8_t value;
        struct
        {
            uint8_t minutes : 4;
            uint8_t ten_min : 3;
            uint8_t bit7 : 1;
        };
    };
} minutes_data_TypeDef; // 分

typedef struct
{
    union
    {
        uint8_t value;
        struct
        {
            uint8_t hours : 4;
            uint8_t ten_hour : 2;
            uint8_t jinzhi : 1;
            uint8_t : 1;
        };
    };
} hours_data_TypeDef; // 时

typedef struct
{
    union
    {
        uint8_t value;
        struct
        {
            uint8_t week : 3;
            uint8_t : 5;
        };
    };
} weeks_data_TypeDef; // 周

typedef struct
{
    union
    {
        uint8_t value;
        struct
        {
            uint8_t date : 4;
            uint8_t ten_date : 2;
            uint8_t : 2;
        };
    };
} dates_data_TypeDef; // 日

typedef struct
{
    union
    {
        uint8_t value;
        struct
        {
            uint8_t month : 4;
            uint8_t ten_month : 1;
            uint8_t : 3;
        };
    };
} months_data_TypeDef; // 月

typedef struct
{
    union
    {
        uint8_t value;
        struct
        {
            uint8_t year : 4;
            uint8_t ten_year : 4;
        };
    };
} years_data_TypeDef; // 年

typedef struct
{
    second_data_TypeDef seconds;
    minutes_data_TypeDef minutes;
    hours_data_TypeDef hours;
    weeks_data_TypeDef weeks;
    dates_data_TypeDef dates;
    months_data_TypeDef months;
    years_data_TypeDef years;
} RTC_time_typedef;

typedef struct
{
    uint16_t year;
    uint16_t month;
    uint16_t day;
    uint8_t week;
    uint16_t hour;
    uint16_t minute;
    uint16_t second;
} date_time_t;

esp_err_t ds1307_init(void);
esp_err_t ds1307_read_time(date_time_t *p_time);
esp_err_t ds1307_set_time(date_time_t datetime);

#endif

main文件

#include <stdio.h>
#include "esp_log.h"
#include "ds1307_driver.h"

static const char *TAG = "i2c_DS1307_main";

void app_main(void)
{
    date_time_t date_time={
        .year = 24,
        .month = 1,
        .day = 26,
        .week = 5,
        .hour = 10,
        .minute = 37,
        .second = 10,
    },date_time_now;

    ESP_ERROR_CHECK(ds1307_init());
    

    /* Read the MPU9250 WHO_AM_I register, on power up the register should have the value 0x71 */
    ESP_ERROR_CHECK(ds1307_set_time(date_time));
    ESP_LOGI(TAG, "set successfully");

    vTaskDelay(3000/portTICK_PERIOD_MS);

    while(1)
    {
        ds1307_read_time(&date_time_now);
        vTaskDelay(1000/portTICK_PERIOD_MS);
    }

}


程序小结:

  1. 这个芯片读取数据没有校验位,因此在操作的时候,如果太快,还是比较容易出现数据不对。因此要想办法校验数据正确性。
  2. 可以多次读取,然后判断值的有效性

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1414513.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

ASP.NET Core 7 Web 使用Session

ASP.NET Core 好像不能像20年前那样直接使用Session函数&#xff0c;我使用如下方法 1、在NuGet安装以下2个包 2、在Program.cs注册 //注册Session builder.Services.AddSession(options > {options.IdleTimeout TimeSpan.FromMinutes(60);options.Cookie.HttpOnly fals…

大小端(C语言)

一、什么是大小端&#xff1a; 1.大端(Big-Endian):高地址存放低位 2.小端(Little-Endian):高地址存放高位 例如&#xff1a;0x11223344在内存中存储 大小端影响了什么&#xff1f; 当基本数据类型占用字节数超过了1字节后&#xff0c;大小端决定了数据按照什么顺序存储在…

3. SQL 语言

重点&#xff1a; MySQL 的 三种安装方式&#xff1a;包安装&#xff0c;二进制安装&#xff0c;源码编译安装。 MySQL 的 基本使用 MySQL 多实例 DDLcreate alter drop DML insert update delete DQL select 3&#xff09;SQL 语言 3.1&#xff09;关系型数据库的常见…

C语言-算法-背包

[USACO07DEC] Charm Bracelet S&#xff08;01背包&#xff09; 题目描述 Bessie has gone to the mall’s jewelry store and spies a charm bracelet. Of course, she’d like to fill it with the best charms possible from the N (1 ≤ N ≤ 3,402) available charms. E…

通过LiveNVR实现海康大华华为宇视等监控摄像头在服务器上录像存储,并web无插件直播和回放

支持云端录像服务器上面集中录像存储在部署LiveNVR的服务器上面 1、流媒体服务软件2、配置开启录像(云端录像)3、录像回看(云端录像)3.1、查看录像3.1.1、时间轴视图3.1.2、列表视图 4、云端录像相关接口5、如何分享时间轴录像回看&#xff1f;6、iframe集成示例7、RTSP/HLS/FL…

Docker 容器内运行 mysqldump 命令来导出 MySQL 数据库,自动化备份

备份容器数据库命令&#xff1a; docker exec 容器名称或ID mysqldump -u用户名 -p密码 数据库名称 > 导出文件.sql请替换以下占位符&#xff1a; 容器名称或ID&#xff1a;您的 MySQL 容器的名称或ID。用户名&#xff1a;您的 MySQL 用户名。密码&#xff1a;您的 MySQL …

数据结构——用链表实现Map

目录 一、映射&#xff08;Map&#xff09; 二、代码实现 1.建立接口 2.方法实现 &#xff08;1&#xff09;映射的建立 键&#xff08;key&#xff09;和值&#xff08;val&#xff09;的建立 重写toString方法 &#xff08;2&#xff09;构造方法 &#xff08;3&…

详解Mockito

详解Mockito 1. Mockito简介 在我们的编程世界中&#xff0c;测试是一个非常重要的环节&#xff0c;它能帮助我们确保代码的质量和稳定性。而在众多的测试方法中&#xff0c;Mock测试是一种非常有效的手段。 1.1 什么是 Mock 测试 Mock测试&#xff0c;顾名思义&#xff0c;…

夹耳式骨传导耳机怎么戴?有什么注意事项吗

骨传导耳机是靠震动我们的颅骨来播放声音的耳机&#xff0c;它的厉害之处在于不用塞进耳朵里&#xff0c;所以不会让耳朵感到堵塞。这意味着在运动、听歌、打电话等各种活动的时候&#xff0c;它们可以提供一个非常特别的体验。而骨传导耳机里有一种类别叫做夹耳式骨传导耳机&a…

2024初学编曲免费软件FL Studio21.2.2

FL Studio在业内也被称作“水果”软件&#xff0c;这是一款功能强大、简单易上手的专业编曲软件。软件中的音效插件库拥有超过25种音效插件&#xff0c;能够帮助激发我们的创作灵感。而FL Studio中文还推出了训练营课程&#xff0c;初学者可以在训练营中进行编曲知识的学习&…

Java多线程--线程的生命周期

文章目录 一、JDK1.5之前&#xff1a;5种状态五种状态1、新建2、就绪3、运行4、阻塞5、死亡 二、JDK1.5及之后&#xff1a;六种状态 Java语言使用 Thread类及其子类的对象来表示 线程&#xff0c;在它的一个完整的生命周期中通常要经历如下一些状态。 一、JDK1.5之前&#xf…

【Java面试】Mysql

目录 sql的执行顺序索引的优点和缺点怎么避免索引失效(也属于sql优化的一种)一条sql查询非常慢&#xff0c;我们怎么去排查和优化&#xff1f;存储引擎 MylSAM和InnoDB、Memory的区别事务的四大特性(ACID)脏读、不可重复读、幻读事务的隔离级别&#xff1f;怎么优化数据库SQL优…

Java中SimpleDateFormat时YYYY与yyyy以及HH和hh的区别注意踩坑

场景 Java开发手册中为什么要求SimpleDateFormat时用y表示年&#xff0c;而不能用Y&#xff1a; Java开发手册中为什么要求SimpleDateFormat时用y表示年&#xff0c;而不能用Y_simpledateformat 怎么确定y就是年-CSDN博客 在使用SimpleDateFormat在获取当前日期时因使用了YY…

【DDD】学习笔记-软件开发团队的沟通与协作

领域驱动设计的核心是“领域”&#xff0c;因此要运用领域驱动设计&#xff0c;从一开始就要让团队走到正确的点儿上。当我们组建好了团队之后&#xff0c;应该从哪里开始&#xff1f;不是 UI 原型设计、不是架构设计、也不是设计数据库&#xff0c;这些事情虽然重要但却非最高…

STM32F1之RTC实时时钟(Unix时间戳)

目录 1. Unix时间戳 2. UTC/GMT 3. 时间戳转换 3.1 time_t 3.2 struct tm 3.3 char * 3.4 时间戳的使用 实时时钟是一个独立的定时器。RTC模块拥有一组连续计数的计数器&#xff0c;在相应软件配置下&#xff0c;可提供时钟日历的功能。修改计数器的值可以重新设置…

leetcode hot100 组合总和Ⅲ

本题中&#xff0c;要求我们求在1-9范围内&#xff0c;满足k个数的和为n的组合&#xff08;组合是无序的&#xff0c;并且题目中要求不可以重复&#xff09;。 这种组合问题依旧需要用回溯算法来解决。因为我们没办法控制产生k层for循环。回溯算法的过程是构建树结构&#xff…

巴厘行记(二)——乌布之夜

欢迎览阅《巴厘行记》系列文章 巴厘行记巴厘行记&#xff08;一&#xff09;——海神庙 巴厘行记&#xff08;二&#xff09;——乌布之夜 巴厘行记&#xff08;三&#xff09;——Auntie和Mudi 巴厘行记&#xff08;四&#xff09;——乌布漫游 巴厘行记&#xff08;五&a…

【学网攻】 第(10)节 -- 路由器单臂路由配置

系列文章目录 目录 系列文章目录 文章目录 前言 一、单臂路由是什么&#xff1f; 二、实验 1.引入 实验拓扑图 PC配置 Sw配置 Router配置 实验验证 总结 文章目录 【学网攻】 第(1)节 -- 认识网络【学网攻】 第(2)节 -- 交换机认识及使用【学网攻】 第(3)节 -- 交…

Qt使用中文字符串乱码的问题

文章目录 vs编译器下第一种解决方式第二种解决方式 Qt编译器下 我们在使用qt的时候有时候会遇到打印中文字符串的时候出现中文乱码的问题&#xff0c;主要是由于Qt的QString字符串存储的方式是使用utf-8的编码方式&#xff0c;如果我们本地的文件是使用GBK方式的编码再使用中文…

Spring: alibaba代码规范校验工具checkstyle

文章目录 一、idea配置checkstyle插件二、激活CheckStyle三、配置自动格式化功能四、使用代码格式化 一、idea配置checkstyle插件 下载 Intellij IDEA Checkstyle 插件&#xff1a;File -> setting -> plugin通过关键字CheckStyle-IDEA搜索并安装。 安裝完成后重启idea…