你的浏览器版本过低,可能导致网站不能正常访问!
为了你能正常使用网站功能,请使用这些浏览器。

发布基于ANSI-C的RTC_Time库,利用UNIX时间戳格式,无中断实现万年历

[复制链接]
jjldc 发布时间:2009-1-4 16:19
基于STM32处理器7 W1 @- _2 n' }1 R; O3 W+ U
RTC只是个能靠电池维持运行的32位定时器over!
: O' B) x- z, j: ~9 f/ @, U, R1 t2 G$ y4 D并不像实时时钟芯片,读出来就是年月日。。。2 m( E5 j- I0 E* N* e
看过些网上的代码,有利用秒中断,在内存中维持一个年月日的日历。1 K6 g- M  u+ J+ M8 C% b6 k
我觉得,这种方法有很多缺点:+ |5 k$ H& o3 @& R- I/ `
1.断电时没有中断可用
8 s% i( D+ U! B2.频繁进中断,消耗资源
- R  ?0 l6 e* b6 g" O3.时间运算复杂,代码需要自己写
' @% V; F" K  ^4.不与国际接轨。。。。6 _1 i% k( a; z$ W4 C" g; {  {

! b4 X3 ]: c7 iso,还是用标准的UNIX时间戳来进行时间的操作吧!
, Y8 y: A' U) @6 I3 y什么是UNIX时间戳?
: i/ L. e  [/ i, Z) \% C4 q7 ZUNIX时间戳,是unix下的计时方式。。。很废话- }6 s) s( q4 g1 G+ A* H1 |0 I' T
具体点:他是一个32位的整形数(刚好和STM32的RTC寄存器一样大),表示从UNIX元年(格林尼治时间1970-1-1 0:0:0)开始到某时刻所经历的秒数
) E8 I1 S5 F& I9 Q) j听起来很玄幻的,计算下: 32位的数从0-0xFFFFFFFF秒,大概到2038年unix时间戳将会溢出!这就是Y2038bug
; m/ k1 I5 r" Z# N- o6 }: I4 a- z/ P+ ?4 n不过,事实上的标准,我们还是照这个用吧,还有二十年呢。。。- n7 F7 U8 p" ^
  w' m/ ^2 s  G' j4 l1 j2 ]
UNIX时间戳:1229544206  现实时间:2008-12-17  20:03:26 7 D0 r9 G% `2 i3 C' H  W( a8 [0 O
* V; L7 w- c& Z: [
我们要做的,就是把当前时间的UNIX时间戳放在RTC计数器中让他每秒++,over: t' B* q0 H$ ^9 |1 M; F
然后,设计一套接口函数,实现UNIX时间戳与年月日的日历时间格式转换 这样就可以了
$ m+ G! A; Q& S; O" J3 r, W3 G
3 `2 c/ Z: C0 {4 i在RTC中实现这个时间算法,有如下好处:) z  C% V4 ]6 z- F5 c( g
1. 系统无需用中断和程序来维持时钟,断电后只要RTC在走即可
3 B! z7 J) z& C1 U& a2. 具体的两种计时的换算、星期数计算,有ANSI-C的标准C库函数实现,具体可以看time.h! Y& `, W1 F  e+ t# N4 L
3. 时间与时间的计算,用UNIX时间戳运算,就变成了两个32bit数的加减法1 |6 k4 N% A9 O! E
4. 与国际接轨。。。
/ P' y* k- B' T
9 c9 |" q: U( c4 d% U& I5 ]4 q7 J5 P
幸好是与国际接轨,我们有time.h帮忙,在MDK的ARM编辑器下有,IAR下也有
* t- c% B. f1 {其中已经定义了两种数据类型:unix时间戳和日历型时间/ L) R$ t8 l( o4 P6 d5 P- H
 time_t:       UNIX时间戳(从1970-1-1起到某时间经过的秒数)
- H: k( t( Z8 N     typedef unsigned int time_t;
) H& `" G6 z  Q* @ 
+ F! I& s2 p7 E3 A4 z struct tm:    Calendar格式(年月日形式)3 ^$ Y) \$ u/ {7 e

9 _" k3 H+ u  r% n3 V" h8 ~同时有相关操作函数3 r8 S5 _6 @8 }  o
gmtime,localtime,ctime,mktime等等,方便的实现各种时间类型的转换和计算  @3 {5 O3 X- A- N& V, K% }, z

) J/ A) q. Q9 O# t/ B9 C, x于是,基于这个time.h,折腾了一天,搞出了这个STM32下的RTC_Time使用的时间库1 G- K% n$ \! ?* s
% c. y: P+ K5 K6 K; ^, G5 x

  _, Q+ ]; y2 P+ W) k( v% l; N: [这是我的RTC_Time.c中的说明:
8 j, O$ t+ x( W7 e0 W% v5 V5 z+ S; P& U; \( u4 U( ^. K( K
 本文件实现基于RTC的日期功能,提供年月日的读写。(基于ANSI-C的time.h)3 m. [9 S) o4 H$ ^( S' I& b) R
   @5 U9 u5 e, M) d* o/ W% Q, |
 作者:jjldc (九九)% k/ o. M, W4 T( B3 G: o6 a
 QQ: 770586178 M& N- j5 |) j3 ?9 f
 
! K: n8 v& p2 S( i2 ? RTC中保存的时间格式,是UNIX时间戳格式的。即一个32bit的time_t变量(实为u32)# R  `+ k; X2 E& e* }7 M7 r

$ i* a5 G+ W4 e) L ANSI-C的标准库中,提供了两种表示时间的数据  型:
. I& d5 R) _) e* W' u time_t:       UNIX时间戳(从1970-1-1起到某时间经过的秒数). z; S/ V) e- i$ S6 g2 ?
     typedef unsigned int time_t;
