草庐IT

【mcuclub】时钟模块DS1302

单片机俱乐部--官方 2023-04-21 原文

一、实物图

 

二、原理图

编号名称功能
1VCC2双供电配置中的主电源供应引脚。DS1302工作于 VCC1和VCC2中较大者.当VCC2比VCC1高0.2V 时,VCC2 给 DS1302供电。当VCC1比VCC2高时, VCC1给DS1302供电
2X132.768kHz晶振引脚
3X2
4GND电源地
5CE使能引脚。输入信号,在读、写数据期间,必须为高。该引脚有两个功能:第一,CE开始控制字访问移位寄存器的控制逻辑;其次,CE提供结束单字节或多字节数据传输的方法
6I/O数据输入/输出引脚。三线接口时的双向数据线
7SCLK串行时钟引脚, 用来同步串行接口上的数据动作
8VCC1备用电源引脚。在使用涓流充电的系统中,这个管脚连接到可再充能量源

电路图中一些电阻电容作用:


VCC2引脚的电容主要用于滤波,而串联一个电阻可以有效防止电源对芯片的冲击。

晶振两端的电容主要用于起振的,如果不接,会导致时间快几秒,但是时间的精确性主要取决于晶振频率。

VCC1接的是一个纽扣电池,当VCC2的电源断电时,VCC1给芯片供电,这样时钟就会继续运行。

三个上拉电阻作用:

DS1302的数据脚(I/O)是双向的,如果只用单片机弱上拉,双向通讯不成功,可能是因为弱上拉时端口电平翻转慢,造成读数不准。

CE脚和SCLK脚是单向的,可以不用接上拉电阻,单片机弱上拉是可以的。

晶振为什么选取32.768kHz:

时钟系统中,秒是一个重要的时间单位,1秒正是1Hz,如果要提高时间精度,那这个1Hz必须要准确。我们知道,在数字世界里,只有0和1两种可能,下面看一个计算:2^15 = 32768 = 32.768K

2的15次方正好等于32768,反过来讲,如果要把32.768K的时钟频率经过15次分频的话,得到的频率正好是1Hz。所以时钟芯片内部经过15次分频就得到了1Hz,即1s。

三、简介

DS1302 是美国DALLAS公司推出的一种高性能、低功耗、带RAM的实时时钟电路,它可以对年、月、日、周、时、分、秒进行计时,具有闰年补偿功能,工作电压为2.0V~5.5V。采用三线接口与CPU进行同步通信,并可采用突发方式一次传送多个字节的时钟信号或RAM数据。DS1302内部有一个31×8的用于临时性存放数据的RAM寄存器。DS1302是DS1202的升级产品,与DS1202兼容,但增加了主电源/后备电源双电源引脚,同时提供了对后备电源进行涓细电流充电的能力。

四、内部框图

 

五、通信协议

DS1302的通信是SPI的变异种类,它用了 SPI 的通信时序,但是通信的时候没有完全按照 SPI 的规则来。SPI接口是以主从方式工作的,这种模式通常有一个主器件和一个或多个从器件,其接口包括以下四种信号:

1、MOSI – 主器件数据输出,从器件数据输入

2、MISO – 主器件数据输入,从器件数据输出

3、SCLK – 时钟信号,由主器件产生

4、/CS – 从器件使能信号,由主器件控制

而DS1302是三种信号,其中I/O替代了MOSI和MISO,利用1根数据线进行数据输入和输出。

六、寄存器地址定义

 

该寄存器显示了时钟的地址信息,操作时往对应的地址写入值就行,也就是说如果想写入秒,往对应的寄存器写入0x80;表示小时的地址的第7位可选为12小时制还是24小时制,WP是写保护位

时钟暂停标志(CH):

秒寄存器的位7被定义为时钟暂停标志,当此位置1时,时钟振荡器暂停,DS1302进入漏电流小于100nA的低功耗备用模式;当此为置0时时钟开始,初始加电状态未定义。

写保护位(WP):

