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

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

[复制链接]
jjldc 发布时间:2009-1-4 16:19
基于STM32处理器
/ u8 M2 Y! g% l9 cRTC只是个能靠电池维持运行的32位定时器over!
  G2 \5 e5 |8 Q/ d0 Z7 }并不像实时时钟芯片,读出来就是年月日。。。
) F+ o$ _$ J3 x  R6 t: ?$ M看过些网上的代码,有利用秒中断,在内存中维持一个年月日的日历。# M0 c% n( W: b: M/ x# P; A
我觉得,这种方法有很多缺点:
' ?" _+ h; ~. V" G$ O* ?1.断电时没有中断可用; o: Y4 T: Z6 U% l, F  u5 s
2.频繁进中断,消耗资源; S7 e+ h3 e8 K: e& @. P& E
3.时间运算复杂,代码需要自己写1 Y5 A+ t1 }0 T8 x8 w  O3 W! C
4.不与国际接轨。。。。3 i' f* _% O7 g8 B: x

* ^4 I; a3 q0 @: ?! y/ y+ U+ ^  [5 _so,还是用标准的UNIX时间戳来进行时间的操作吧!
1 _/ G6 p  x9 n* e9 w什么是UNIX时间戳?2 i# ~, e: ]* X% x8 ]- R. @. {* x
UNIX时间戳,是unix下的计时方式。。。很废话
+ r5 m; q" }9 i( L3 p具体点:他是一个32位的整形数(刚好和STM32的RTC寄存器一样大),表示从UNIX元年(格林尼治时间1970-1-1 0:0:0)开始到某时刻所经历的秒数
' ~' f+ _0 g0 X2 p/ v听起来很玄幻的,计算下: 32位的数从0-0xFFFFFFFF秒,大概到2038年unix时间戳将会溢出!这就是Y2038bug4 J" w  W  u8 |( y2 C! s0 C2 A$ u
不过,事实上的标准,我们还是照这个用吧,还有二十年呢。。。
2 i1 \4 S* ^) Z: f: m# p  @( j, _/ @  {8 P) U  ]
UNIX时间戳:1229544206  现实时间:2008-12-17  20:03:26
: d3 ^$ O# E. @
4 Y4 t) u7 Z2 C我们要做的,就是把当前时间的UNIX时间戳放在RTC计数器中让他每秒++,over
, R) c5 g) k  [. m8 C8 {2 K然后,设计一套接口函数,实现UNIX时间戳与年月日的日历时间格式转换 这样就可以了
. N! z! w$ R% [* x$ G
8 C; K2 _- k" e& z) U  }在RTC中实现这个时间算法,有如下好处:
8 I8 D0 \' |) m# E) I1. 系统无需用中断和程序来维持时钟,断电后只要RTC在走即可, y' r5 n& l% J' L+ g* M% n
2. 具体的两种计时的换算、星期数计算,有ANSI-C的标准C库函数实现,具体可以看time.h: X- g) ], j3 J
3. 时间与时间的计算,用UNIX时间戳运算,就变成了两个32bit数的加减法
: t* k( l* y1 ?$ I+ `7 I: P4. 与国际接轨。。。9 i6 M" R; ?- W6 b, x, h
) U& m& g. _2 I) o
/ Q1 R. y+ M! k( t
幸好是与国际接轨,我们有time.h帮忙,在MDK的ARM编辑器下有,IAR下也有) {; Q: v2 `% w$ S8 p
其中已经定义了两种数据类型:unix时间戳和日历型时间  C  Y: L' p" R5 |" o
 time_t:       UNIX时间戳(从1970-1-1起到某时间经过的秒数); u$ o8 G1 T! n. @( M* M
     typedef unsigned int time_t;% b- [& f3 L* `) l+ o2 P# H% [1 _. i
 - c6 v8 A: R! e& o! m' N
 struct tm:    Calendar格式(年月日形式)% ]- }) B; G- C5 @
! ]' ^  [3 Q0 L# N) a1 v7 I
同时有相关操作函数" N3 J+ n8 k& Y# @9 Y
gmtime,localtime,ctime,mktime等等,方便的实现各种时间类型的转换和计算) S* V; w& K1 [2 {

6 `* u1 z; W& w4 \! ?: x于是,基于这个time.h,折腾了一天,搞出了这个STM32下的RTC_Time使用的时间库
+ n: t( |: _) x. F- o! ?( `0 d( }, a  Z0 H0 V
: U3 \' u9 {. B) {
这是我的RTC_Time.c中的说明:
6 v* C6 m! X# _; e$ m. j& d5 R* e2 ]9 G4 c
 本文件实现基于RTC的日期功能,提供年月日的读写。(基于ANSI-C的time.h)
7 O: F# {% h5 l) ~3 B* I ' X) g( r' c# c0 A* N
 作者:jjldc (九九)
! {- f. h0 X! X7 V5 q, k& b. d' P QQ: 77058617  B4 [+ S  N0 m) s! I
 0 w6 {1 ^* a9 L- T5 d8 f, c& K3 H
 RTC中保存的时间格式,是UNIX时间戳格式的。即一个32bit的time_t变量(实为u32)& k8 [: ~) R, G6 L0 D

9 v0 R& z* L/ I% {( m0 x8 } ANSI-C的标准库中,提供了两种表示时间的数据  型:: ?- T7 L5 i0 h$ y5 h
 time_t:       UNIX时间戳(从1970-1-1起到某时间经过的秒数)
* \1 S6 D5 O% Q) P$ ^     typedef unsigned int time_t;
1 v* a) R5 a( \. L 4 V/ f! t  C, E0 {
 struct tm:    Calendar格式(年月日形式)6 r  ]  x  S; R, }
   tm结构如下:: Q9 s5 x0 m( b3 K8 \3 |
   struct tm {5 m# ^: x" c  O8 e) \  a* r4 D* l  h3 v
       int tm_sec;   // 秒 seconds after the minute, 0 to 60
, n6 q$ @; L0 U                        (0 - 60 allows for the occasional leap second)0 _; ^4 |1 V  P" p
       int tm_min;   // 分 minutes after the hour, 0 to 592 l( E1 P% M; q8 d( J0 X5 a; o
        int tm_hour;  // 时 hours since midnight, 0 to 23( E% D# P( O( ]! w& }
        int tm_mday;  // 日 day of the month, 1 to 31- \6 m2 L! V9 {1 e& {; x2 |
        int tm_mon;   // 月 months since January, 0 to 11& Y, w  ^  D, r* i3 E) c7 g
        int tm_year;  // 年 years since 1900
: ?' K1 i; a- `8 f        int tm_wday;  // 星期 days since Sunday, 0 to 6
1 `& G+ `" a- h# T; a        int tm_yday;  // 从元旦起的天数 days since January 1, 0 to 365+ ~4 z( h4 p, _6 E( {% ?- w$ i/ ^
         int tm_isdst; // 夏令时??Daylight Savings Time flag3 z* N- y7 w) i1 z8 \) |0 {
         ...
- K  `8 c. G1 N1 ?, I3 q  d     }
/ I" m7 P9 s+ V+ v6 u     其中wday,yday可以自动产生,软件直接读取/ g( E5 x7 q5 B2 B
     mon的取值为0-11! a4 u$ x6 P" L- U- j2 Y0 b
    ***注意***:
- ]& a" R( N4 H! S& a    tm_year:在time.h库中定义为1900年起的年份,即2008年应表示为2008-1900=108. ]  N- _, D" a! p. M
     这种表示方法对用户来说不是十分友好,与现实有较大差异。1 U1 _# G1 k% Q
     所以在本文件中,屏蔽了这种差异。
. T  E. h5 k- E* U     即外部调用本文件的函数时,tm结构体类型的日期,tm_year即为2008
% i4 x) z6 e& w6 C, P1 x" x" e     注意:若要调用系统库time.c中的函数,需要自行将tm_year-=19003 J! d, h; z3 F2 D$ H# H
 
& g" z5 x0 c3 f  n4 r+ I- n4 [1 }/ I 成员函数说明:
1 W5 i2 S& i% Z struct tm Time_ConvUnixToCalendar(time_t t);# D! Y% l. z/ @1 ~( Z. T
     输入一个Unix时间戳(time_t),返回Calendar格式日期
& l3 V% y- {' U. S time_t Time_ConvCalendarToUnix(struct tm t);
$ E6 g* \% O" q% v1 \     输入一个Calendar格式日期,返回Unix时间戳(time_t). O, y* {' z$ U! H. j: g
 time_t Time_GetUnixTime(void);
- [5 R# [8 Q& z6 i! M9 l! A     从RTC取当前时间的Unix时间戳值: J: |! k. d6 X7 c: N" e- G
 struct tm Time_GetCalendarTime(void);! E# i+ \3 ~9 v5 s: T: k
     从RTC取当前时间的日历时间8 ~# W" h8 f. M5 `% s
 void Time_SetUnixTime(time_t);
& a# w6 x; `' Z$ k     输入UNIX时间戳格式时间,设置为当前RTC时间) i" b$ }& w1 A9 e; F. U
 void Time_SetCalendarTime(struct tm t);! _2 k* d; W# t" b% U' d0 Z- `
     输入Calendar格式时间,设置为当前RTC时间
9 v8 i3 C2 h2 N$ L 7 K) d) ], p4 P1 N. ^( x8 C
 外部调用实例:
% E2 x2 i- D) r0 ^ 定义一个Calendar格式的日期变量:% p* I" J6 y& h% w4 l4 z0 q* p% G
 struct tm now;
% z! K6 f2 Y* o8 P" ^5 h now.tm_year = 2008;
) c2 A+ I, ]( L8 x- v now.tm_mon = 11;        //12月+ L- V+ z% K' ?; F' m
 now.tm_mday = 20;9 ~. \9 v- t% c4 F3 u
 now.tm_hour = 20;/ w& F2 Q  ^' s2 R; {$ ^: M
 now.tm_min = 12;
- |) O( ~  s* O. _( k' A now.tm_sec = 30;$ A5 m3 D3 ]2 e+ `- @- d. F
 4 w% X! _( e% B$ E3 b/ Q
 获取当前日期时间:! c* D: ]9 H, M, b% p
 tm_now = Time_GetCalendarTime();
2 M- [, `; D& V; X/ g 然后可以直接读tm_now.tm_wday获取星期数3 r4 z  t  I8 W
 
" A. L, [: `8 W6 ~+ u7 R 设置时间:
/ E8 n* u8 p5 }1 j Step1. tm_now.xxx = xxxxxxxxx;* f! u2 Y' H: O, r; F& I
 Step2. Time_SetCalendarTime(tm_now);
3 L8 L8 V& E) y4 r) X  p2 N ( R4 P) W2 R% j$ R- Y+ {. j7 u
 计算两个时间的差7 U- z( e/ Z1 n9 E; Z* [) U
 struct tm t1,t2;
/ r0 B# p$ V5 O% z0 @. N3 y t1_t = Time_ConvCalendarToUnix(t1);  t( S  N* h. {  F. L+ E4 w
 t2_t = Time_ConvCalendarToUnix(t2);
% F1 Q8 ]* j. T# h& |: ]9 O dt = t1_t - t2_t;6 I/ a+ y" T4 c$ V8 u
 dt就是两个时间差的秒数
/ O3 x8 X$ L. ?; J dt_tm = mktime(dt);    //注意dt的年份匹配,ansi库中函数为相对年份,注意超限# g8 t0 l; X( l( }1 x+ o
 另可以参考相关资料,调用ansi-c库的格式化输出等功能,ctime,strftime等
+ {* h' h+ w% h4 C( r2 W 4 a" j+ a7 M) k) N

2 o' a0 w, H5 ~8 ?) w这是包含了RTC_Time的工程实例,可以用来参考7 f6 s. _1 r2 ]/ B" }$ U" {
基于MDK环境5 {! r+ I; E6 \7 u
 ; z1 n4 F) q$ ~4 i5 \" U3 c
 

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

下载

179.12 KB, 下载次数: 92

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

举报

0个回答
关于
我们是谁
投资者关系
意法半导体可持续发展举措
创新与技术
意法半导体官网
联系我们
联系ST分支机构
寻找销售人员和分销渠道
社区
媒体中心
活动与培训
隐私策略
隐私策略
Cookies管理
行使您的权利
官方最新发布
人形机器人运动控制、感知与智能配电
半导体创新技术与应用方向
EE架构与软件定义汽车
12V/48V 汽车智能配电(SPD)
区域控制单元(ZCU)与分区架构
关注我们
st-img 微信公众号
st-img 手机版