OpenEdv-开源电子网

 找回密码
 立即注册
正点原子全套STM32/Linux/FPGA开发资料,上千讲STM32视频教程免费下载...
查看: 3157|回复: 7

浮动定时,大家有经验么,阿mo有个帖子讲,可是没账号啊

[复制链接]

85

主题

378

帖子

0

精华

高级会员

Rank: 4

积分
902
金钱
902
注册时间
2013-4-29
在线时间
87 小时
发表于 2016-8-15 08:53:29 | 显示全部楼层 |阅读模式
11金钱
[size=18.6667px]整体的意思:
定时器只用一个,接口函数是设置硬件定时器和获得定时器运行剩余时间,还有就是定时中断会调用中断函数,资源就这么些,我们也要通过软件来虚拟定时器了。硬件定时器有相关的定时寄存器资源来设置定时时间和一些配置参数,用软件来模拟也需要定时时间和配置参数来描述这个定时器,这里我们用一个结构体来保存这些参数数据,其成员包括:定时器状态(空闲、激活、在使用、超时触发、周期触发)、全局结构体指针、回调函数指针(用于定时时间到后调用触发函数)、ID(用于标识定时器)、定时时间和定时周期(0表示非周期)


[size=18.6667px]http://www.amobbs.com/thread-5641423-1-1.html?_dsign=de7e3393 求助此贴具体内容

最佳答案

