源:RTC-高效率实现TimerTicker编解码

  嵌入式系统中时间是很重要的,在以往的系统中设计者常常使用一种叫RTC的专用芯片来维持时间,这种芯片种类很多接口形式也很多,如常用的DS1302、PCF8563、DS12887等等,虽然用起来方便,但额外增加一个器件和一种驱动程序,这同时也增加了系统的不安全因素,并且很多时候嵌入式工程师常发现这些时钟芯片的走时精度值得怀疑,且难于修改。

  现在的MCU或MPU,一般都带有RTC功能,这对嵌入式工程师来说是个好消息,不用再为此扩展一枚芯片了,但通常RTC寄存器中提供的是一个32位的时间刻度值,并没有专用芯片那样分解成时分秒日月年之类的,此处,我将讨论它们的互换算法,其实也很简单。

  一般可以设定RTC寄存器每秒加1,这样寄存器中的值使终代表了当前累计的秒数,还好这种RTC结构都是可以由后备电池来维护运行的,不致于断电就没有了。这个32位寄存器值被称为TimerTicker,时间刻度,很是形象。

  首先考虑记录时间,32位的整型量每秒加一,其共能记录的时间为,2的32次方秒,即约136.19年,这对于一个产品来说运行时间相当足够了,试想一个产品能运行超过136年是多么恐怖的数字啊。

  

  如何把任意时刻转换成为刻度呢?也就是编码。

  先看下面的时间结构:

typedef struct
{
uint8 Year;       //年
uint8 Month;       //月
uint8 Day;  //日
uint8 Hour; //时
uint8 Minute; //分
uint8 Second; //秒
}DateTime;

  上面定义的结构实现了最常用的时间结构,对于具体应用,可以添加星期等。其年份可以用年纷的后两位实现,这样可以实现任何世纪,呵呵,理论上。

  下面的方法将把此结构编码成为时间刻度:

//Author: 愿陪你一生 QQ380052073
//Note: 本方法时间起点从2000-1-1 0:0:0开始,向后编码150年
uint32 RTC_EncodeTime(DateTime * DT)
{
uint8 T,K;
uint32 T32,TimeData=;
for(T=,K=;T<DT->Year;T++){ //累加年份
K=T&0x03;
TimeData+=K?:;
}
for(T=;T<DT->Month;T++){
if(T!=){ //统计平月
T32=((T+(T>>))&0x01)?:;
}else T32=K?:; //统计闰月
TimeData+=T32;
}
T32=DT->Day-;TimeData+=T32*; //统计天
T32=DT->Hour;TimeData+=T32*; //统计时
T32=DT->Minute;TimeData+=T32*; //统计分
TimeData+=DT->Second; //统计秒
return TimeData;
}

  以上方法实现任意时刻编码,其算法思路是先累加年份,从起点年份开始向后计算,每过四年要计算一次闰年,其它为平年,这里运用位运算方法实现了闰年和平年的判断,接下来就计算一年中的月数,这里要对2月份分闰年和平年来讨论,上面的方法中供用了闰平年判断的标志,不用再次判断。最后是时分秒的累加过程,这部分最简单了,全部化为秒即可。

  

  同样的思路,可以实现从任意刻度解码到当前时间,即逆变换过程,如下面的方法:

//Author: 愿陪你一生 QQ380052073
//Note: 本方法时间起点从2000-1-1 0:0:0开始,向后解码150年
void RTC_DecodeTime(uint32 TimeData,DateTime * DT)
{
uint8 T,K;
uint32 T16,K16;
K16=TimeData%; //分离时/分/秒
T16=TimeData/; //分离年/月/日
DT->Second=K16%; //计算秒
K16/=;DT->Minute=K16%; //计算分
K16/=;DT->Hour=K16%; //计算时
for(K16=,T=;T<;T++){ //按天累计年份
K16=(T&0x03)?:; //统计闰年
if(T16<K16){K16-=;break;} //计算当年二月份天数
else T16-=K16; //减掉年份
}
DT->Year=T; //计算得到相对年份
for(T=;T<;T++){
K=(T==)?K16:(((T+(T>>))&0x01)+); //统计当月天数
if(T16>=K)T16-=K; //减掉当前月
else break;
}
DT->Month=T; //计算得到当年中的月份
DT->Day=T16+; //计算得到当年中的天
}

  上面的算法实现了解码,正好采用相反的方向,先分离出时分秒和年月日,因为闰平年中一天种有24个小时,一小时总是3600秒,而从一月有多少天这里开始出现分岐,所以分离出两部分。秒分时的解码从前部分中得到,依次求余即可,而年月日的分离则需要考虎闰平年和是否2月等。同样先从起点时刻向上累加天数,中间需要区分闰平年,之后即可把年份提取出来,随后再分开月和天,月分的闰年标记同样从年份分离中得到。

  以上只是时间刻度编解码的一种方法,经过测试,其效率还是比较高的,运行速度和程序占用空间都满意,适合MCU使用。在分解后的时间结构中,还可以实现类似农历的算法。

