打印

C51编程 计算两个时间点之间的差值问题 感觉蛮有挑战性的

[复制链接]
4893|25
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主
gdmgb520|  楼主 | 2009-8-29 21:46 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
问题:如何判断两个时间点之间的间隔小于5分钟(300s)。
背景:at89s52系统从串口就收到上位机发来的数据,该数据的主要部分如下(内容为时间):年 月日 时 分 秒 年 月日 时 分 秒 ,前面的是系统时间,后面的是任务时间。如:09 08 28 16 05 20 09 08 29 22 20 00 。现在程序要判断这两个时间之间的间隔(任务时间-系统时间)是不是小于5分钟(300s),如果小于五分钟系统将采取提示动作,否则不动作。简而言之:单片机怎样判断现在的时间是否接近任务时间。
   
思想:先把所有可能出现的情况列出来,然后找出这些情况所满足的条件,那么在处理时就可以判断对象是否满足这些条件来决定对象是否达到要求。但是这种逻辑可能存在的问题是:不满足条件的肯定不符合要求,但是满足条件的却不一定符合要求。所以就要求用于判断的条件非常精确。
我的思路:经过分析,应该发出提示的有三大种情况1、两个时间点在同一天内相隔五分钟;2、两个时间点在同一个月内相隔五分钟;3、两个时间点在同一年内相隔五分钟。具体为以下六小种情况。
a.<两个时间点在同一天> 09.08.28 16:20:00 / 09.08.28 17:00:00 即—>  同年(年差yearc=0)、  同月(月差monthc=0)、  同日(日差dayc=0)  最后以秒为单位计算这两个时间点之间的差值
b.<两个时间点跨天> 09.08.28 23:55:00 / 09.08.29 00:00:00 即—>  同年(年差yearc=0)、  同月月差monthc=0)、不同日(日差dayc=1) 时差(hourc=-23)    最后以秒为单位计算这两个时间点之间的差值
c.<两个时间点跨月> 09.08.31 23:55:00 / 09.09.01 00:00:00 即—>  同年(年差yearc=0)、 不同月(月差monthc=1)、不同日(日差dayc=-30)时差(hourc=-23)  最后以秒为单位计算这两个时间点之间的差值
d.<两个时间点跨月> 09.09.30 23:55:00 / 09.10.01 00:00:00 即—>  同年(年差yearc=0)、 不同月(月差monthc=1)、不同日(日差dayc=-29)时差(hourc=-23)  最后以秒为单位计算这两个时间点之间的差值
e.<两个时间点跨月> 09.02.28(29) 23:55:00 / 09.03.01 00:00:00 即—>  同年(年差yearc=0)、 不同月(月差monthc=1)、不同日(日差dayc=-28或-27)时差(hourc=-23)  最后以秒为单位计算这两个时间点之间的差值
f.<两个时间点跨年> 09.12.30 23:55:00 / 10.01.01 00:00:00 即—> 不同年(年差yearc=1)、 不同月(月差monthc=-11)、不同日(日差dayc=-29)时差(hourc=-23)  最后以秒为单位计算这两个时间点之间的差值
假设现在接收到一组时间数据如果是应该做出提示的,那么这组时间数据必定符合上述条件之一,所以我用if语句来判断,如下:
(以上情况的各个条件必须要同时满足才算符合要求,只有符合要求的才算他们之间具体的时间差)
if (yearc==0 && monthc++0 &&dayc==0)
    {采用第一种时间差计算}
else if (yearc==0 && monthc==0 && dayc==1 && hourc==-23)
    {采用第二种时间差计算}
else if (yearc==0 && monthc==1 && (dayc==-30 ||dayc==-29 || dayc==-28 dayc==-27) && hourc==-23)
    {   
        调用月份判断函数(判断系统时间中的月是大月(flag=1)、小月(flag=2)、闰年2月(flag=3)或非闰年2月(flag=4),用变量flag来标识)
        if ((dayc==-30 && flag==1) || (dayc==-29 && flag==2) || (dayc==-28 && flag==3) || (dayc==-27 && flag==4))
            {采用第二种时间差计算}
    }
else if (yearc==1 && monthc==-11 && dayc==-29 && hourc==-23)
    {采用第二种时间差计算}
else
    {不计算时间差}