查看完整内容[请看2#楼]

1.getElapsedTime函数可以获得执行当时离上一次TimeDispatch被调用时的时间距(单位为us) 2.total_sleep_time变量用来保存如无意外,下一次TimeDispatch被调用的时间。如果有意外比如发生SetAlarm新增定时器时则用来判断,以便重新决定下一次TimeDispatch被调用的时间。
正点原子逻辑分析仪DL16劲爆上市
回复

使用道具 举报

85

主题

378

帖子

0

精华

高级会员

Rank: 4

积分
902
金钱
902
注册时间
2013-4-29
在线时间
87 小时
 楼主| 发表于 2016-8-15 08:53:30 | 显示全部楼层
1.getElapsedTime函数可以获得执行当时离上一次TimeDispatch被调用时的时间距(单位为us)
2.total_sleep_time变量用来保存如无意外,下一次TimeDispatch被调用的时间。如果有意外比如发生SetAlarm新增定时器时则用来判断,以便重新决定下一次TimeDispatch被调用的时间。
回复

使用道具 举报

58

主题

6294

帖子

1

精华

资深版主

Rank: 8Rank: 8

积分
11544
金钱
11544
注册时间
2014-4-1
在线时间
1315 小时
发表于 2016-8-15 09:22:02 | 显示全部楼层

说说你到底要实现什么具体功能。

回复

使用道具 举报

85

主题

378

帖子

0

精华

高级会员

Rank: 4

积分
902
金钱
902
注册时间
2013-4-29
在线时间
87 小时
 楼主| 发表于 2016-8-15 10:53:44 | 显示全部楼层
在 移植canfestival, 里边的 时间调度 移植不好,
回复

使用道具 举报

85

主题

378

帖子

0

精华

高级会员

Rank: 4

积分
902
金钱
902
注册时间
2013-4-29
在线时间
87 小时
 楼主| 发表于 2016-8-15 10:54:09 | 显示全部楼层
/*
This file is part of CanFestival, a library implementing CanOpen Stack.

Copyright (C): Edouard TISSERANT and Francis DUPIN

See COPYING file for copyrights details.

This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.

This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
Lesser General Public License for more details.

You should have received a copy of the GNU Lesser General Public
License along with this library; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
*/
/*!
** @file   timer.c
** @author Edouard TISSERANT and Francis DUPIN
** @date   Tue Jun  5 09:32:32 2007
**
** @brief
**
**
*/

/* #define DEBUG_WAR_CONSOLE_ON */
/* #define DEBUG_ERR_CONSOLE_ON */

#include <applicfg.h>
#include "timer_canfestival.h"

/*  ---------  The timer table --------- */
s_timer_entry timers[MAX_NB_TIMER] = {{TIMER_FREE, NULL, NULL, 0, 0, 0},};

TIMEVAL total_sleep_time = TIMEVAL_MAX;
TIMER_HANDLE last_timer_raw = -1;

#define min_val(a,b) ((a<b)?a:b)

/*!
** -------  Use this to declare a new alarm ------
**
** @param d
** @param id
** @param callback
** @param value
** @param period
**
** @return
**/
TIMER_HANDLE SetAlarm(CO_Data* d, UNS32 id, TimerCallback_t callback, TIMEVAL value, TIMEVAL period)
{
        TIMER_HANDLE row_number;
        s_timer_entry *row;

        /* in order to decide new timer setting we have to run over all timer rows */
        for(row_number=0, row=timers; row_number <= last_timer_raw + 1 && row_number < MAX_NB_TIMER; row_number++, row++)
        {
                if (callback &&         /* if something to store */
                   row->state == TIMER_FREE) /* and empty row */
                {        /* just store */
                        TIMEVAL real_timer_value;
                        TIMEVAL elapsed_time;

                        if (row_number == last_timer_raw + 1) last_timer_raw++;

                        elapsed_time = getElapsedTime();
                        /* set next wakeup alarm if new entry is sooner than others, or if it is alone */
                        real_timer_value = value;
                        real_timer_value = min_val(real_timer_value, TIMEVAL_MAX);

                        if (total_sleep_time > elapsed_time && total_sleep_time - elapsed_time > real_timer_value)
                        {
                                total_sleep_time = elapsed_time + real_timer_value;
                                setTimer(real_timer_value);
                        }
                        row->callback = callback;
                        row->d = d;
                        row->id = id;
                        row->val = value + elapsed_time;
                        row->interval = period;
                        row->state = TIMER_ARMED;
                        return row_number;
                }
        }

        return TIMER_NONE;
}

/*!
**  -----  Use this to remove an alarm ----
**
** @param handle
**
** @return
**/
TIMER_HANDLE DelAlarm(TIMER_HANDLE handle)
{
        /* Quick and dirty. system timer will continue to be trigged, but no action will be preformed. */
        MSG_WAR(0x3320, "DelAlarm. handle = ", handle);
        if(handle != TIMER_NONE)
        {
                if(handle == last_timer_raw)
                        last_timer_raw--;
                timers[handle].state = TIMER_FREE;
        }
        return TIMER_NONE;
}

/*!
** ------  TimeDispatch is called on each timer expiration ----
**
**/
int tdcount=0;
void TimeDispatch(void)
{
        TIMER_HANDLE i;
        TIMEVAL next_wakeup = TIMEVAL_MAX; /* used to compute when should normaly occur next wakeup */
        /* First run : change timer state depending on time */
        /* Get time since timer signal */
        UNS32 overrun = (UNS32)getElapsedTime();

        TIMEVAL real_total_sleep_time = total_sleep_time + overrun;

        s_timer_entry *row;

        for(i=0, row = timers; i <= last_timer_raw; i++, row++)
        {
                if (row->state & TIMER_ARMED) /* if row is active */
                {
                        if (row->val <= real_total_sleep_time) /* to be trigged */
                        {
                                if (!row->interval) /* if simply outdated */
                                {
                                        row->state = TIMER_TRIG; /* ask for trig */
                                }
                                else /* or period have expired */
                                {
                                        /* set val as interval, with 32 bit overrun correction, */
                                        /* modulo for 64 bit not available on all platforms     */
                                        row->val = row->interval - (overrun % (UNS32)row->interval);
                                        row->state = TIMER_TRIG_PERIOD; /* ask for trig, periodic */
                                        /* Check if this new timer value is the soonest */
                                        if(row->val < next_wakeup)
                                                next_wakeup = row->val;
                                }
                        }
                        else
                        {
                                /* Each armed timer value in decremented. */
                                row->val -= real_total_sleep_time;

                                /* Check if this new timer value is the soonest */
                                if(row->val < next_wakeup)
                                        next_wakeup = row->val;
                        }
                }
        }

        /* Remember how much time we should sleep. */
        total_sleep_time = next_wakeup;

        /* Set timer to soonest occurence */
        setTimer(next_wakeup);

        /* Then trig them or not. */
        for(i=0, row = timers; i<=last_timer_raw; i++, row++)
        {
                if (row->state & TIMER_TRIG)
                {
                        row->state &= ~TIMER_TRIG; /* reset trig state (will be free if not periodic) */
                        if(row->callback)
                                (*row->callback)(row->d, row->id); /* trig ! */
                }
        }
}
回复

使用道具 举报

85

主题

378

帖子

0

精华

高级会员

Rank: 4

积分
902
金钱
902
注册时间
2013-4-29
在线时间
87 小时
 楼主| 发表于 2016-8-15 10:54:34 | 显示全部楼层
canopen栈使用一个总共享定时器实体(Linux中使用一个posix定时器,单片机中使用一个定时器中断),定时触发TimeDispatch(void)执行:
扫描定时表 s_timer_entry timers[MAX_NB_TIMER]中的定时项,如果到时则执行它的callback函数,未到时则减少定时项时间参数。

结构定义:
struct struct_s_timer_entry {
     UNS8 state;
     CO_Data* d;
     TimerCallback_t callback; /* The callback func. */
     UNS32 id; /* The callback func. */
     TIMEVAL val;
     TIMEVAL interval; /* Periodicity */
};
回复

使用道具 举报

85

主题

378

帖子

0

精华

高级会员

Rank: 4

积分
902
金钱
902
注册时间
2013-4-29
在线时间
87 小时
 楼主| 发表于 2016-8-15 10:54:46 | 显示全部楼层
1.登记定时项
TIMER_HANDLE SetAlarm(CO_Data* d, UNS32 id, TimerCallback_t callback, TIMEVAL value, TIMEVAL period)
2.删除定时项
TIMER_HANDLE DelAlarm(TIMER_HANDLE handle)
3.总定时器关联函数(处理定时项数组 timers[MAX_NB_TIMER])
void TimeDispatch(void)
回复

使用道具 举报

58

主题

6294

帖子

1

精华

资深版主

Rank: 8Rank: 8

积分
11544
金钱
11544
注册时间
2014-4-1
在线时间
1315 小时
发表于 2016-8-15 11:16:17 | 显示全部楼层

抱歉不懂了,帮顶。
但总感觉没什么吧。。。

回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则



关闭

原子哥极力推荐上一条 /2 下一条

正点原子公众号

QQ|手机版|OpenEdv-开源电子网 ( 粤ICP备12000418号-1 )

GMT+8, 2025-6-7 11:40

Powered by OpenEdv-开源电子网

© 2001-2030 OpenEdv-开源电子网

快速回复 返回顶部 返回列表