[新人试水] LPC1768 Nano3_9 添加RTC

发表在 RTC2018-3-28 23:16 [复制链接] 3 1592

本帖最后由 wlof 于 2018-3-28 23:16 编辑
$ A: V6 H. H: k1 l2 _
0 A+ Q5 P3 V0 L! E' i7 ?第九章 添加RTC
Wlof
摘要:本文首先介绍如何将RTC组件添加到RTT_Nano3上使用,针对在MDK下无法正常使用mktime的问题,重写了mktime函数,也是抄过来的。

3 Z* b7 C0 H( X, Q6 [9.1 起源- a# l* c1 X9 V! l
之前SD卡上我们为了写入时间,将gettime这个函数进行了替换,主要还是那个time函数没有去弄它,为了尽可能少地修改提供的代码,这里使用了RTC组件进行操作,实现time函数。在调试过程中发现,mktime这个函数不对,不知道怎么回事,为此在网上找了一些文章,正在好发现有个linux下的源码,直接改写过来。至于那个自带的函数为什么会有问题,俺也不清楚,网上很多人说可以用,但我实际测试就是不能用呢。

0 T; X9 Y3 b* C: v. T5 y$ o# w9.2 复制文件
) r) d+ r' B7 M" T& T
位于rt-thread-master\components\drivers\rtc,全部搞过来也行,这里只用以了rtc.c,对应的头文件也复制过来,在rt-thread-master\components\drivers\include\drivers里面。
然后找个参考复制文件,我这里参考了STM32F429的,把文件drv_rtc.c 和.h复制过来。
这4个文件,统一放到一个目录下,添加到工程,添加include到包含目录。