控制寄存器的位7是写保护位,前7位(位0至位6被强制为0且读取时总是读0,在任何对时钟或RAM的写操作以前,位7必须为0;当为高时,写保护位禁止任何寄存器的写操作,初始加电状态未定义;因此,在试图写器件之前应该清除WP位。

命令字:

命令字启动每一次数据传输时需要配置,第7位固定为1,如果是0则禁止对DS1302的写入,第6位写1则是读取或写入RAM区,写0则读取或写入时钟,第1~5位是地址,即要操作的地址,秒的地址是从0开始;第0位置1是read,对地址进行读取,置0是write,对地址进行写入

例如要读取月信息,则往命令字寄存器写0x89,如要写入月信息,则往命令字寄存器写0x88,对应了RTC左边的地址。

七、时序解析

 

CE输入驱动高启动所有的数据传输。CE输入有两个功能。首先,CE打开控制逻辑,允许访问的移位寄存器的地址/命令序列。其次,CE提供了一个终止单字节或多字节数据传输方法。

一个时钟周期是由一个下降沿之后的上升沿序列。对于数据传输而言,数据必须在有效的时钟的上升沿输入,在时钟的下降沿输出。如果CE为低,数据传输终止。

对于数据输入︰

开始的8个SCLK周期,输入写命令字节,数据字节在后8个SCLK周期的上升沿输入。数据输入位0开始。

代码如下:

void Ds1302_Write_Byte(uchar addr, uchar dat)

{

   uchar i;

   DS1302_CE = 1;                        //启动DS1302总线

   //写入目标地址:addr

   addr = addr & 0xFE;                 //最低位置0,寄存器0位为0时写,为1时读

   for(i = 0; i < 8; i++)

   {

      DS1302_IO = addr & (0x01 << i);

      DS1302_SCLK = 1;

      DS1302_SCLK = 0;

   }

   //写入数据:dat

   for(i = 0; i < 8; i++)

   {

      DS1302_IO = dat & (0x01 << i);

      DS1302_SCLK = 1;

      DS1302_SCLK = 0;

   }

   DS1302_CE = 0;                        //停止DS1302总线

}

对于数据输出︰

开始的8个SCLK周期,输入一个读命令字节,数据字节在后8个SCLK周期的下降沿输出。注意,第一个数据字节的第一个下降沿发生后,命令字的最后一位被写入。当CE仍为高时。如果还有额外的SCLK周期,DS1302将重新发送数据字节,这使DS1302具有连续突发读取的能力。

代码如下:

uchar Ds1302_Read_Byte(uchar addr)

{

   uchar i,dat = 0x00;

   DS1302_CE = 1;                        //启动DS1302总线

   //写入目标地址:addr

   addr = addr | 0x01;                 //最低位置1,寄存器0位为0时写,为1时读

   for(i = 0; i < 8; i++)

   {

      DS1302_IO = addr & (0x01 << i);

      DS1302_SCLK = 0;

      DS1302_SCLK = 1;

   }

   //输出数据:dat

   for(i = 0; i < 8; i++)

   {

      DS1302_SCLK = 1;

      DS1302_SCLK = 0;

      if(DS1302_IO)

       dat |= (0x01 << i);

   }

   DS1302_CE = 0;                        //停止DS1302总线

   DS1302_IO = 0;                        //读取后将IO设置为0,否则读出的数据会出错

   return dat;

}

八、BCD码

BCD码(Binary Coded Decimal‎),用4位二进制数来表示1位十进制数

例:0001 0011表示13,1000 0101表示85,0001 1010不合法

在十六进制中的体现:0x13表示13,0x85表示85,0x1A不合法

BCD码转十进制:DEC=BCD/16 * 10+BCD%16; (2位BCD)

十进制转BCD码:BCD=DEC/10 * 16+DEC%10; (2位BCD)

因为时钟芯片内存放的是BCD码,所以直接读取出来的话会不准确,要转为十进制来显示。

九、流程设计

首先初始化引脚,然后初始化DS1302,设置CE为高,设置是读操作还是写操作,然后写入8位目标地址,接下来如果是写操作,则写入数据,如果是读操作,则读取数据,最后设置CE为低,结束操作。

有关【mcuclub】时钟模块DS1302的更多相关文章

  1. ruby - 在 Ruby 中使用匿名模块 - 2

    假设我做了一个模块如下:m=Module.newdoclassCendend三个问题:除了对m的引用之外,还有什么方法可以访问C和m中的其他内容?我可以在创建匿名模块后为其命名吗(就像我输入“module...”一样)?如何在使用完匿名模块后将其删除,使其定义的常量不再存在? 最佳答案 三个答案:是的,使用ObjectSpace.此代码使c引用你的类(class)C不引用m:c=nilObjectSpace.each_object{|obj|c=objif(Class===objandobj.name=~/::C$/)}当然这取决于

  2. ruby-on-rails - Ruby net/ldap 模块中的内存泄漏 - 2

    作为我的Rails应用程序的一部分,我编写了一个小导入程序,它从我们的LDAP系统中吸取数据并将其塞入一个用户表中。不幸的是,与LDAP相关的代码在遍历我们的32K用户时泄漏了大量内存,我一直无法弄清楚如何解决这个问题。这个问题似乎在某种程度上与LDAP库有关,因为当我删除对LDAP内容的调用时,内存使用情况会很好地稳定下来。此外,不断增加的对象是Net::BER::BerIdentifiedString和Net::BER::BerIdentifiedArray,它们都是LDAP库的一部分。当我运行导入时,内存使用量最终达到超过1GB的峰值。如果问题存在,我需要找到一些方法来更正我的代

  3. ruby-on-rails - 在混合/模块中覆盖模型的属性访问器 - 2

    我有一个包含模块的模型。我想在模块中覆盖模型的访问器方法。例如:classBlah这显然行不通。有什么想法可以实现吗? 最佳答案 您的代码看起来是正确的。我们正在毫无困难地使用这个确切的模式。如果我没记错的话,Rails使用#method_missing作为属性setter,因此您的模块将优先,阻止ActiveRecord的setter。如果您正在使用ActiveSupport::Concern(参见thisblogpost),那么您的实例方法需要进入一个特殊的模块:classBlah

  4. ruby - 当使用::指定模块时,为什么 Ruby 不在更高范围内查找类? - 2

    我刚刚被困在这个问题上一段时间了。以这个基地为例:moduleTopclassTestendmoduleFooendend稍后,我可以通过这样做在Foo中定义扩展Test的类:moduleTopmoduleFooclassSomeTest但是,如果我尝试通过使用::指定模块来最小化缩进:moduleTop::FooclassFailure这失败了:NameError:uninitializedconstantTop::Foo::Test这是一个错误,还是仅仅是Ruby解析变量名的方式的逻辑结果? 最佳答案 Isthisabug,or

  5. ruby - 获取模块中定义的所有常量的值 - 2

    我想获取模块中定义的所有常量的值:moduleLettersA='apple'.freezeB='boy'.freezeendconstants给了我常量的名字:Letters.constants(false)#=>[:A,:B]如何获取它们的值的数组,即["apple","boy"]? 最佳答案 为了做到这一点,请使用mapLetters.constants(false).map&Letters.method(:const_get)这将返回["a","b"]第二种方式:Letters.constants(false).map{|c

  6. ruby - 模块嵌套代码风格偏好 - 2

    我的假设是moduleAmoduleBendend和moduleA::Bend是一样的。我能够从thisblog找到解决方案,thisSOthread和andthisSOthread.为什么以及什么时候应该更喜欢紧凑语法A::B而不是另一个,因为它显然有一个缺点?我有一种直觉,它可能与性能有关,因为在更多命名空间中查找常量需要更多计算。但是我无法通过对普通类进行基准测试来验证这一点。 最佳答案 这两种写作方法经常被混淆。首先要说的是,据我所知,没有可衡量的性能差异。(在下面的书面示例中不断查找)最明显的区别,可能也是最著名的,是你的

  7. ruby-on-rails - 使用 config.threadsafe 时从 lib/加载模块/类的正确方法是什么!选项? - 2

    我一直致力于让我们的Rails2.3.8应用程序在JRuby下正确运行。一切正常,直到我启用config.threadsafe!以实现JRuby提供的并发性。这导致lib/中的模块和类不再自动加载。使用config.threadsafe!启用:$rubyscript/runner-eproduction'pSim::Sim200Provisioner'/Users/amchale/.rvm/gems/jruby-1.5.1@web-services/gems/activesupport-2.3.8/lib/active_support/dependencies.rb:105:in`co

  8. ruby-on-rails - Controller 中的 Rails 辅助模块 - 2

    我有一个Controller,我想为这个Controller创建一个助手,我可以在不包含它的情况下使用它。我尝试像这样创建一个与Controller同名的助手classCars::EnginesController我创建的助手是moduleCars::EnginesHelperdefcheck_fuellogger.debug("chekingfuel")endend我得到的错误是undefinedlocalvariableormethod`check_fuel'for#有没有我遗漏的约定? 最佳答案 如果你真的想在Controll

  9. ruby-on-rails - 具有同名的模块和类 - 2

    我有一个模块stat存在于目录结构中:lib/stat_creator/stat/在lib/stat_creator/stat.rb中,我在lib/stat_creator/stat/目录中有我需要的文件,以及:moduleStatCreatormoduleStatendend当我使用该模块时,我将这些类称为StatCreator::Stat::Foo.new现在我想要一个存在于应用程序中的根Stat类。我在app/models中制作了我的Stat类,并在routes.rb中进行了设置。但是,如果我转到Rails控制台并尝试在应用程序/模型中使用Stat类,例如:Stat.by_use

  10. ruby-on-rails - 使用 rspec 和 rails 测试嵌套模块 - 2

    这个问题在这里已经有了答案:关闭10年前。PossibleDuplicate:Testingmodulesinrspec目前我正在使用rspec成功测试我的模块,如下所示:require'spec_helper'moduleServicesmoduleAppServicedescribeAppServicedodescribe"authenticate"doit"shouldauthenticatetheuser"dopending"authenticatetheuser"endendendendend我的模块位于应用程序/服务/services.rb应用程序/服务/app_servi

随机推荐