DS1302时钟芯片+esp8266 / spi 学习 arduino

news2025/1/15 8:37:03

DS1302时钟芯片+esp8266

        这个芯片往上能找到很多资料,这里主要记录我手里的模块,

看了下芯片资料,说是当vcc 供电小于备用时用备用电源

这里直接没有接vcc 

遇到的问题

1.esp8266复位短路导致串口断开:

当只接scl sda rst  三个引脚的时候 esp8266复位会 导致短路,也有可能是之前我宏定义 复位引脚的时候命名问题,如果你也遇到这个问题,把gnd 接上就行 

2.自己手写的模拟spi 无法正常工作:

改来改去,没办法,还是用了别人写好的库

分析代码 

主体代码

// CONNECTIONS:
// DS1302 CLK/SCLK --> 5
// DS1302 DAT/IO --> 4
// DS1302 RST/CE --> 2
// DS1302 VCC --> 3.3V - 5V
// DS1302 GND --> GND
#include <Arduino.h>
#include <RtcDS1302.h>

// 定义 ThreeWire 对象,用于与 DS1302 RTC 通信
ThreeWire myWire(12, 13, 16); // IO, SCLK, CE
RtcDS1302<ThreeWire> Rtc(myWire);

// 打印日期时间的函数
void printDateTime(const RtcDateTime& dt);

void setup() 
{
    // 初始化串口通信
    Serial.begin(57600);

    // 输出编译日期和时间
    Serial.print("compiled: ");
    Serial.print(__DATE__);
    Serial.println(__TIME__);

    // 开始 RTC 通信
    Rtc.Begin();

    // 获取当前编译日期和时间
    RtcDateTime compiled = RtcDateTime(__DATE__, __TIME__);
    printDateTime(compiled);
    Serial.println();

    // 检查 RTC 是否有效
    if (!Rtc.IsDateTimeValid()) 
    {
        // 常见原因:
        // 1) 第一次运行时设备尚未启动
        // 2) 设备电池电量低或缺失
        Serial.println("RTC lost confidence in the DateTime!");
        Rtc.SetDateTime(compiled);
    }

    // 检查 RTC 是否被写保护
    if (Rtc.GetIsWriteProtected())
    {
        Serial.println("RTC was write protected, enabling writing now");
        Rtc.SetIsWriteProtected(false);
    }

    // 检查 RTC 是否正在运行
    if (!Rtc.GetIsRunning())
    {
        Serial.println("RTC was not actively running, starting now");
        Rtc.SetIsRunning(true);
    }

    // 获取当前日期时间
    RtcDateTime now = Rtc.GetDateTime();
    if (now < compiled) 
    {
        Serial.println("RTC is older than compile time!  (Updating DateTime)");
        Rtc.SetDateTime(compiled);
    }
    else if (now > compiled) 
    {
        Serial.println("RTC is newer than compile time. (this is expected)");
    }
    else if (now == compiled) 
    {
        Serial.println("RTC is the same as compile time! (not expected but all is fine)");
    }
}

void loop() 
{
    // 获取当前日期时间
    RtcDateTime now = Rtc.GetDateTime();

    // 打印日期时间
    printDateTime(now);
    Serial.println();

    // 检查日期时间是否有效
    if (!now.IsValid())
    {
        // 常见原因:
        // 1) 设备电池电量低或缺失且电源线断开
        Serial.println("RTC lost confidence in the DateTime!");
    }

    // 延时 10 秒
    delay(10000); // 十秒
}

// 宏定义,计算数组长度
#define countof(a) (sizeof(a) / sizeof(a[0]))

// 打印日期时间的函数
void printDateTime(const RtcDateTime& dt)
{
    char datestring[26]; // 存储日期时间字符串

    // 格式化日期时间字符串
    snprintf_P(datestring, 
               countof(datestring),
               PSTR("%02u/%02u/%04u %02u:%02u:%02u"),
               dt.Month(),
               dt.Day(),
               dt.Year(),
               dt.Hour(),
               dt.Minute(),
               dt.Second());
    Serial.print(datestring);
}

