嵌入式软件之定时器的设计
嵌入式软件之定时器的设计
爱吃冰红茶 发表于4年前
嵌入式软件之定时器的设计
  • 发表于 4年前
  • 阅读 180
  • 收藏 5
  • 点赞 0
  • 评论 0

【腾讯云】买域名送云解析+SSL证书+建站!>>>   

这是真正意义上的第一篇自己写的博客,以前的都是copy的,后来发现这有很多弊病,所以果断全部给delete了!

不说废话了,正式开始!

前段时间,跟着项目做智能家居里的一部分工作,里面有写一个定时器,今天就专门来说说这个!

一说到定时器,估计很多人都第一个想到的是用alarm来做,这个是没问题的,我最初所用的方法也是用的是alarm,但是由于项目要求是在一个进程内控制多个设备的定时开关机(我设计的是16个),于是用alarm就会觉得力有不逮了!

先来看看用alarm吧!一个进程只能有一个 闹钟时间,如果在调用alarm之前已设置过闹钟时间,则任何以前的闹钟时间都被新值所代替。在最初用alarm时,我是先写一个控制设备开关机的函数 setPowerOnOff,然后当alarm的时间到了之后,系统会发出一个SIGALRM信号,我再用调用signal函数,使得系统接收到这个信号 时就调用setPowerOnOff函数,但是问题出来了,当我alarm倒计时还没结束时,我再次设置定时开关机,假设刚才设置的是1号机,现在我设置 2号机,那么系统就会清除之前的1号机alarm,而采用2号机的定时时间重新alarm,那么一号机就被这样被抛弃了!

于是换了个方法,通过开辟一个线程来维护一个结构体:

我先声明一个结构体:

typedef struct intervaltime
{
    int hour;
    int min;
    int sec;
}IntervalTime;                                      //时间格式

typedef struct Timing
{
    int devid[16];                               //16台设备的id
    IntervalTime timeOn[16];             //定时开机时间
    IntervalTime timeOff[16];             //定时关机时间
    int OnState[16];                           //定时开机状态位
    int OffState[16];                           //定时关机状态位
}timing;

在维护这个结构体之前,我们还需要写一个获取当前系统时间的函数,代码如下:

struct tm *ipp_sac_getNowTime()
{
    time_t rawtime;
    struct tm *systime;
    time(&rawtime);
    systime = localtime(&rawtime);
    return systime;
}

前面两部分代码都很简单,也就不多说什么了。

在声明结构体时,我们可以看到,此定时器只是需要时、分、秒,其余的天,月什么的 我们都没去考虑,当然如果说非要用的话,也不是什么难事。我的方法是比较传统的方法,通过比较当前系统时间和设置的定时时间是否相等,以及相应的开关机状 态位,来判断在什么时候执行什么样的操作。在我跟的这个项目里,用户端发送的是一个倒计时给我,所以我需要先将这个倒计时转化为一个我们平时所看到的系统 时间的格式:

struct tm *timeinfo;
    timeinfo = ipp_sac_getNowTime();
        static timing TimingPowerOnOff;

    //当前系统时间加上设置的定时关机时间,即为系统将要执行关机动作的时间。
    TimingPowerOnOff.devid[deviceid] = deviceid;
    TimingPowerOnOff.timeOff[deviceid].hour = timeinfo->tm_hour + time.hour;
    TimingPowerOnOff.timeOff[deviceid].min = timeinfo->tm_min + time.minute;
    TimingPowerOnOff.timeOff[deviceid].sec = timeinfo->tm_sec + time.sec;
        //当时,分达到24和60时,则需要如下的处理:
    if(TimingPowerOnOff.timeOff[deviceid].min > 59)
    {
        TimingPowerOnOff.timeOff[deviceid].min = TimingPowerOnOff.timeOff[deviceid].min - 60;
        TimingPowerOnOff.timeOff[deviceid].hour = TimingPowerOnOff.timeOff[deviceid].hour + 1;
    }

    if(TimingPowerOnOff.timeOff[deviceid].hour > 23)
    {
        TimingPowerOnOff.timeOff[deviceid].hour = TimingPowerOnOff.timeOff[deviceid].hour - 24;
    }

时间处理好了,接下来我们就只需要判断当前时间是否等于设置的时间就行了,以前设置的是定时开机还是定时关机,设置定时开关机状态就是0和1的问题,就不多说了。

while(1)
    {
        int tmp;
        struct tm *nowTimeInfo;
        nowTimeInfo = ipp_sac_getNowTime();

        for(tmp = 0;tmp < 16;tmp++)
        {
            if(TimingPowerOnOff.timeOff[tmp].hour ==  nowTimeInfo->tm_hour && TimingPowerOnOff.timeOff[tmp].min == nowTimeInfo->tm_min)
            {
                if(TimingPowerOnOff.OffState[tmp] == 1)
                {
                    mcu_sac_setPower(tmp,POWER_OFF);     //mcu_sac_setPower即为触发设备开关机的函数,此处就不列代码了。POWER_OFF = 1;
                    TimingPowerOnOff.OffState[tmp] = 0;
                }
            }

            if(TimingPowerOnOff.timeOn[tmp].hour ==  nowTimeInfo->tm_hour && TimingPowerOnOff.timeOn[tmp].min == nowTimeInfo->tm_min)
            {
                if(TimingPowerOnOff.OnState[tmp] == 1)
                {
                    mcu_sac_setPower(tmp,POWER_ON);  //POWER_ON = 0;
                    TimingPowerOnOff.OnState[tmp] = 0;
                }
            }
        }
        sleep(60);                 //虽然我声明的时间类型的有秒,但是实际项目里我没用到,所以这里就加了个sleep(60),让它每隔一分钟循环一次。
    }

到这里,定时器就设计好了,但是同时值得注意的是,我是开辟了一个线程来做定时器这个功能的,只是代码里我没有把那部分给列举出来而已;当然,如果整个进程只是跑一个定时器,线程神马的就可以不用了,这看个人喜好啦!

第一篇博客就算搞定啦,虽然定时器这个很简单,我说的估计也不仔细,但是不积跬步无以至千里,一切慢慢来吧!


  • 打赏
  • 点赞
  • 收藏
  • 分享
共有 人打赏支持
粉丝 2
博文 4
码字总数 4471
×
爱吃冰红茶
如果觉得我的文章对您有用,请随意打赏。您的支持将鼓励我继续创作!
* 金额(元)
¥1 ¥5 ¥10 ¥20 其他金额
打赏人
留言
* 支付类型
微信扫码支付
打赏金额:
已支付成功
打赏金额: