这个问题,我想了一个春节(是我没表达清楚?)

[复制链接]
 楼主| yuntian 发表于 2008-2-13 15:20 | 显示全部楼层 |阅读模式
新年第一贴,先拜个年再说.

   问题比较简单,但是我想了一个春节也没有好的算法.
一个产品,需要判断两个时间是否相差在30分钟以内,因为单片机已经空间快用完了,所以是个非常头痛的问题,是PIC系列的,程序空间只剩下110字,两个时间包括年月日时分,因为两次时间不确定哪个一个快,哪一个慢,加上程序空间限制了,所以头大,单片机是用8脚的,这个类型的单片机好像没有超过2K程序空间的.
    比较有挑战的问题,哪个有好办**

问题等于是任意给定两个时间,判断这两个时间是否相差30分钟,(注意,括年月日时分5个参数)


再把问题说清楚一下:
就是系统是一个门禁,主机MCU程序空间有2K,每个ID卡都有独立时钟,门禁需要两个人都插入ID卡才能打开,再只有一个插卡口,所以只能一个人插卡后拔出来,另一个人再插卡,两次插卡时间不能超过30分钟,超过30分钟前一次插卡无效.
   再则,时钟不是主机产生的,是由每个ID插卡时发送自己的当前时间给主机判断,这点要注意.
   搞得我好像觉得自己智商很低,连减法都搞不定,另一个前提是程序空间只有110字,大程序装不下,否则这么简单搞不定我只能改行了.

xwj 发表于 2008-2-13 15:29 | 显示全部楼层

很简单啊,应该不用110字

ayb_ice 发表于 2008-2-13 15:31 | 显示全部楼层

110字节搞不定啊

可能也差不多,直接减吧,PICC的效率还是很高的。
HWM 发表于 2008-2-13 15:32 | 显示全部楼层

“减法”是一个有挑战的问题吗?

老狼 发表于 2008-2-13 16:48 | 显示全部楼层

很简单的。

第一个事件来的时候,启动定时计时,等第二个事件到来! 代码量应该够了。

或者第一个事件来的时候,用不断读取时钟信号的秒变位计数,如果精度允许一分钟-2分钟,就读取分钟变位计数,反正方法挺多。
3.3v 发表于 2008-2-13 18:28 | 显示全部楼层

计数

 楼主| yuntian 发表于 2008-2-13 18:45 | 显示全部楼层

没那么简单吧

因为两个时间是不确定的,比如第一个时间是2008-01-20 15:59,第二个时间是2004-02-29 16:01怎么比较他们是否相差30分钟?如果减法,我可以肯定的告你,代码绝对超过空间了.这还有润年的问题.
如果代码长度没有限制,我想很多人都很快搞定,问题是空间不够了,算法一定要想当精简,而且还会有时间换空间.
xwj 发表于 2008-2-13 19:00 | 显示全部楼层

唉.....

老狼 发表于 2008-2-13 20:54 | 显示全部楼层

我倒!

谈的元 发表于 2008-2-13 22:24 | 显示全部楼层

2008比2004大,就是差超过30分钟呀

先比较年,再比较月,。。。

楼主有什么问题呀?
程序匠人 发表于 2008-2-14 08:14 | 显示全部楼层

5楼老狼的方法似乎是正解

lz不会连RAM也用得一个不剩吧?
 楼主| yuntian 发表于 2008-2-14 09:17 | 显示全部楼层

原来写过一个,有漏洞

i=date.month;
    if(date.year>last_time.year)//年比较
        {i+=12;}
    if(i>last_time.month)//月比较
        {i=days_month[date.month&0x0f-1];
            if(date.month==1&&(date.year&0x03)==0)    //测试是否是润年
                {i++;}
            i+=date.day;
        }
    else{i=date.day;}
    if(i>last_time.day)//日比较
        {i=date.hour+24;}
    else{i=date.hour;}
    if(i>last_time.hour)//时比较
        {i=date.minute+60;}
    else{i=date.minute;}
    if(i>=last_time.minute)
        {i-=last_time.minute;
            if(i>30)//间隔超过30分?
                {return(1);}//超时返回=1
        }