看看它库文件是如何定义的 (打开RtcDS1302.h )

#pragma once

#include <Arduino.h>
#include "RtcUtility.h"
#include "RtcDateTime.h"
#include "ThreeWire.h"

// DS1302 寄存器地址
const uint8_t DS1302_REG_TIMEDATE   = 0x80;          // 时间日期寄存器
const uint8_t DS1302_REG_TIMEDATE_BURST = 0xBE;      // 时间日期突发读写寄存器
const uint8_t DS1302_REG_TCR    = 0x90;              // 滴流充电控制寄存器
const uint8_t DS1302_REG_RAM_BURST = 0xFE;           // RAM 突发读写寄存器
const uint8_t DS1302_REG_RAMSTART   = 0xC0;          // RAM 起始地址
const uint8_t DS1302_REG_RAMEND     = 0xFD;          // RAM 结束地址
// RAM 读写地址交错
const uint8_t DS1302RamSize = 31;                    // RAM 大小

// DS1302 滴流充电控制寄存器位
enum DS1302TcrResistor 
{
    DS1302TcrResistor_Disabled = 0,                   // 电阻禁用
    DS1302TcrResistor_2KOhm = 0b00000001,             // 2K 欧姆电阻
    DS1302TcrResistor_4KOhm = 0b00000010,             // 4K 欧姆电阻
    DS1302TcrResistor_8KOhm = 0b00000011,             // 8K 欧姆电阻
    DS1302TcrResistor_MASK  = 0b00000011,             // 电阻掩码
};

enum DS1302TcrDiodes 
{
    DS1302TcrDiodes_None = 0,                         // 无二极管
    DS1302TcrDiodes_One      = 0b00000100,            // 一个二极管
    DS1302TcrDiodes_Two      = 0b00001000,            // 两个二极管
    DS1302TcrDiodes_Disabled = 0b00001100,            // 二极管禁用
    DS1302TcrDiodes_MASK     = 0b00001100,            // 二极管掩码
};

enum DS1302TcrStatus 
{
    DS1302TcrStatus_Enabled  = 0b10100000,            // 启用状态
    DS1302TcrStatus_Disabled = 0b01010000,            // 禁用状态
    DS1302TcrStatus_MASK     = 0b11110000,            // 状态掩码
};

const uint8_t DS1302Tcr_Disabled = DS1302TcrStatus_Disabled | DS1302TcrDiodes_Disabled | DS1302TcrResistor_Disabled;  // 默认禁用设置

// DS1302 时钟停止寄存器及位
const uint8_t DS1302_REG_CH = 0x80;                  // 时钟停止位在秒寄存器中的位置
const uint8_t DS1302_CH     = 7;                     // 时钟停止位

// 写保护寄存器及位
const uint8_t DS1302_REG_WP = 0x8E;                  
const uint8_t DS1302_WP = 7;                         // 写保护位