RTC-高效率实现TimerTicker编解码的更多相关文章

  1. 各种音视频编解码学习详解 h264 ,mpeg4 ,aac 等所有音视频格式

    编解码学习笔记(一):基本概念 媒体业务是网络的主要业务之间.尤其移动互联网业务的兴起,在运营商和应用开发商中,媒体业务份量极重,其中媒体的编解码服务涉及需求分析.应用开发.释放 license收费等 ...

  2. 集显也能硬件编码:Intel SDK && 各种音视频编解码学习详解

    http://blog.sina.com.cn/s/blog_4155bb1d0100soq9.html INTEL MEDIA SDK是INTEL推出的基于其内建显示核心的编解码技术,我们在播放高清 ...

  3. 我的Android进阶之旅------>Android中编解码学习笔记

    编解码学习笔记(一):基本概念 媒体业务是网络的主要业务之间.尤其移动互联网业务的兴起,在运营商和应用开发商中,媒体业务份量极重,其中媒体的编解码服务涉及需求分析.应用开发.释放license收费等等 ...

  4. 【miscellaneous】各种音视频编解码学习详解

    编解码学习笔记(一):基本概念 媒体业务是网络的主要业务之间.尤其移动互联网业务的兴起,在运营商和应用开发商中,媒体业务份量极重,其中媒体的编解码服务涉及需求分析.应用开发.释放license收费等等 ...

  5. 【FFMPEG】各种音视频编解码学习详解 h264 ,mpeg4 ,aac 等所有音视频格式

    目录(?)[-] 编解码学习笔记二codec类型 编解码学习笔记三Mpeg系列Mpeg 1和Mpeg 2 编解码学习笔记四Mpeg系列Mpeg 4 编解码学习笔记五Mpeg系列AAC音频 编解码学习笔 ...

  6. 【知识点】H264, H265硬件编解码基础及码流分析

    前言 音视频开发需要你懂得音视频中一些基本概念,针对编解码而言,我们必须提前懂得编解码器的一些特性,码流的结构,码流中一些重要信息如sps,pps,vps,start code以及基本的工作原理,而大 ...

  7. iOS8系统H264视频硬件编解码说明

    公司项目原因,接触了一下视频流H264的编解码知识,之前项目使用的是FFMpeg多媒体库,利用CPU做视频的编码和解码,俗称为软编软解.该方法比较通用,但是占用CPU资源,编解码效率不高.一般系统都会 ...

  8. IOS和Android支持的音频编解码

    1.IOS编码 参考文档地址:https://developer.apple.com/library/ios/documentation/AudioVideo/Conceptual/Multimedi ...

  9. java编解码技术,netty nio

    对于java提供的对象输入输出流ObjectInputStream与ObjectOutputStream,可以直接把java对象作为可存储 的字节数组写入文件,也可以传输到网络上去.对与java开放人 ...

随机推荐

  1. 滚动条加粗和panel,gridControl结合用

    private void FrmLotterycs_Load(object sender, EventArgs e) { t = 0; UserJuanquanTB = O.get_UserJuanq ...

  2. HDU--1301--Jungle Roads(最小生成树)

    Problem Description The Head Elder of the tropical island of Lagrishan has a problem. A burst of for ...

  3. 其他应用和技巧-用Json格式来保存数据

    -------------------- <script type="text/javascript">            //定义json变量           ...

  4. MC 跨周期 画线

    using System; using System.Drawing; using PowerLanguage.Function; using System.Collections; namespac ...

  5. 第3章 Java语言基础----声明成员变量,对变量进行赋值

    声明成员变量,对变量进行赋值的正确语句,如下图所示:

  6. 7.在第4题中Hello.class所在路径下, 输入命令:java Hello.class,会出现什么结果,为什么?

    java Hello已经是加载类了

  7. differences between null pointer and void pointer.

    These are two different concepts, you cannot compare them. What the difference between the skunk and ...

  8. mysql数据库参数innodb_buffer_pool_size和max_connections

    接到报故,查看mysql数据库以下参数 1.innodb_buffer_pool_size 2.max_connections 该参数定义了数据缓冲区buffer pool大小,类似于oracle的d ...

  9. 获取IP地址bash[转载]

    ipaddr=`/sbin/ifconfig | grep 'inet addr:' | grep -v '127.0.0.1' | cut -d : -f2 | awk '{print $1}'`

  10. vs远程调试

    一.远程       建立共享目录debug 二.本地 1.生成->输出->输出路径,由"bin\Debug\"改为远程目录"\\xxx\\debug&quo ...