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

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

[复制链接]
jjldc 发布时间:2009-1-4 16:19
基于STM32处理器3 I7 W3 o: H8 Y! v% q
RTC只是个能靠电池维持运行的32位定时器over!
6 v7 ^! H( \2 h+ e) N7 a9 x并不像实时时钟芯片,读出来就是年月日。。。
* Y" B4 P. O* j- ^( j0 ?看过些网上的代码,有利用秒中断,在内存中维持一个年月日的日历。; i+ l" N+ j2 L2 \
我觉得,这种方法有很多缺点:5 V0 R' {+ c+ G
1.断电时没有中断可用
# g6 w9 @% r$ j2 n/ f, u* Y% E2.频繁进中断,消耗资源2 F" y+ c% ^; y5 i3 K
3.时间运算复杂,代码需要自己写# l, ]! u0 l- P. I. J- f
4.不与国际接轨。。。。
  T" a6 ?) M$ z; d* p% ^6 c( q" p( U9 V8 A% h1 y+ b
so,还是用标准的UNIX时间戳来进行时间的操作吧!, z* q/ p' E. [* h
什么是UNIX时间戳?& {+ @' ]3 O6 w' d+ S
UNIX时间戳,是unix下的计时方式。。。很废话
7 L) ]# t) e5 Y( ^, v/ g! B0 W- i具体点:他是一个32位的整形数(刚好和STM32的RTC寄存器一样大),表示从UNIX元年(格林尼治时间1970-1-1 0:0:0)开始到某时刻所经历的秒数% D! {1 o& W. A0 k( u( G- L
听起来很玄幻的,计算下: 32位的数从0-0xFFFFFFFF秒,大概到2038年unix时间戳将会溢出!这就是Y2038bug3 a5 [3 d! l& T; w& U. _
不过,事实上的标准,我们还是照这个用吧,还有二十年呢。。。
  I0 z+ U, u$ X9 _* B; Y  ^
5 [/ _. X! ~2 H: J6 QUNIX时间戳:1229544206  现实时间:2008-12-17  20:03:26
0 P, P/ `6 s9 @+ z; u6 o; W
6 J# F: J: M( c8 x% l6 U. q' |我们要做的,就是把当前时间的UNIX时间戳放在RTC计数器中让他每秒++,over" Z1 K$ n( b- f1 Q- V& e! u& Q" _
然后,设计一套接口函数,实现UNIX时间戳与年月日的日历时间格式转换 这样就可以了
2 r6 t* `. @; e9 e& ~5 h
1 v; K, p/ S# K) H+ R在RTC中实现这个时间算法,有如下好处:
6 @9 U5 F. M' e3 n: u1 F1. 系统无需用中断和程序来维持时钟,断电后只要RTC在走即可7 _, F) g0 n! x/ ~7 j/ M  N7 A- c
2. 具体的两种计时的换算、星期数计算,有ANSI-C的标准C库函数实现,具体可以看time.h  F6 c+ J& d9 k, I
3. 时间与时间的计算,用UNIX时间戳运算,就变成了两个32bit数的加减法) n0 Z9 c$ P1 ]" g2 w8 I
4. 与国际接轨。。。
0 M) n- T# J4 ]& X, [) _9 E
9 X* W  Y2 c2 v0 Q. B2 U4 p# ~3 F, N  y+ }4 T0 p. a+ x  L
幸好是与国际接轨,我们有time.h帮忙,在MDK的ARM编辑器下有,IAR下也有* O' u0 Q4 q/ K1 h
其中已经定义了两种数据类型:unix时间戳和日历型时间8 \8 y4 o2 K" J) q4 [) q1 l
 time_t:       UNIX时间戳(从1970-1-1起到某时间经过的秒数)