就这个编译下来都超过100字了,
gyt 发表于 2008-2-17 13:43 | 显示全部楼层

楼主要改变原来的思考方法

采用新的思路
winds 发表于 2008-2-17 13:59 | 显示全部楼层

只要跳出原来的思路

另外建立个时间,比如定时器产生1分钟定时等,这样才有可能解决。
mikesullen 发表于 2008-2-18 01:32 | 显示全部楼层

看来楼主对单片机的理解不够

可能是只会用C语言来写
li_mu 发表于 2008-2-18 04:32 | 显示全部楼层

你这个程序如果优化一下(反汇编)能到多少?

原来写过一个,有漏洞

i=date.month;
    if(date.year>last_time.year)//年比较
        {i+=12;}
    if(i>last_time.month)//月比较
        {i=days_month[date.month&0x0f-1];
            if(date.month==1&&(date.year&0x03)==0)    //测试是否是润年
                {i++;}
            i+=date.day;
        }
    else{i=date.day;}
    if(i>last_time.day)//日比较
        {i=date.hour+24;}
    else{i=date.hour;}
    if(i>last_time.hour)//时比较
        {i=date.minute+60;}
    else{i=date.minute;}
    if(i>=last_time.minute)
        {i-=last_time.minute;
            if(i>30)//间隔超过30分?
                {return(1);}//超时返回=1
        }

就这个编译下来都超过100字了,
-----------------------------------
我怎么总觉得好像算法有些复杂了呢
fsaok 发表于 2008-2-18 06:43 | 显示全部楼层

pic

pic用结构类去写,肯定占用更多的空间
 楼主| yuntian 发表于 2008-2-18 10:54 | 显示全部楼层

找到一个好方法

经过多次更改思路,问题解决了,楼上仁兄说得不对,俺以前是用汇编写了四年的程序后来才改C的,现在的方法比较巧的,
就是写了两个子程序,一个是日期比较程序,即比较两个日期是否相等,这个用循环可以做到,入口是两上日期的指针.
另一个程序是日期程序,即从分钟开终判断,看是否超过60分,超过则小时进位,同理天,月,年也累加,若是润年,则2月为29天.
再用一个循环把分钟逐分钟加,也是用指针,每加一次,进行一次日期标准化调整.调整后,再判断两个日期是否相等,连加30分钟,如果两个时间相差在30分钟内,则30分连加一定有一次相等,先对时间1相加30分,再对时间2连加60分钟,只要有相等则退出,完整解了问题.各位看还有更好的方法不?
forthlab 发表于 2008-2-18 12:23 | 显示全部楼层

5楼的正解!

LZ的思维太僵化了!作茧自缚啊!
可惜了你的春节了,不如出去好好玩玩,放松一下,开拓一下.
 楼主| yuntian 发表于 2008-2-18 13:34 | 显示全部楼层

TO:forthlab兄,看看这个你就知道僵化不?

if(CARRY)
    {if(ZERO)//当前大于过去年则月份加12个月
            {i=date.month;}
        else{i=date.month+12;}
        i=i-last_time.month;
        if(CARRY)//当前月大于等于过去月?
        {if(ZERO)
            {i=date.day;}
            else
            {i=days_month[last_time.month&0x0f]+date.day;
                if(last_time.month==2&&(last_time.year&0x03)==0)
                {i++;}
            }
            i-=last_time.day;
            if(CARRY)
            {if(ZERO)
                {i=date.hour;}
                else{i=date.hour+24;}
                i-=last_time.hour;
                if(CARRY)
                {if(ZERO)
                    {i=date.minute;}
                    else{i=date.minute+60;}
                    i-=last_time.minute;
                    if(CARRY)
                    {if(i>30)return(1);}
                }
                else
                {}
            }
        }
您需要登录后才可以回帖 登录 | 注册

本版积分规则

29

主题

178

帖子

1

粉丝
快速回复 在线客服 返回列表 返回顶部