8 @2 c5 p7 e/ v/ U( b; e- [9.3 修改drv_rtc.c9.3.1 头文件
3 n( I$ w% i( }! y2 A, x) }
去除drv_rtc.c #include "board.h",添加#include "LPC17xx.h"。

) _+ Q9 {2 r# [* a/ ?6 T  ]9.3.2 删除函数
" ~3 s# _# I$ p0 O
保留rt开头的函数,保留RTC_Init,SetRTCTimeStamp,GetRTCTimeStamp函数,其的函数全部干掉。
然后清空RTC_Init,SetRTCTimeStamp,GetRTCTimeStamp这3个函数的内容,因为我们要添加到LPC1768上来。所有的驱动代码要用LPC1768上的代码,周立功网上可以下载到参考代码。

% R. k  P  z8 d; L9.3.3 添加函数
. X' @& J1 V  g9 H: R; ]# `* F
然后把周立功里面的代码复制过来,先不管它用不用,先搞去再说,那个初始化,放到RTC_Init里去,时间读取和设置函数先不要。

4 z% ~/ p+ k$ v% \4 P4 k% ?1 z! C
  1. void RTC_IRQHandler (void)
    ) U& G0 s$ ]- a, u! J9 s8 \+ s+ z
  2. {
    9 U0 R' B! `9 e5 G6 ]8 Z
  3.   LPC_RTC->ILR |= ILR_RTCCIF;      /* clear interrupt flag */9 ~6 S( L% P  M* T8 q0 Q7 O( t
  4.   return;
    + c# D5 q- e) e+ B! J& W: W
  5. }* _1 E- d. y8 S2 I4 G1 E3 K  E
  6. - p# T) b. f, Z
  7. void RTC_Init(void)
    2 n+ n! e# B# k% [. }4 @  S
  8. {- T9 q) a, |  e" }$ U
  9.     uint32_t calibration_register = 0;
    ! x6 x9 x& }3 V3 l, y4 l  W) \4 V
  10.      R0 Y5 X# D1 d# i3 L
  11.     /* Disable RTC Clock, Reset Clock, Disable Calibration */& ?' }8 W7 C! r# L& C6 }# e
  12.     LPC_RTC->CCR  =   ( !CLKEN |  CTCRST );
    . W( J' H' y* K' @: f% E9 Q& R, p% L& ~7 W
  13.    
    , m5 @0 C* H4 d4 K, [, f
  14.     calibration_register = 32768000 / (32768000 - 327630000);   //4min + 1s
    / ~1 u- U0 X+ X
  15. " j% ^  F1 B: e8 [7 s
  16.     /* CALDIR */
    4 q) [  z- N" h) Y7 [9 N7 e5 d; ^
  17.     calibration_register &= ~CALDIR(0);   
    2 P/ E& K$ C- d/ M4 x  `2 A3 ]
  18.     /* Enable calibration */
    - K5 F+ o! I8 \4 Y
  19.     LPC_RTC->CCR &= ~CCALEN;     S. p* _2 I# t# T/ a- t
  20.     /* Save new calibration register value */
    % n! H$ q5 O2 m& J! T) g! y$ f
  21.     LPC_RTC->CALIBRATION = calibration_register;
    ) `! b! l: a% [$ P6 S: G3 x4 q8 S
  22. ( S) o: G! n) f# N1 A
  23.     /* Disable Clock Reset */  3 {! W3 Y2 e" g9 [" U
  24.     LPC_RTC->CCR &= ~CTCRST;( I- f$ e* k& s1 s  z: U' ]
  25. //==================================//
    + g' m* c1 ?$ f5 E! A; W4 a
  26. ) D( \3 T- B4 o$ B2 s
  27.     /* Enable CLOCK into RTC */: [% _6 v, U6 \% K+ F  |
  28.     LPC_SC->PCONP |= (1 << 9);. W% ^# P9 \9 V' O: v2 B- a" R  b
  29. & r% o( d$ Q3 k; t& Y1 `( u
  30.     /* If RTC is stopped, clear STOP bit. */
    3 Y" l! B! b) ~/ p
  31.     if ( LPC_RTC->RTC_AUX & (0x1 << 4) )
      {! A6 X1 d/ \* x7 ]
  32.     {* s" a- x% J4 o6 K  p7 @3 V
  33.        LPC_RTC->RTC_AUX |= (0x1 << 4);4 x, B- o& u; p( X" L+ ]9 v) p
  34.     }
    , Z) ^- `. X$ b- u( R
  35. . v, f* Q  g* e" r: a
  36.     /*--- Initialize registers ---*/
    0 v) o, |( j8 ^+ K
  37.     LPC_RTC->AMR = 0;           //Alarm Mask Register
    7 X5 U& }% f) S$ c
  38.     LPC_RTC->CIIR = 0;          //Counter Increment Interrupt Register) y, f  ~8 |3 A& s# L& d) A  g
  39.     LPC_RTC->CCR = 0;           //Clock Control Register4 u, T& k- g6 ]+ z) J
  40. }3 O( \) k8 U& y! V& P8 {
  41. % E2 N% a+ t3 s( P$ `3 `
  42. void RTCStart( void )7 \6 u1 c8 e( R# H
  43. {2 [2 f  q: R* x7 B' I
  44.     /*--- Start RTC counters ---*/
    5 ^- z2 w" P7 Q0 S/ j  U2 ^
  45.     LPC_RTC->CCR |= CCR_CLKEN;
    6 C* U. l% X- b" O; K! |% Q7 ]) }3 H
  46.     LPC_RTC->ILR = ILR_RTCCIF;
    5 {; W& |& y4 Z' j. c
  47.     return;4 z% w: Z, }0 |9 g/ N) ]/ N
  48. }
    1 x( @' X3 X) O# E

  49. 2 J7 a$ f: `( r7 H& N) h
  50. void RTCStop( void )
    : w" s) `2 _4 f- ]: I9 [& `/ p( J
  51. {
    & e2 d* w- U: l* n+ d
  52.     /*--- Stop RTC counters ---*/
    : S- T5 j0 O' Q+ ?
  53.     LPC_RTC->CCR &= ~CCR_CLKEN;
    1 e( d( }- t3 M0 b1 i
  54.     return;
    7 X* W9 O7 ~+ t- t; ?
  55. }
    1 W+ A& V% D4 b. n0 y
  56. 1 H" J. K4 ^* ^; o; |* O
  57. void RTC_CTCReset( void )# h& r8 ]; {' }8 t
  58. {
    ! L2 p8 E9 T! v, p5 R7 d
  59.     /*--- Reset CTC ---*/$ a7 C6 @: w* S. V+ [& b
  60.     LPC_RTC->CCR |= CCR_CTCRST;4 M. L' `3 z& l% Q; V
  61.     return;
    6 [7 k1 a) }+ B6 }) Y9 N0 m; J
  62. }. \2 s* g+ w: H- N# c/ ^; Q

  63. $ U$ O* L; r( o( M7 b. h8 j
  64. void RTCSetAlarmMask( uint32_t AlarmMask )* E3 }0 b  f% |" t* N$ a( e1 g
  65. {. z, F+ f: K% G; L
  66.     /*--- Set alarm mask ---*/" J! [! P2 s9 s( Z- C/ o% k
  67.     LPC_RTC->AMR = AlarmMask;
    4 p) T8 Z% f) h; ^' ^: s" j
  68.     return;' i5 z# W4 `7 I* H( g/ T& N( a! q8 w
  69. }
复制代码
' \( y$ f* A( A) f7 Y9 A' k8 z

# W0 a! b& D7 f0 {& |9.3.4 修改读写时间函数1 ?, X' K& f3 }4 S# S: v$ N$ M
, k5 P2 ?2 G8 N9 N, Z, m' x
  1. time_tGetRTCTimeStamp(void)" l/ R: T5 v4 d7 U/ s' g" ]/ Y
  2. {
    1 _2 r& w0 I* l6 ]/ {$ G
  3.     struct tm tm_new = {0};6 Q: @  T, F  t; @
  4.     time_t cur_time = 0;' ^" I; j% F: b2 f+ v: s
  5.     tm_new.tm_sec  = LPC_RTC->SEC;
    3 ]0 c3 R# w# f7 @) ]) z8 T+ }7 V
  6.     tm_new.tm_min  = LPC_RTC->MIN;
    ' X7 V# V6 T3 j3 Z
  7.     tm_new.tm_hour = LPC_RTC->HOUR;+ M  S' W  x4 Q3 ^( R! f
  8.     tm_new.tm_mday = LPC_RTC->DOM;
    # {* S6 C$ `+ O* k7 }9 H- T
  9.     tm_new.tm_mon  = LPC_RTC->MONTH;
    , ^# ^; W! W/ a
  10.     tm_new.tm_year = LPC_RTC->YEAR;
    8 p  u# q2 ]' ^5 }
  11.     cur_time = mktime(&tm_new);
    8 y. @/ \3 O- [6 g- `$ h3 q
  12.     return cur_time;//mktime(&tm_new);, Y( F; x+ C* Q' G& `
  13. }. v- i2 Z; E+ j& @' V
  14. rt_err_t SetRTCTimeStamp(time_t time_stamp)
    8 n! h' O/ ~, d
  15. {" T* V$ k& o# m& I
  16.     struct tm *p_tm;
    . P( M" F0 L+ l1 x+ q
  17.     p_tm = localtime(&time_stamp);
    ) R7 b. m! n' p9 d$ H" N
  18.     if(p_tm->tm_year < 100): K/ G- ^% G; K/ {3 j7 O% A6 Y* }
  19.     {
      L! k6 y) [& S  S) K$ ^- w
  20.        return RT_ERROR;' k. I. F4 F2 d+ j, b6 ~! @
  21.     }# b9 J  ^9 Q( y0 q
  22.     LPC_RTC->SEC  = p_tm->tm_sec;' ?1 A# z5 O7 h# s
  23.     LPC_RTC->MIN  = p_tm->tm_min;
      D3 v+ M6 `' r/ x, L$ q
  24.     LPC_RTC->HOUR = p_tm->tm_hour;
    : `: H; G1 a& S! W0 X0 j
  25.     LPC_RTC->DOW  = p_tm->tm_wday+1;
    % F  F( J3 z+ \# Y! F' d3 E7 c
  26.     LPC_RTC->DOM  = p_tm->tm_mday;
    ( a% Y, ?/ I, ]/ I3 A
  27.     LPC_RTC->MONTH = p_tm->tm_mon+1;8 q: v' M( x# R$ i; U7 }
  28.     LPC_RTC->YEAR = p_tm->tm_year-100;
    5 ]/ g! o$ |1 f9 I8 I
  29.     return RT_EOK;( R* g7 p: t* R1 d4 I. \7 M
  30. }
复制代码
' p  q/ f/ }/ A/ F7 d. y! [6 z* ]& k
1 ^# K* p: t' K& o
这里都是按原来的那个文件进行改写的,应改不会出太大的问题。
( g8 |/ a; I) J( y$ {6 g
9.3.5 修改初始化函数
  1. int  rt_hw_rtc_init(void)
    ! C% `' [2 ?; ?) L" l
  2. {
    " q' z- q6 @& {# o/ A  f
  3.     RTC_Init();
    $ M; u% L0 T+ \& N( |$ A) g0 n
  4.   NVIC_EnableIRQ(RTC_IRQn);
    - V- F# G1 F: {$ K( P* w& J& W! A
  5.   RTCSetAlarmMask(AMRSEC | AMRMIN | AMRHOUR | AMRDOM | AMRDOW | AMRDOY | AMRMON | AMRYEAR);/ T+ m8 C0 }; k2 H
  6.   LPC_RTC->CIIR = IMMIN | IMYEAR;) f0 c/ c9 J7 F! {/ `" m2 @
  7.     RTCStart();
    " D$ }. f* ^) Y* ?$ t8 V
  8.     /* register rtc device */
    9 r8 I/ P: @# `5 S( _1 z# S6 u
  9.     rt_hw_rtc_register(&rtc, RT_RTC_NAME, 0);) ?) I' |& Q' u5 ~2 w6 p
  10.     return RT_EOK;
    5 [( a: |, O) m0 y
  11. }- M' I. B) B, t
  12. INIT_BOARD_EXPORT(rt_hw_rtc_init);
复制代码
& g) ]% E& v: O% l$ p- U3 Y1 \
2 O; o' V/ H% Z4 X3 K8 `
这里发现一个好东东,以前没有注意,这个INIT_BOARD_EXPORT可以让系统自动执行初始化函数