$ h. N! b: E# O5 p$ a1 E$ W: q$ m     typedef unsigned int time_t;
& Z: e4 e% M- G* {5 A 8 F3 _; G5 f' J7 H% e8 u% @
 struct tm:    Calendar格式(年月日形式)# w& D: n8 a0 S1 e, ~

9 a0 ]& E5 F* {4 B3 c# @$ x/ N同时有相关操作函数" V' f: h1 P+ k6 n; x% b9 B2 g1 \
gmtime,localtime,ctime,mktime等等,方便的实现各种时间类型的转换和计算6 Z2 O( v! ^! P# [& W' Z

. p1 j) K) c  m) x6 d5 Y于是,基于这个time.h,折腾了一天,搞出了这个STM32下的RTC_Time使用的时间库' F. ]( J* S3 x" p9 h5 |) |
1 v5 l( p1 k4 a$ R+ Z' @
8 q. c0 S1 z* v" m, ~; i% w9 \
这是我的RTC_Time.c中的说明:# `5 n3 ?& h- V) O

: X1 m( T0 |( X( O. Y 本文件实现基于RTC的日期功能,提供年月日的读写。(基于ANSI-C的time.h)
. h6 D" [. F$ a2 t % ]" T% c* r3 y! B$ \
 作者:jjldc (九九)
* ~" D3 `  R/ Q* r QQ: 77058617
5 ?- E) T2 L4 D' H9 f 
2 s$ g$ T. @  b' N% q# C% q1 _ RTC中保存的时间格式,是UNIX时间戳格式的。即一个32bit的time_t变量(实为u32)
: v0 E4 D6 x9 _4 Y& G6 v0 l# e8 V7 z7 |3 K
 ANSI-C的标准库中,提供了两种表示时间的数据  型:
$ k) f, w8 N, v, q: x! P time_t:       UNIX时间戳(从1970-1-1起到某时间经过的秒数)6 i+ ^( t1 F/ N) E+ H
     typedef unsigned int time_t;
- |, e2 ]  d2 L) Y# \3 D$ y* | * t2 i, Q6 D- h/ H# ?# i. O+ ]; e
 struct tm:    Calendar格式(年月日形式)5 W5 w  ?. Y/ b9 D
   tm结构如下:5 ^/ h5 t2 ?/ P( e; L
   struct tm {' l7 P9 ]3 ~/ _* @$ A
       int tm_sec;   // 秒 seconds after the minute, 0 to 60
8 C7 G) j' S, y0 c7 E  m1 k5 p                        (0 - 60 allows for the occasional leap second)
5 q' e% e: e2 j. c) N1 W       int tm_min;   // 分 minutes after the hour, 0 to 59
1 H/ F8 v; U7 P, L/ r1 t, ]( u* L        int tm_hour;  // 时 hours since midnight, 0 to 23  ?+ |) Y, F) ]7 V7 @
        int tm_mday;  // 日 day of the month, 1 to 31
$ H$ \0 y/ q' |        int tm_mon;   // 月 months since January, 0 to 11
8 U( ]. \$ Y3 R" F, c" Q        int tm_year;  // 年 years since 1900
; l5 Z9 p& V2 ^6 p! |. V7 i2 ~4 M        int tm_wday;  // 星期 days since Sunday, 0 to 6
& S% P( |0 U# }) L$ V3 k6 _# F        int tm_yday;  // 从元旦起的天数 days since January 1, 0 to 365
& n; R* p' D- L& [" q# U5 a         int tm_isdst; // 夏令时??Daylight Savings Time flag" M  O) j$ T4 G% n
         ...! h) j" b/ Q# m# d0 r
     }
! R- e: ?; B( _' F- a5 `5 a) w     其中wday,yday可以自动产生,软件直接读取2 S8 P, v5 C+ F- p" Y' n
     mon的取值为0-11
2 {& v# d( G- A- g    ***注意***:
8 n. C4 k& @; k    tm_year:在time.h库中定义为1900年起的年份,即2008年应表示为2008-1900=108
$ ^9 {( H, z6 I- Z     这种表示方法对用户来说不是十分友好,与现实有较大差异。' x2 T/ @6 E- z, y" ?3 k- O
     所以在本文件中,屏蔽了这种差异。- X% P3 Q6 t" c* \# m# P* d
     即外部调用本文件的函数时,tm结构体类型的日期,tm_year即为2008
/ J7 z, @2 e# z8 ?8 R     注意:若要调用系统库time.c中的函数,需要自行将tm_year-=1900
3 g! ^8 G; j+ u% I2 \ 2 r" F0 x7 J4 g/ L* F/ C
 成员函数说明:
" T) I7 r7 `+ `, @7 x% U+ C struct tm Time_ConvUnixToCalendar(time_t t);9 |2 L) X( f& ^# ?5 O6 L& V: n) t
     输入一个Unix时间戳(time_t),返回Calendar格式日期' |/ x  Q* R, {& ]  q6 o: I+ B! T0 _
 time_t Time_ConvCalendarToUnix(struct tm t);
9 h4 B0 {7 P3 \9 i     输入一个Calendar格式日期,返回Unix时间戳(time_t)
) N/ A7 _- ?% k7 a/ }) a time_t Time_GetUnixTime(void);$ ]. P) g5 y1 m6 e/ ?
     从RTC取当前时间的Unix时间戳值$ r5 @8 S3 |+ d
 struct tm Time_GetCalendarTime(void);
