『1』软硬件环境
本文适用于:
Raspberry Pi:Model B/B+(已测),其他型号理论上也可以,只不过可能要修改一下后面说到的shell脚本中的端口号
OS:Arch Linux ARM
『2』实时时钟与树莓派的关系
树莓派为了节约成本以及减小体积,没有板载的实时时钟(real-time clock,RTC),或者叫硬件时钟,因此,如果你没有配置过树莓派自动从网络同步时间的话,或者就算你配置好了自动从网络同步时间、但没有网络可用的话,那么,你设置好的系统时间,在重启树莓派之后就会丢失。而我们家用的电脑之所以在开机之后时间仍然正确,是因为电脑主板上有实时时钟。
因此,在某些场合下,如果树莓派无法联网,但是它上面运行的程序又和时间紧密相关,要求系统时间是正确的,在这种情况下,我们就可以为树莓派添加一个外部的RTC,使之重启之后也能保持时间正确。
其原理是:
先将树莓派的系统时间通过网络对时,使系统时间正确
首次使用RTC时,将系统时间写入RTC
树莓派断网重启时,通过一个开机自动启动的程序,从RTC中读取出里面存储的时间,写回到树莓派的系统中
『3』实时时钟型号及硬件接线方法
(1)RTC概述
我使用的RTC是成本低廉、市场上遍地都是的DS1302模块,淘宝价一般是5元左右。之所以用DS1302最重要的原因不是因为它便宜,而是WiringPi已经自带了DS1302的驱动程序,稍微修改一下就可以用起来了。
DS1302模块自带一块CR2032纽扣电池,电池使用时间至少应该有1年以上。先来个特写:
VCC:接树莓派的 3.3V 输出
GND:接树莓派的 Ground(地)
CLK:接树莓派的 SCLK
DAT:接树莓派的 SDA0
RST:接树莓派的 CE0
这里有一个巨大的陷阱:网上某些文章只告诉你要按照上面的方法连接RTC和树莓派,却没有告诉你一个非常关键的事情:在RTC的VCC和DAT两个针脚之间还要接一个上拉电阻!如果没有这个上拉电阻的话,你会发现用程序从RTC读出的时间非常不稳定,各种错乱。
我们知道,上拉电阻一般是指一端接电源,一端接芯片管脚的电阻,其作用是防止输入端的“floating”(浮动)状态,使电平可被稳定检测。
在这里,上拉电阻可以用10K~30K的,我试了10K和20K的,RTC都可以稳定运行。
下图简单地展示了应该怎么接这个上拉电阻:
另外需要提醒大家的是,尽管商家提供的这款DS1302模块的说明里写着VCC可以接5V,但是我劝大家不要这样玩,我亲测“毁”了一次树莓派(Model B+)——
VCC接5V的时候,我试验过,在Model B+上不接上拉电阻也可以 rtest 成功(Model B则不行),并且可以将系统时间正确写入RTC,并且还可以从RTC读出正确的时间,但是一旦你尝试把RTC中的时间写入系统时间,树莓派马上挂掉,任何命令都无法再执行,提示 bash: /usr/bin/ls: Input/output error。我觉得这不是偶然现象,而是可以复现的,只不过我不想再“毁”一次树莓派了。
所以,大家务必要把VCC接3.3V,并且接10K的上拉电阻。
(3)整体硬件接线图
下面展示一下RTC+树莓派的整体硬件接线电路图,先是Model B+的:
再是Model B的:
『4』实时时钟控制软件使用说明
在接好了线之后,我们就要修改一下WiringPi自带的DS1302驱动程序来符合我们的要求了,文件位置在 WiringPi 安装包的 examples/ds1302.c,代码内容挺多,不需要仔细研究。如果你连看都不想看,那么可以直接使用我修改过的版本:https://github.com/codelast/raspberry-pi/tree/master/real-time-clock
使用方法举例:
./ds1302.sh:打印出 DS1302 模块中存储的时间
./ds1302.sh rtest:测试 DS1302 模块是否工作正常
./ds1302.sh sdsc:将Linux系统时间写入 DS1302 模块中
./ds1302.sh slc:将 DS1302 模块中的时间写入Linux系统
./ds1302.sh slc b:与上面命令效果相同,但只适用于树莓派model B(如果不提供第2个参数的话默认是model B+)
ds1302.sh脚本的作用就是编译ds1302.c并运行它。由于Model B和B+的某些WiringPi端口号不同,因此,ds1302.sh中根据不同的树莓派型号,分别设置了不同的端口号,并传给DS1302程序。
写本文的时候,我手上只有B和B+,所以无法对其他的型号进行测试,如果你要支持其他的型号,对ds1302.sh稍加修改即可。
ds1302.sh脚本中定义了三个变量:
SCLK_PORT
SDA0_PORT
CE0_PORT
它们指的是WiringPi编号方式下,树莓派的SCLK、SDA0、CE0这三个针脚对应的GPIO端口号(GPIO端口分布图请参考这里)。RTC上的CLK、DTA、RST三个针脚分别与这这三者一一对应。
其中,SCLK、CE0的WiringPi端口号对树莓派Model B和B+都是相同的,分别是14和10,但SDA0不同(Model B为8,B+为30)。
『5』实时时钟控制软件部分代码解析
由于这一部分含有比较多的代码,而在手机上看代码排版较乱,很费劲,所以这一部分就不写了,各位看官可以点击下面的“阅读原文”跳转到我的网站进行阅读。
文章来源:http://www.codelast.com/
『6』配置树莓派的系统
在使用RTC的程序之前,首先要配置树莓派系统的时区,否则RTC将无法正常使用。
编辑 /etc/rc.conf 文件,添加如下内容:
LOCALE="en_US.UTF-8"
DAEMON_LOCALE="no"
HARDWARECLOCK="localtime"
TIMEZONE="Asia/Shanghai"
然后:
ln -sf /usr/share/zoneinfo/Asia/Shanghai /etc/localtime
并网络同步一次系统时间(我配置了自动同步服务,在此不详述)。
文章来源:http://www.codelast.com/
『7』测试
软硬件都就绪的情况下,就要对RTC进行测试了。运行如下命令:
./ds1302.sh rtest
如果接线接错了,会打印出一堆类似于下面这样的信息:
DS1302 RAM TEST
DS1302 RAM Failure: Address: 0, Expected: 0x00, Got: 0xFF
DS1302 RAM Failure: Address: 1, Expected: 0x00, Got: 0xFF
DS1302 RAM Failure: Address: 2, Expected: 0x00, Got: 0xFF
...
DS1302 RAM Failure: Address: 28, Expected: 0x1C, Got: 0xFF
DS1302 RAM Failure: Address: 29, Expected: 0x1D, Got: 0xFF
DS1302 RAM Failure: Address: 30, Expected: 0x1E, Got: 0xFF
-- DS1302 RAM TEST FAILURE. 465 errors.
注意,前面说了必须要接一个上拉电阻,如果你没有接,也会报错。
如果一切正常,程序会提示“DS1302 RAM TEST: OK”。
文章来源:http://www.codelast.com/
然后将系统时间写入RTC:
./ds1302.sh sdsc
输出类似于:
Setting the clock in the DS1302 from Linux time [15-11-8 13:40:9]...OK
再从RTC中读取出其存储的时间,看是否正确:
./ds1302.sh
输出类似于:
0: 13:41:34 8/11/2015
1: 13:41:34 8/11/2015
2: 13:41:34 8/11/2015
3: 13:41:35 8/11/2015
4: 13:41:35 8/11/2015
5: 13:41:35 8/11/2015
6: 13:41:35 8/11/2015
7: 13:41:35 8/11/2015
8: 13:41:36 8/11/2015
最后测试一下将RTC中的时间写入树莓派的系统:
./ds1302.sh slc
输出类似于:
Setting the Linux Clock from the DS1302... Sun Nov 8 13:43:03 CST 2015
再看看系统时间是否正确:
date
搞定。
『8』开机启动
在上面的测试一切正常的情况下,只需要让系统启动时执行 ./ds1302.sh slc 命令,即可在树莓派断网的情况下也能保持正确走时了。