第一种时间差计算:hourc*3600+minutec*60 +secondc
第二种时间差计算:(minutec+60)*3600+secondc
月份判断函数()
{
    switch (系统月)
    case 1:
    case 3:
    case 5:
    case 7:
    case 8:
    case 10:
    case 12: flag=1; break;
    case 4:   
    case 6:
    case 9: flag=2; break;
    case 2: {判断该年是否为闰年,若是flag=3,否则flag=4} break;
    default:break;
}

我觉得这个逻辑判断能把所有符合要求的找出来,就是说对于应该提示的情况会发出提示,但是会不会在不应该提示的情况下也发出提示呢?
也不知道我说清楚了没有。希望大家帮我想一想,我想了几天头都晕了。很感谢你能耐着性子看到这里,我真诚的向您表示感谢。
希望大家能给出更好的方案建议,我在论坛没有找到类似的技术**,但是我相信这个问题以前一定有人做过,我知道这个问题可以用查表的方式解决,如果您以前做过,请您给我一些方案和建议。我的邮箱是gdmgb520@163.com,也可以留下您的邮箱,我和您联想。

相关帖子

沙发
一级菜鸟| | 2009-8-29 21:53 | 只看该作者
太麻烦了点,月份的天数查表,处理闰年,算出两个日期转换为秒的数,之后比较即可

使用特权

评论回复
板凳
gdmgb520|  楼主 | 2009-8-29 22:15 | 只看该作者
恩,我是以前没做过查表的,所以一开始就想到了用这个方法。另外,我决的查表的话要把表放到存储器里,如果是放很多年那数据会不会很大呢?

使用特权

评论回复
地板
一级菜鸟| | 2009-8-29 22:24 | 只看该作者
放一年的就够了老大,闰年的2月份加1,12个字节没多大吧

使用特权

评论回复
5
冷漠| | 2009-8-30 10:22 | 只看该作者
唉,看来在咱们中国——堂堂14亿人口大国,能用、会用嵌入式操作系统的工程师寥寥无几。