& ]* ?* K6 {& K3 v     从RTC取当前时间的日历时间- \) h8 c5 ?0 H3 U1 P6 Z( Q
 void Time_SetUnixTime(time_t);: O2 i; q, K: ?) Q3 K4 T
     输入UNIX时间戳格式时间,设置为当前RTC时间1 G- A- k6 E( M# y$ w- n  r7 m) N
 void Time_SetCalendarTime(struct tm t);6 O  J$ t! E# p& u, I3 R8 l. a
     输入Calendar格式时间,设置为当前RTC时间
! R  {% ]* v9 o4 e4 U $ W, Q* |, P9 }4 C
 外部调用实例:
4 ?, a& |9 f# R" M- C$ E! C7 D 定义一个Calendar格式的日期变量:
( H. W- C& k# v" G: r8 m struct tm now;
' i- G" w2 ^2 p" v! T now.tm_year = 2008;
7 E7 [5 x+ b( p" J7 U8 A now.tm_mon = 11;        //12月
. n8 ?: g% d1 S* V now.tm_mday = 20;
* j7 h# e8 R( K# K9 M now.tm_hour = 20;
/ I9 v$ b6 t( l7 }% g now.tm_min = 12;
: {3 d8 Z0 R' p  g' X now.tm_sec = 30;: V5 Y' c; w, p- y$ a% N: T
 : e7 M/ W; V  o
 获取当前日期时间:
7 s4 M. V! Y7 V tm_now = Time_GetCalendarTime();
1 O/ o* Y( U/ x7 R 然后可以直接读tm_now.tm_wday获取星期数
! Q4 E0 k2 X  E  Y 
/ F/ v8 m: K0 l# q9 l& S 设置时间:( G: s2 ]6 y+ w
 Step1. tm_now.xxx = xxxxxxxxx;
3 u( J7 U% D: I# d0 ] Step2. Time_SetCalendarTime(tm_now);5 a% t! L: P3 k7 V
   Y* P9 X, M& P' K- r
 计算两个时间的差; ~& o5 W& U5 Y8 A& ~
 struct tm t1,t2;7 f4 r/ h) B9 t1 `, J3 |, z
 t1_t = Time_ConvCalendarToUnix(t1);
9 z4 W* a4 P* a! G5 o t2_t = Time_ConvCalendarToUnix(t2);& G# n+ ]  e1 l4 p$ t8 Y
 dt = t1_t - t2_t;
' e  R: E" S' A% s% X, Z dt就是两个时间差的秒数' z+ {7 J0 z7 Y' k2 q
 dt_tm = mktime(dt);    //注意dt的年份匹配,ansi库中函数为相对年份,注意超限' p5 L  g% ~9 h$ c* z( [
 另可以参考相关资料,调用ansi-c库的格式化输出等功能,ctime,strftime等& l# _5 Y  c& d3 W
 
& a! S) d" T, }$ K
7 T$ B4 t( Q' s* O这是包含了RTC_Time的工程实例,可以用来参考+ A5 M, g# ^1 b2 k- Z3 X- h* v
基于MDK环境
: J8 ~% v0 R2 w! t+ b) P  y 
, M% S. P8 U+ F9 K 

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

下载

179.12 KB, 下载次数: 92

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

举报

0个回答

所属标签

关于
我们是谁
投资者关系
意法半导体可持续发展举措
创新与技术
意法半导体官网
联系我们
联系ST分支机构
寻找销售人员和分销渠道
社区
媒体中心
活动与培训
隐私策略
隐私策略
Cookies管理
行使您的权利
官方最新发布
STM32N6 AI生态系统
STM32MCU,MPU高性能GUI
ST ACEPACK电源模块
意法半导体生物传感器
STM32Cube扩展软件包
关注我们
st-img 微信公众号
st-img 手机版