, Z6 c' P; d/ m5 ]
  d4 x! v, K) Q, `! ?1 [# l% b9 n( w* @  z* E8 Q/ p
7 R" h/ x- v, [' D6 r. }; q  L/ g; G
9.4 dfs_elm.c的函数还原
9 r2 Y+ r, v( d
这里主要是因为在上一节中我们自己写了一个函数进行了替换,现在将它还原回去。如果没有看上节也没有关系,这里提到这个函数的主要目的就是对这个函数地进行测试,看一下最后结是不是我们想要的。
  1. DWORD get_fattime(void)
    " o* d1 T- p8 C9 E" l( u
  2. {! X% c2 m6 v; X
  3.     time_t now;
    % T2 J1 O3 m, g7 }$ G
  4.     struct tm *p_tm;! E. ?5 Y* Y; V! _, R
  5.     struct tm tm_now;
    & j. F$ P+ s. h% [" p) @/ `
  6.     DWORD fat_time;! X; N5 p3 \! t
  7.    
    8 a$ t9 J7 s, D3 h& x
  8.     /* get current time */2 x8 q, W* ~  g; C7 O- o- L
  9.     now = time(RT_NULL);
    + |. C- ], }1 N4 d- B& ^# S
  10.     /* lock scheduler. */
    ' z& x8 f# q' g( H
  11.     rt_enter_critical();/ C  `: R" ^3 F# H, W* b4 l5 e
  12.     /* converts calendar time time intolocal time. */* y6 Y' H' e# x
  13.     p_tm = localtime(&now);
    ; P: D, |6 g5 c" |+ W
  14.     /* copy the statically locatedvariable */
    / E; a2 X5 x+ c; I8 Q) j+ y
  15.     memcpy(&tm_now, p_tm, sizeof(struct tm));
    6 L& w' L' G" s$ M; z
  16.     /* unlock scheduler. */( ]$ m: o. ~& ^. V+ u9 M* p
  17.     rt_exit_critical();/ N2 k6 Q6 D" W' K$ G
  18.     fat_time =  (DWORD)(tm_now.tm_year - 80) << 25 |/ o' Q0 C- Q; N& I" Q) I
  19.                 (DWORD)(tm_now.tm_mon + 1)   << 21 |
    0 Z& B) L3 i( V" X
  20.                 (DWORD)tm_now.tm_mday        << 16 |1 \& ]6 [- v( F2 O5 N* ^: j+ M
  21.                 (DWORD)tm_now.tm_hour        << 11 |
    5 p/ t$ r/ b( D4 F" Z2 W
  22.                 (DWORD)tm_now.tm_min         << 5 |
    ! ~% c8 @, F7 Q7 y8 p- [( C( Q
  23.                 (DWORD)tm_now.tm_sec / 2 ;
    ; v4 T7 }  B; y' D: Y
  24.     return fat_time;- m3 A: t$ m, v+ E
  25. }
复制代码
* N: l  t, p$ J2 ?" y3 @. Q
. ^# d0 Z8 A  [' l$ v, `, e
9.5 编译测试: N' n  X# A; s! V/ |7 D( T! g
编译有错的话,记得把头文件的宏定义复制来过。编译没有错了,发现转换的时间死活就是不对。
我不知道别人有没有这事,反正我里那mktime这个函数就是不对,不仅不对还将传入的参数都改了!!!

6 T2 a1 c( x. L& V$ H- f
) U: r# i9 E* F. P8 v3 l- ]$ T
* J8 U- P% Z1 \9.6 mktime抄过来
4 x% a( s1 D+ p+ |* G
按理说,它应改可以正常工作的,但是这是为什么呢?不知道,我用的是MDK5.23。这个代码的原版本是从Linux中搞出来的,我按头文件的写法重新搞一下,其实就是得到utc时间。
  1. time_t mktime(struct tm * timeptr)
    : C- f4 |( r& r1 l$ A& ^
  2. {6 B0 N/ j7 F1 i+ n/ R) C
  3.   uint32_t y,m,d,h,n,s;+ I9 y; D4 h$ i
  4.   y = timeptr->tm_year;
    / O* U. Y' _4 ^# c6 r
  5.   m = timeptr->tm_mon;
    " y+ I! I" R4 K9 m3 C5 v
  6.   d = timeptr->tm_mday;
    * ^& |% U$ W3 e, t- ?
  7.   h = timeptr->tm_hour;6 k1 R$ i3 y( ^9 u
  8.   n = timeptr->tm_min;
    8 `; Z6 L5 t) r1 t! H
  9.   s = timeptr->tm_sec;
    ) b" ?' L3 Y' d7 {1 |
  10.   if(0 >= (int) (m -= 2)){//1...12 --> 11,12,1...10
    ' {& Q) s0 X1 k  B
  11.     m += 12;
      `* J( J) n7 H
  12.     y -= 1;
    5 J& D1 W/ t# b$ ]7 {
  13.   }
    + o+ {. |4 S/ s& L
  14.   return (((
    2 M) x- |# S! X; Q
  15.               (time_t)(y/4 - y/100 + y/400 + 367*m/12 +d) +
    - c- B' q9 X: T2 }- s* o
  16.               y*365 - 719499: \8 b. @; j: T& f, U8 h/ h' c
  17.             )*24 + h
    : ]) I% ^/ I- p1 ~
  18.           )*60 + n
    2 B9 x9 [* J3 i4 I2 w
  19.          )*60 + s;
    ' G% w4 C/ D: a6 o
  20. }
复制代码
! b0 H6 S+ _+ z0 T+ F1 p$ X

: a; Z+ H; G8 D' g5 f0 k, Y# T( R* u8 i$ {0 N
9.7 测试
   
  1. {/ x% \4 ?, ~& p3 _$ S
  2.       time_t x = 0;       //2017-10-16 14:21:4
    / |0 w) n) m" g  H# `% [! d
  3.       x = time(RT_NULL);//x=1508163664
    & V( Y# g5 ^  s1 I3 T
  4.       x = x;" |+ v  v# e2 q+ p, B
  5.       get_fattime();  //里面的tm_now 117-9-1614:22:52(加了断点抄数造成的延时)
    ( u3 `9 m/ H' k7 g5 o: L1 W3 d
  6.      rt_thread_delay(1);$ w$ E4 v* c8 c7 A0 {3 e% Q; {' A4 H, N
  7.      SetRTCTimeStamp(1508163664);//2017-10-16 14:21:42 L- u4 W( {2 ~
  8.     }
复制代码

/ x' H9 T: n% X+ @( q! V4 k% W
, b  ~7 O$ M+ p7 r( ~3 ?
值得一提的是,那个localtime这个函数,使用时要注意,它返回的是一个指针,应该是一个静态变量,只是值不一样而已,调用一次用一次,不然会悲剧,好像是传说中的不可重入函数。
1 y1 V: T3 \9 {+ m; S/ V3 `" K
3 n+ R$ E  w6 O: }: `. h
文档下载: RT_Nano_V3初级教程_9 添加RTC.pdf (235.89 KB, 下载次数: 0)
使用道具 举报 显示全部楼层 回复
最新评论 | 正序浏览
显示全部楼层 |楼层直达:
发表于 2018-3-29 17:04:14 | 显示全部楼层
造了 mktime ,可是测试里面好像没看到使用?
使用道具 举报 回复
发表于 2018-3-30 07:07:34 | 显示全部楼层
armink 发表于 2018-3-29 17:04& n" }4 p' s7 z* |" E# f: }' \
造了 mktime ,可是测试里面好像没看到使用?

  i' `) l; D  J那个函数被测代码中的函数调用,洲试代码中的函数在前面。
1 z3 l6 i+ W, @6 z- }
使用道具 举报 回复
发表于 2018-3-30 07:10:06 | 显示全部楼层
9.3.4中调用了它,那个time也调用了它
使用道具 举报 回复
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

Archiver|手机版|小黑屋|RT-Thread开发者社区 ( 沪ICP备13014002号-1

有害信息举报电话:021-31165890 手机:18930558079

© 2006-2019 上海睿赛德电子科技有限公司

Powered by RT-Thread

快速回复 返回顶部 返回列表