最近制作的一个ESP32项目需要使用RTC,最先选中的是一个DS1307,经过实验发现有奇怪的问题:设定好时间之后经过一段时间会出现时间错乱的情况;无奈之下更换为 DS3231。
卖家关于这个模块介绍如下:
DS3231是低成本、高精度I2C实时时钟(RTC),具有集成的温补晶振(TCXO)和晶体。该器件包含电池输入端,断开主电源时仍可保持精确的计时。集成晶振提高了器件的长期精确度,并减少了生产线的元件数量。DS3231提供商用级和工业级温度范围,采用16引脚300mil的SO封装。
RTC保存秒、分、时、星期、日期、月和年信息。少于31天的月份,将自动调整月末的日期,包括闰年的修正。时钟的工作格式可以是24小时或带/AM/PM指示的12小时格式。提供两个可设置的日历闹钟和一个可设置的方波输出。地址与数据通过I2C双向总线串行传输。
精密的、经过温度补偿的电压基准和比较器电路用来监视VCC状态,检测电源故障,提供复位输出,并在必要时自动切换到备份电源。另外,/RST监视引脚可以作为产生μP复位的手动输入。
除计时精度高之外,DS3231还具有一些其它功能,这些功能扩展了系统主机的附加功能和选择范围。该器件内部集成了一个非常精确的数字温度传感器,可通过I2C*接口对其进行访问(如同时间一样)。这个温度传感器的精度为±3°C。片上控制电路可实现自动电源检测,并管理主电源和备用电源(即低压电池)之间的电源切换。如果主电源掉电,该器件仍可继续提供精确的计时和温度,性能不受影响。当主电源重新加电或电压值返回到容许范围内时,片上复位功能可用来重新启动系统微处理器。
模块参数:
1.尺寸:38mm(长)*22mm(宽)*14mm(高)
2.重量:8g
3.工作电压:3.3--5.5V
4.时钟芯片:高精度时钟芯片DS3231
5.时钟精度:0-40℃范围内,精度2ppm,年误差约1分钟
6.带2个日历闹钟
7.可编程方波输出
8.实时时钟产生秒、分、时、星期、日期、月和年计时,并提供有效期到2100年的闰年补偿
9.芯片内部自带温度传感器,精度为±3℃
10.存储芯片:AT24C32(存储容量32K)
11.IIC总线接口,最高传输速度400KHz(工作电压为5V时)
12.可级联其它IIC设备,24C32地址可通过短路A0/A1/A2修改,默认地址为0x57
13.带CR2032电池,保证系统断电后,时钟任然正常走动
14.包装方式:单个防静电包装
接线说明(以Arduino uno r3为例):
SCL→A5
SDA→A4
VCC→5V
GND→GND
从网上看这个比前面那个口碑好很多,但是惊奇的发现经过一段时间运行同样会出现问题。典型问题如下,可以看到前一个时间尚且正常,随后就变成了 2165/165/165 165:165:85 这样的错误时间。
58:2d:34:3a:81:cf,2021/8/26 20:0:48,74.9,31.8
58:2d:34:3a:81:cf,2021/8/26 20:0:50,74.9,31.8
58:2d:34:3a:e6:d1,2021/8/26 20:0:51,77.1,31.8
58:2d:34:3a:e6:d1,2165/165/165 165:165:85,76.3,31.7
58:2d:34:3a:81:cf,2021/8/45 78:79:41,74.8,31.8
58:2d:34:3a:e6:d1,2021/8/45 78:79:41,75.7,31.7
58:2d:34:3a:81:cf,2021/8/45 78:79:41,74.8,31.7
58:2d:34:3a:81:cf,2021/8/45 78:79:43,74.8,31.8
58:2d:34:3a:81:cf,2021/8/45 78:79:45,74.8,31.8
连续试验了2个库都有同样的问题。想来应该不是软件的问题。另外,可以观察到出现错误之后 RTC 仍然会按照错误的时间继续输出,这个说明芯片仍然在工作。最终,我将目光投向了模块本身。前面提到过DS1307电池的问题,这次仍然从这里下手。在工作状态下,首先测量了一下电池电压,在3.3V 说明是电力充足的;之后,拆下来电池再次测量电池位(具体可以从正面下面的位置测量到)。惊奇的发现电压是 4.2V 左右。再接上电池之后发现这个位置虽然是 3.3V 左右,但是以每秒0.01v的速度在升高。经过一段时间的观察发现它能升高到 3.48V,仍然在不停的升高。这个看起来是模块在试图对电池充电。
在英文网站上搜索发现,有人指出这个模块必须使用可充电纽扣电池:LIR2032,而这种电池的电压是 3.6v。我购买的模块也确实带有了一个这个型号的电池,但是目前已经鼓包了。查看模块的电路如下:
可以看到上面的 VCC 经过 R5 和一个二极管直接给电池供电,这样的话,如果使用3.3V对模块供电,那么出现在电池上的电压是3.3-0.7=2.6V 左右(电池低于2.6V时可以进行充电);但是如果使用5V 对模块供电的话,出现在电池上的压降将会时 5-0.7=4.3V 左右,这个电压远超过电池的最高电压。这就是为什么我看到电池两端电压缓慢上升的原因,也许是原配电池鼓包的原因。
确定这一点后,去掉下面 R5 处的电阻即可断开充电电路:
但是,测试结果仍然会出现错误。但是,如果硬件上有一个问题,那么很可能还有其他的问题。从上面的信息来看,问题发生很可能和 IIC 有关系。从 DS3231 上看过去 IIC 被拉到了 VCC 上。但是,我们的 VCC 是 5V。换句话说,这里出现在 IIC 上的是5V,而ESP32端是 3.3V 的引脚。因此,这里会出现电平不匹配的问题(5V供电的设备可以将 3.3V判定为1, 但是3.3V供电的设备无法正确判断5V信号)。
最终的解决方法是:使用 3.3V 作为RTC模块的供电。当然,如果使用3.3V进行供电的话,前面的 rework 也不是必须的动作了。
总结:这个模块的卖家说明是错误的,如果你使用GPIO 是 3.3V的单片机/SOC 作为主控,那么必须使用3.3V对DS3231模块供电才能保证工作。