这类问题,前人早就做过了,并且写成了标准函数,用户只要调用2个库函数就解决了。(即使你不使用嵌入式OS,从它的库函数中抽出相关函数OBJ代码,应该没问题吧。何况随便就能找到这类库函数的开源代码。

LZ愿意自己做这类程序练练手,又另当别论。那么研究完了以后,是否也能写成标准库函数,供以后世人需要时调用,也不枉研究心血一场。

使用特权

评论回复
评分
参与人数 1威望 -10 收起 理由
NE5532 -10
6
NE5532| | 2009-8-30 10:30 | 只看该作者
没有探索就没有创新,会用人家的东西,充其量只是民工,堆砖头的罢了。应该鼓励这种有激情的研究方式。

使用特权

评论回复
7
谈的元| | 2009-8-30 10:52 | 只看该作者
恩恩,顶顶,花费点工夫也是值得的

使用特权

评论回复
8
zgl7903| | 2009-8-30 11:21 | 只看该作者
LZ的思路其实已经很接近了, 只是直接计算两个时间时差比较麻烦,跨年、跨月、。。。 考虑的因素比较多,
换一个思路,建一个参考的起始时间,这个参考时间取某年1月1号0时0分0秒,暂称原点。因为原点到每一组时间跨的都是整数,就算就容易多了。两组与原点的时差相减就得到两组时间的时差了。
还有一种方式,系统时间+5分钟,因为只需要考虑时日月年的进位,也比较容易
如果是电脑不断的刷新,那自然用电脑计算是最方便的(SystemTimeToVariantTime CTimeSpan 现成的),传递控制命令即可

使用特权

评论回复
9
一级菜鸟| | 2009-8-30 11:45 | 只看该作者
唉,看来在咱们中国——堂堂14亿人口大国,能用、会用嵌入式操作系统的工程师寥寥无几。

这类问题,前人早就做过了,并且写成了标准函数,用户只要调用2个库函数就解决了。(即使你不使用嵌入式OS,从它的库函数中 ...
冷漠 发表于 2009-8-30 10:22


不是每个应用都有条件调用现成函数的,某些MCU核甚至连C编译器都没有

使用特权

评论回复
10
有风| | 2009-8-30 12:06 | 只看该作者
楼上还没有考虑到闰年的问题,
你的参考起始时间很难顾及到闰年的问题,
例如,你选2009年1月1日,
那么2011年1月1日跟它相差多少天呢?还是要考虑到2010年不是闰年.

还是楼主老土一点的办法好一点,
不过感觉将天,小时合并一下好一点.
分别算出sys_time,  task_time的下面4个值,

年       unsigned int   year;
日       unsigned int   f_date(); //当天在当年的第几天
小时     unsigned char  hour;
秒       unsigned int   f_sec() = minute*60 +second;

char year_c = year[sys] - year[task];         // -1 ~ +1
int  date_c = f_date(sys) - f_date(task);     // -365 ~ +365
char hour_c = hour[sys] - hour[task];         // -23 ~ +23
int  second_c = f_sec[sys] - f_sec[task];     // -3599 ~ +3599

if(year_c >= 0)
{
  if(date_c >= 0)
  {
    if(hour_c >= 0)
    {
        ........
    }
}
要考虑到各种情况....
例如 year_c = 1, date_c = -365 这种情况
即sys_time  = 2010- 01-01 00:01
  task_time = 2009- 12-31 23:59

使用特权

评论回复
11
一级菜鸟| | 2009-8-30 12:08 | 只看该作者
楼上还没有考虑到闰年的问题,
你的参考起始时间很难顾及到闰年的问题,
例如,你选2009年1月1日,
那么2011年1月1日跟它相差多少天呢?还是要考虑到2010年不是闰年.

还是楼主老土一点的办法好一点,
不过感觉将天,小时合 ...
有风 发表于 2009-8-30 12:06


逢闰年加1,俺说过了的,有需要汇编源码的回帖,俺可以贴上来

使用特权

评论回复
12
有风| | 2009-8-30 12:16 | 只看该作者
不过话又说回来,
如果可以确定时间差小于24小时的话,
一大堆计算其实是扯淡!!!
直接比较秒即可.
没有借位直接取整,有借位+3600

使用特权

评论回复
13
救火车| | 2009-8-30 12:44 | 只看该作者
12楼说的必须是时间差小于24小时。
例如:
1号的23:59     到 3号的00:01
就会出错。

其实你可以换个角度考虑问题。
让单片机自己计时,用定时器做一个2秒的时钟。
没有收到信号,就自增1(程序控制最大增到151)。
收到信号,就清0.
(为了安全起见,使用字节型计数器,使最大数值不起过255)

使用特权

评论回复
14
wlsui| | 2009-8-30 17:54 | 只看该作者
经常看到有人拿着一个很小的问题在那很高深似的"研究", 有意思吗?

使用特权

评论回复
15
一级菜鸟| | 2009-8-30 18:45 | 只看该作者
经常看到有人拿着一个很小的问题在那很高深似的"研究", 有意思吗?
wlsui 发表于 2009-8-30 17:54


问题小不小因人而异,就LZ的问题,以本菜的水平来看,实现虽然简单,但是要取得一个最优的实现,问题不算小

使用特权

评论回复
16
耕在此行| | 2009-8-30 19:07 | 只看该作者
方法1:
      以一个时间点作起始点,再计算比较,如同8楼.
      当前时间与起始时间计算: 年*分钟数 + 月*分钟数 + 时*分钟数+分
    年分钟数应按一个回归年的时间计. 月分钟数查表.

使用特权

评论回复
17
音乐乐乐| | 2009-8-30 19:13 | 只看该作者
统一转换为秒计算嘛(好像是1977年开始的?),网上有现成的代码

使用特权

评论回复
18
gdmgb520|  楼主 | 2009-8-30 20:44 | 只看该作者
5# 冷漠
谢谢!
我是个新手,以前具体的项目基本没怎么做过,所以……,但是我也知道这个问题以前肯定有人做过,所以才来请教大家,一是让大家帮我看看我现在的思路能否实现,二是想听听大家对以前方法的介绍。

使用特权

评论回复
19
gdmgb520|  楼主 | 2009-8-30 20:49 | 只看该作者
8# zgl7903

谢谢!
您说的前两种思路,我也考虑过,但是仍然要判断这个时间点与原点的天数,还是要用到查表,所以这算做查表一类的。我正打算用查表的做。

使用特权

评论回复
20
gdmgb520|  楼主 | 2009-8-30 20:50 | 只看该作者
10# 有风


谢谢10楼,
你给的意见我再琢磨琢磨!

使用特权

评论回复
发新帖 我要提问
您需要登录后才可以回帖 登录 | 注册

本版积分规则

67

主题

452

帖子

1

粉丝