- h; _( I) f; J' p3 s/ X5 t 
3 X; E. R; x) G struct tm:    Calendar格式(年月日形式)
* Z' [8 E- K; P- a. s$ A, C! |   tm结构如下:
- y# t0 g3 Y. p   struct tm {3 Z* T" V" z9 |) o
       int tm_sec;   // 秒 seconds after the minute, 0 to 60
# f' z9 @. `( R' u: ~3 V8 l                        (0 - 60 allows for the occasional leap second)/ @7 k4 B' O$ X# r4 J1 i5 z. c, g  V% J+ R
       int tm_min;   // 分 minutes after the hour, 0 to 59
! Q* _1 O( X- p/ n& @$ ~        int tm_hour;  // 时 hours since midnight, 0 to 23
) y+ _- f* {' V! z        int tm_mday;  // 日 day of the month, 1 to 31
; @& o$ T# k8 ?/ b2 m* p        int tm_mon;   // 月 months since January, 0 to 11
+ M+ w  M3 P5 O5 M% [" ]        int tm_year;  // 年 years since 1900
3 a1 ]# ^+ K, e7 ^* \3 c        int tm_wday;  // 星期 days since Sunday, 0 to 6+ R8 q$ `: j0 M
        int tm_yday;  // 从元旦起的天数 days since January 1, 0 to 365
- E& \% i& ^% O/ l) d# Q. P         int tm_isdst; // 夏令时??Daylight Savings Time flag
+ ~7 H0 k" {% i0 L6 o3 i0 p5 d         ...# C6 I6 v3 B/ x
     }: s) d  B4 \) R9 z! w  T9 U$ m
     其中wday,yday可以自动产生,软件直接读取