// RTC 类模板
template<class T_WIRE_METHOD> class RtcDS1302
{
public:
    // 构造函数
    RtcDS1302(T_WIRE_METHOD& wire) :
        _wire(wire)
    {
    }

    // 初始化 RTC
    void Begin()
    {
        _wire.begin();
    }

    // 获取是否写保护
    bool GetIsWriteProtected()
    {
        uint8_t wp = getReg(DS1302_REG_WP);
        return !!(wp & _BV(DS1302_WP));
    }

    // 设置是否写保护
    void SetIsWriteProtected(bool isWriteProtected)
    {
        uint8_t wp = getReg(DS1302_REG_WP);
        if (isWriteProtected)
        {
            wp |= _BV(DS1302_WP);
        }
        else
        {
            wp &= ~_BV(DS1302_WP);
        }
        setReg(DS1302_REG_WP, wp);
    }

    // 检查日期时间是否有效
    bool IsDateTimeValid()
    {
        return GetDateTime().IsValid();
    }

    // 获取 RTC 是否运行
    bool GetIsRunning()
    {
        uint8_t ch = getReg(DS1302_REG_CH);
        return !(ch & _BV(DS1302_CH));
    }

    // 设置 RTC 是否运行
    void SetIsRunning(bool isRunning)
    {
        uint8_t ch = getReg(DS1302_REG_CH);
        if (isRunning)
        {
            ch &= ~_BV(DS1302_CH);
        }
        else
        {
            ch |= _BV(DS1302_CH);
        }
        setReg(DS1302_REG_CH, ch);
    }

    // 获取滴流充电设置
    uint8_t GetTrickleChargeSettings()
    {
        uint8_t setting = getReg(DS1302_REG_TCR);
        return setting;
    }

    // 设置滴流充电设置
    void SetTrickleChargeSettings(uint8_t setting)
    {
        if ((setting & DS1302TcrResistor_MASK) == DS1302TcrResistor_Disabled) 
        {
            // 无效电阻设置,设置为禁用
            setting = DS1302Tcr_Disabled;
        }
        else if ((setting & DS1302TcrDiodes_MASK) == DS1302TcrDiodes_Disabled ||
            (setting & DS1302TcrDiodes_MASK) == DS1302TcrDiodes_None) 
        {
            // 无效二极管设置,设置为禁用
            setting = DS1302Tcr_Disabled;
        }
        else if ((setting & DS1302TcrStatus_MASK) != DS1302TcrStatus_Enabled) 
        {
            // 无效状态设置,设置为禁用
            setting = DS1302Tcr_Disabled;
        }

        setReg(DS1302_REG_TCR, setting);
    }

    // 设置日期时间
    void SetDateTime(const RtcDateTime& dt)
    {
        // 设置日期时间
        _wire.beginTransmission(DS1302_REG_TIMEDATE_BURST);

        _wire.write(Uint8ToBcd(dt.Second()));
        _wire.write(Uint8ToBcd(dt.Minute()));
        _wire.write(Uint8ToBcd(dt.Hour())); // 24 小时模式
        _wire.write(Uint8ToBcd(dt.Day()));
        _wire.write(Uint8ToBcd(dt.Month()));

        // RTC 硬件星期是 1-7,1 表示星期一
        // 转换我们的星期到 RTC 星期
        uint8_t rtcDow = RtcDateTime::ConvertDowToRtc(dt.DayOfWeek());

        _wire.write(Uint8ToBcd(rtcDow));
        _wire.write(Uint8ToBcd(dt.Year() - 2000));
        _wire.write(0); // 不写保护,如果写保护则忽略所有这些操作

        _wire.endTransmission();
    }

    // 获取日期时间
    RtcDateTime GetDateTime()
    {
        _wire.beginTransmission(DS1302_REG_TIMEDATE_BURST | THREEWIRE_READFLAG);

        uint8_t second = BcdToUint8(_wire.read() & 0x7F);
        uint8_t minute = BcdToUint8(_wire.read());
        uint8_t hour = BcdToBin24Hour(_wire.read());
        uint8_t dayOfMonth = BcdToUint8(_wire.read());
        uint8_t month = BcdToUint8(_wire.read());

        _wire.read();  // 忽略星期,因为我们自己计算

总结:看不太懂

找找数据手册看看

数据手册icon-default.png?t=O83Ahttps://www.findic.com/doc/browser/bLXENOVde?doc_id=32251673#locale=zh-CN

DS1302中文数据手册 - 豆丁网icon-default.png?t=O83Ahttp:// https://www.docin.com/p-2157760379.html 

电路图 

引脚功能

 时序相关

命令字节:
命令字节启动每个数据传输。MSB(第 7 位)必须是一个逻辑1. 
如果为 0,则禁用对 DS1302 的写入。
如果 逻辑0,则 Bit 6 指定 clock/calendar 数据,
如果 逻辑 1 则指定 RAM 数据。
位 1 至 5 指定要输入或输出的指定寄存器,
LSB(位 0)指定写操作
0的时候是读取
1的时候是写入

命令字节始终以 LSB (位 0) 开头的输入。(这句意思是从低位到高位)

 

时序图:

可以看到当RST在高电平时,芯片才能正常通信

通过时序图可以看出,刚开始的八位发送过去的是命令字节,

数据手册中给出了寄存器地址

根据上述资料 模拟spi 代码实现 

实现失败,留着以后再说................

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

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

相关文章

★ C++进阶篇 ★ AVL树实现

Ciallo&#xff5e;(∠・ω< )⌒☆ ~ 今天&#xff0c;我将继续和大家一起学习C进阶篇第五章----AVL树实现 ~ ❄️❄️❄️❄️❄️❄️❄️❄️❄️❄️❄️❄️❄️❄️澄岚主页&#xff1a;椎名澄嵐-CSDN博客C专栏&#xff1a;★ C进阶篇 ★_椎名澄嵐的博客-CSDN博客 ❄️…

QT工程概述

在Qt中&#xff0c;创建 "MainWindow" 与 "Widget" 项目的主要区别在于他们的用途和功能范围&#xff1a; MainWindow&#xff1a;这是一个包含完整菜单栏、工具栏和状态栏的主窗口应用程序框架。它适合于更复 杂的应用程序&#xff0c;需要这些额外的用户…

Java | Leetcode Java题解之第479题最大回文数乘积

题目&#xff1a; 题解&#xff1a; class Solution {public int largestPalindrome(int n) {if (n 1) {return 9;}int upper (int) Math.pow(10, n) - 1;int ans 0;for (int left upper; ans 0; --left) { // 枚举回文数的左半部分long p left;for (int x left; x >…

uni-app关闭底部系统导航栏的控制按钮BUG

描述 plus.navigator.hideSystemNavigation(); 在uni-app中使用 plus.navigator.hideSystemNavigation(); 关闭导航栏时会出bug会留下一个黑框。这个bug基于手机&#xff1b; 平板的性能来决定出bug频率原因是&#xff1a;过早启用霸屏导致的&#xff08;过早使用plus.navig…

执行vue create XXX报错The operation was rejected by your operating system

创建项目&#xff1a; vue create my-project 报错&#xff1a; npm ERR! code EPERM npm ERR! syscall open npm ERR! path D:\Program Files\nodejs\node_cache\_cacache\tmp\5d2a6f8e npm ERR! errno -4048 npm ERR! Error: EPERM: operation not permitted, open D:\Pro…

18933 括号匹配问题

### 思路 1. **输入处理**&#xff1a;读取输入的字符串。 2. **匹配括号**&#xff1a;使用栈来匹配括号&#xff0c;记录无法匹配的左括号和右括号的位置。 3. **标注输出**&#xff1a;根据记录的位置&#xff0c;生成标注字符串&#xff0c;输出原始字符串和标注字符串。 …

车辆损伤评估数据集(提供分割和检测两种标注方式)6类4000张高分辨率图共9000余标注,6GB数据量

车辆损伤评估数据集&#xff08;提供分割和检测两种标注方式&#xff09; 标注类型包括 dent: 凹痕 scratch: 划痕 crack: 裂缝 glass shatter: 玻璃破碎 tire flat: 轮胎扁平 lamp broken: 车灯损坏 4000张高分辨率图共9000余标注&#xff0c;6GB数据量 车辆损伤评估数据集介…

复合泊松过程

复合泊松过程的均值、方差与特征函数 复合泊松过程的定义 复合泊松过程 ( Y(t) ) 是一种常见的随机过程&#xff0c;通常定义为&#xff1a; Y ( t ) ∑ k 1 N ( t ) X k Y(t) \sum_{k1}^{N(t)} X_k Y(t)k1∑N(t)​Xk​ 其中&#xff1a; ( N(t) ) 是一个强度为 ( \lambd…

IP地址与CDN提升网络速度

视频流媒体、在线游戏、或是电商购物&#xff0c;互联网在我们的工作生活中愈加不可或缺&#xff0c;人们对于网络的加载速度要求也越来越严苛。而IP地址与CDN的协同工作&#xff0c;对于互联网速度增加与稳定起这重大的作用。 一、CDN的工作原理 CDN是由分布在全球各地的服务…

P1439 【模板】最长公共子序列 Python 题解

【模板】最长公共子序列 题目描述 给出 1 , 2 , … , n 1,2,\ldots,n 1,2,…,n 的两个排列 P 1 P_1 P1​ 和 P 2 P_2 P2​ &#xff0c;求它们的最长公共子序列。 输入格式 第一行是一个数 n n n。 接下来两行&#xff0c;每行为 n n n 个数&#xff0c;为自然数 1 …

Shell脚本:分发文件到各个集群节点

找一个全局目录/root/bin 写脚本 touch xsync chmod 777 xsync #!/bin/bash#作者&#xff1a;ldj #时间&#xff1a;2024-10-15 #描述&#xff1a;拷贝文件#1. 判断参数个数 if [ $# -lt 1 ]thenecho "Error: Not Enough Argument!"exit fi#2.遍历集群所有机器 spac…

工业和建筑工地 安全帽-安全带识别数据集 yolo数据集 共2200张 已增强 标注

安全帽-安全带识别数据集 yolo数据集 共2200张 已增强 安全帽检测与安全带识别数据集 图像数量&#xff1a;2,200张增强后标注数量&#xff1a; belt&#xff08;安全带&#xff09;&#xff1a;3,197个head&#xff08;头部&#xff09;&#xff1a;326个helmet&#xff08;安…

asp.net Core 自定义中间件

内联中间件 中间件转移到类中 推荐中间件通过IApplicationBuilder 公开中间件 使用扩展方法 调用中间件 含有依赖项的 》》》中间件 参考资料

数据结构——排序(1)

数据结构——排序(1) 文章目录 数据结构——排序(1)一、排序1.概念&#xff1a;所谓排序&#xff0c;就是使一串记录&#xff0c;按照其中的某个或某些关键字的大小&#xff0c;递增或递减的排列起来的操作。 2.运用&#xff1a;购物筛选排序&#xff0c;院校排名等。 3.常见排…

业务的合并与分批

1.你中有我&#xff0c;我中有你 2.合久必分&#xff0c;分久必合 3.正负负正&#xff0c;正道无穷

MRI学习笔记-LItool使用教程,计算偏侧化指数lateralization index

偏侧化指数介绍 描述功能偏侧化最常用的方法之一是计算偏侧化指数&#xff0c;分别是左侧和右侧感兴趣区域&#xff08;ROI&#xff09;中值高于特定激活阈值的体素数。因此&#xff0c;LI值的范围从1&#xff08;左主导&#xff09;到1&#xff08;右主导&#xff09;。然而&…

AtCoder Beginner Contest 375 A-E 题解

我的老师让我先做最后再交&#xff0c;看正确率&#xff08;即以OI赛制打abc&#xff09; 所以我用的小号&#xff08;… …&#xff09; C 卡了老半天才出来&#xff0c;我把题读错了 难度&#xff1a; A. Seats 题意 给你一个字符串 S S S&#xff0c;仅包含 . 和 #&…

unity 调整skinweight (皮肤权重),解决:衣服穿模问题

提示&#xff1a;文章写完后&#xff0c;目录可以自动生成&#xff0c;如何生成可参考右边的帮助文档 文章目录 前言一、skinweight 是什么&#xff1f;二、代码控制&#xff1a;可根据平台切换1.引入库 总结 前言 最近遇到一个问题&#xff0c;人物模型的衣服穿模&#xff08…

本地拉取Docker镜像打包导入远程服务器

起因是因为使用远程服务器拉取镜像时&#xff0c;由于网络问题一直拉不成功&#xff0c;使用国内镜像由于更新不及时&#xff0c;国内镜像没有最新的 docker 镜像。最后使用本地的计算机&#xff0c;通过代理下载最新的镜像后打包成 tar&#xff0c; 然后上传到远程服务器进行导…

interwirelessac9560感叹号,电脑无法连接wifi,无法搜索到wifi

interwirelessac9560感叹号 电脑无法连接wifi&#xff0c;无法搜索到wifi 原因 这可能是wifl模块出现了问题。 解决方案 1、winx 打开&#xff0c;选择【设备管理器】 2、选择网络适配器 右键打开wireless-AC&#xff0c;选择【卸载设备】。 3、关机2分钟后&#xff0c…