RTC(real time clock)实时时钟,在电脑、手机等电子产品中都有,应用较多。它的主要作用就是,在产品断电之后,时间还可以继续走数。这样我们在重新使用电子产品时,时间仍然正确。芯片本身可以通过纽扣电池供电,接下来我们一起学习一下RTC的驱动。
在官方文档中,给出了以下重要特点描述:
( Z; j; Q+ L" Q8 P1、实时时钟系统可以计数时、分、秒、日、月、星期、区分闰年平年的年份等,最多支持2100年。
2、有31*8bit的存储容量的RAM。
3、实时时钟系统或者RAM的读写,可以单字节或者多字节(突发模式)进行数据传输。
在芯片计时过程中,可以准确的计出时分秒等,还有每个月各有多少天。有30、31、28、29天的区分,年份有闰年平年的区分。小时有12小时制和24小时制。有AM和PM的区分。
芯片的控制是通过CE、I/O(data line)和SCLK。数据线可以一次传输1字节或者31字节。
- h; x, q8 R" W1 y
二、端口
" o4 [/ b* k1 ~( Z, K9 P3 |
( D7 l! O% X/ _8 y
7 s3 p' M& @& {+ q- O
- m2 _/ a4 w: z: U) W
图中的mcu在此时是指的我们的FPGA,那么,FPGA与芯片进行数据交互时,是通过三个串行线进行的,并且I/O为双端口类型。芯片的端口中,除了三个主控端口(CE、I/O、SCLK)外,还有X1和X2。
这两个端口为晶振接口,芯片需要一个外挂晶振来提供时钟,以便用来计时。VCC1和VCC2为两路电源,其中VCC2为板卡提供的电源,VCC1为纽扣电池供电。供电关系会在下面的管脚说明里面进行讲解。
GND为电源地。
6 K! b+ @) I+ c# R8 y5 \
B4 s" v+ m4 i, _
三、管脚说明
( a- C0 v `4 C& ]1 C7 ?
" f/ Y+ u4 _: |, {$ g( W' g
4 F+ E$ e5 d% H6 a
9 a0 M* s7 F4 P) `6 K
四、命令格式
\1 d3 J% L9 T2 E: @ t
2 e9 I* b6 N3 M( G! Q下图展示了命令字节,一个命令字节由数据的发送者决定。最高位必须为1,如果是0,将禁止向芯片写数据。bit6如果是0将与实时时钟系统通信,如果是1将与RAM通信。bit1到bit5为寄存器地址;bit0如果为0为写操作,1为读操作。
% Y6 R4 t, I- z Q4 V7 `- E t0 Q: }( D3 k9 j) p" D
) `: f) a7 A' t$ b( l' r! W+ q* ]4 c
7 Q$ N5 d) [9 B9 x# ]' L3 w: R2 N
/ C2 ~1 J3 O. n: k
5 M/ T$ u9 m6 m/ X
0 Y" n( s# a; y- t0 j2 a" K: L, J; \, m. B5 N- d+ E2 E
! J4 d7 v; w, o; O' y- ~$ h$ a五、读写控制
0 @8 w& Z6 Y* i% l5 h' B2 c' U8 Q! [! R- N4 E; O9 {1 ^/ J* g
+ u; y5 O9 H9 E; T0 `4 h. P) z
( B% u$ W4 b' V7 A5 w0 B: V首先是写操作,在8个SCLK时钟周期内,主机发送一个写命令字节,数据输入在接下来的8个SCLK时钟的上升沿,数据开始为bit0,也就是说,数据在发送时,从低位开始发送。
3 Z L. r7 C8 [5 Y0 i
数据读操作,在8个SCLK时钟周期内,主机发送一个读命令,数据输出在接下来的8个SCLK时钟下降沿。第一个数据bit出现在命令字节最后一个bit被写入之后的第一个下降沿。通常数据传输需要在CE为高时。读数据时,也是从低位开始。
' W6 i) R0 q) q/ p% u4 @7 C: E- f5 Y( y E0 ?6 q: y- R- {$ R
六、接口协议
% P! d# h$ f$ _
基于芯片的读写方式,我们可以使用SPI协议进行数据读写,那么接下来我们介绍一下SPI协议。
SPI协议有四种模式,如下图:
. I# e/ u% e, x4 s& i* D$ F( w
0 F8 E" c% Q% ?/ h2 P9 y/ u+ `2 `
4 B7 {# P( A; ~+ j- \' g6 H, jSPI的四种模式是按照其时钟极性(CPOL)和时钟相位(CPHA)共同决定的,CPOL=0,即SCLK=0,表示SCLK时钟信号线在空闲状态时的电平为低电平,因此有效状态为高电平。CPHA=0,即表示在时钟的第一个岩信号进行采样。CPOL和CPHA共有四种组合,固有四种通信模式。
, P; w8 L. K5 _1 jSPI为主从模式,在通信线上,需要4通信线:
CS – 从设备使能信号,由主设备控制
SCL – 时钟信号,由主设备产生
MISO – 主设备数据输入,从设备数据输出
MOSI – 主设备数据输出,从设备数据输入
但是,一般为了节省资源,会使用3跟通信线,分别为CE、SCL、SDA。其中SDA为双端口。数据的输出和输入都使用这条线。
在我们的DS1302时序图中,读写时序跟SPI的第一种模式一样,所以我们在写代码的时候可以使用SPI协议去写。
; F) j% N/ B$ H
接下来我们开始新建工程写代码。
; ?/ u+ t3 d7 {3 w8 y
/ x( H: y% y2 k' m8 j; g
, I6 r0 _, h0 M0 H. O; M
; I9 h% b7 v# ~2 y; z
. T; @) _/ c5 g9 @& l/ l1 K! J) q
: Y. |3 G. K( p$ | ?
; `" Y- c1 v" r3 S J
\- F2 c8 N* M+ x! F7 q新建文件,按照写时序,通过线性序列机写出写模块。
2 H8 \5 S2 N3 X3 N6 u
; x, [+ [. Y$ q* x% u v" I$ A' H1 z" D% D2 f: Z. o
* S7 e b; z7 a
r3 m+ [ i F$ w
- t# `% _* J% } O: F$ j
0 u$ n1 O) {9 c# d7 L: \1 h& ?
代码如下:
6 e& ~+ D1 o8 i) k
) i+ _5 Z. Y) I4 m. L/ s: y5 |2 z+ W- s
同样的方式,新建文件读模块以及控制模块,代码如下:
) M" z, K2 x/ g! ^2 t# K( O$ B: P( q* y, |" n
; _; ]5 q/ \/ l/ o* E. v, O$ G2 L$ G1 E( u6 V8 x
在读写模块中,按照框架设计,计数器必须在使能有效的条件下进行,所以,在写计数器时,必须判断使能信号。
! G: n3 A2 F4 ^
控制模块如下:
* d% Q" _! a. ~8 I) G
% G1 E/ a9 R) Y2 t4 G! x$ ^" T
; U& N; A# ?0 w) E) C7 j4 u' q7 D& W9 k8 ]2 E( x& A$ `- v5 H& v! {
. p: u* n o/ `' m" R- [
在控制模块中,我们前三个状态要把时间的初值写进芯片,比如我们写入时分秒,那么我们需要按照手册给出相应的命令。
~( o- N+ T S$ f
4 y: v% ?+ N7 v
2 g1 P% M# v3 r/ z. o& e" o5 R在这里我们需要解释一下小时的数据格式。BIT7如果为0代表使用的是24小时制,如果为1代表使用的是12小时制。BIT6恒为0。BIT5,如果是12小时制,0代表上午,1代表下午,如果是24小时制,BIT5和BIT4共同组成了小时的十位。BIT3到BIT0为小时的个位。
5 s9 ~4 S8 a- W2 P- B; B顶层模块代码如下:
( b- w: {( I' c7 Y5 V8 T& s2 x
) `- V, @& I) x+ ~$ L8 y9 M% E7 L9 ^
在这里需要大家注意的是三态门的编写。
" m3 [" ?4 e& {+ g0 L: |
$ y& B! r7 }# D! g, P6 z; U
' i& y3 P: `) Q9 C/ [+ ~作为输入时,将数据线置为高祖态。
. [! t6 r/ o$ z; Y
仿真代码如下:
. l' j" Z0 L; X
; M7 l& \4 X/ n$ l: f
- Z v" ?8 D) d. z8 A仿真图如下:
" Q3 @' a1 L: W5 @( N7 M2 }/ q& e$ g8 R# c9 q5 S3 G
# [* B4 K3 @; U7 x% `( C m0 [9 O+ a
4 ^4 K- i4 K' H! G
前三个状态,分别写入了时分秒等数据,3 4 5三个状态分别是读时分秒的状态,最后一个状态是做的延时,在一秒时间内,读出的数据是没有变化的,因此我们可以减少读操作的频率来降低工作频率。在rd_done信号拉高时,可以看到时分秒都有数据被赋值,及读出正常。