; _' l2 ?$ ?9 ^  E4 d, f7 g$ \     mon的取值为0-11
+ N% h$ O5 l' f( [9 h    ***注意***:3 D* R9 r* g* R  |! L
    tm_year:在time.h库中定义为1900年起的年份,即2008年应表示为2008-1900=108# \/ T+ ~: ^; G5 I/ f# _  I( y+ `9 v6 {
     这种表示方法对用户来说不是十分友好,与现实有较大差异。8 |. M" U2 G+ _, j4 O6 m
     所以在本文件中,屏蔽了这种差异。: Y$ h8 c- y( Q
     即外部调用本文件的函数时,tm结构体类型的日期,tm_year即为2008
; c, b, b" M$ o- d+ x, L     注意:若要调用系统库time.c中的函数,需要自行将tm_year-=1900
$ W/ U; \4 u2 f% D4 C% ^   x  I) ^1 L$ h$ F
 成员函数说明:' n' X0 _( D. U6 \  {. Y9 u2 p! q
 struct tm Time_ConvUnixToCalendar(time_t t);2 D+ V  ^7 R2 ?7 q( r( x
     输入一个Unix时间戳(time_t),返回Calendar格式日期: c- ~9 a, c  ~4 m5 e" o' N
 time_t Time_ConvCalendarToUnix(struct tm t);( T3 ~* o& C( Z, ?
     输入一个Calendar格式日期,返回Unix时间戳(time_t)
# m) H. h2 Z( G! n time_t Time_GetUnixTime(void);: P5 f$ D' g4 K" A; z& h
     从RTC取当前时间的Unix时间戳值, j. ^) t+ D; \8 c
 struct tm Time_GetCalendarTime(void);
8 o' l# @, O/ E( q) O     从RTC取当前时间的日历时间& {- ?$ V. S% o$ o* J
 void Time_SetUnixTime(time_t);
5 Z3 j6 R) }  @- y  ^' O' j- G2 P     输入UNIX时间戳格式时间,设置为当前RTC时间
7 ]3 T" Z; C2 j: |% m- z1 l3 P5 R$ F void Time_SetCalendarTime(struct tm t);  ~- E  l0 k% {& j0 T7 g1 j+ o
     输入Calendar格式时间,设置为当前RTC时间3 v3 i3 K/ h) |7 ~: _* r0 s
 
- q; f5 D6 a  }. B 外部调用实例:
5 y# _/ r; }! ~$ @) }; c# L- Y6 o 定义一个Calendar格式的日期变量:
$ t/ J: m( k# H- S, X& G- z& L struct tm now;
8 }3 N- A  Z1 t8 v now.tm_year = 2008;5 |4 s/ E$ q& c8 j- g
 now.tm_mon = 11;        //12月. ]3 K2 t6 Y1 i. h
 now.tm_mday = 20;
2 U$ x- I1 _: f now.tm_hour = 20;
$ y7 S" }: {" q  ` now.tm_min = 12;, {. F3 E+ }) g( X1 E3 Z
 now.tm_sec = 30;
$ L' N8 B; a* g & O5 q! ]; j2 b4 g0 J
 获取当前日期时间:
* C* O3 ^; W. w2 i tm_now = Time_GetCalendarTime();
9 ~3 {( f; x( M' S/ K 然后可以直接读tm_now.tm_wday获取星期数+ _# }4 @8 o% T3 s, {
 ' j# B- G) N( }. h
 设置时间:: L# y& B0 L7 x
 Step1. tm_now.xxx = xxxxxxxxx;5 H8 a+ N+ q* Z+ G9 m0 V
 Step2. Time_SetCalendarTime(tm_now);
' q+ y( q; E& H* j6 y! j ) M% V& b; ]" m3 s; }. w, u
 计算两个时间的差
) s+ O$ @/ O) F struct tm t1,t2;7 p! S' d1 ^, ]% O+ C9 C
 t1_t = Time_ConvCalendarToUnix(t1);
8 s0 e( B( {! \9 ?8 b; K0 B t2_t = Time_ConvCalendarToUnix(t2);
4 @1 _- D: W3 f1 r dt = t1_t - t2_t;
2 v6 A4 m9 J) F dt就是两个时间差的秒数
4 }0 j# n% O3 M7 |8 W dt_tm = mktime(dt);    //注意dt的年份匹配,ansi库中函数为相对年份,注意超限
- L1 M4 T+ P; S2 B$ @. R 另可以参考相关资料,调用ansi-c库的格式化输出等功能,ctime,strftime等6 B% e3 E+ N5 G1 O( {2 i
 
4 h2 u" t: {% E% d: }+ F: k9 l0 U5 l. I* _8 `% R) L) n% U
这是包含了RTC_Time的工程实例,可以用来参考- s2 I3 [/ a* y6 P" T  `2 a0 f5 g# E
基于MDK环境
6 V; c( Q  H9 ^$ a ' v0 K6 Z  B6 X- ~
 

发布基于ANSI-C的RTC_Time库,利用UNIX时间戳格式,无中断实现万年历.rar

下载

179.12 KB, 下载次数: 92

收藏 评论0 发布时间:2009-1-4 16:19

举报

0个回答

所属标签

相似分享

关于意法半导体
我们是谁
投资者关系
意法半导体可持续发展举措
创新和工艺
招聘信息
联系我们
联系ST分支机构
寻找销售人员和分销渠道
社区
媒体中心
活动与培训
隐私策略
隐私策略
Cookies管理
行使您的权利
关注我们
st-img 微信公众号
st-img 手机版