3

是否可以更改重复计时器的周期(在 TimerFcn 中)?

直观地说,在为 Windows 编程时,我会处理 WM_TIMER 消息并使用 SetTimer 来编辑定时器的周期,但类似的方法在 MATLAB 中似乎不起作用,因为需要重新启动定时器才能更改 Period 属性. 这会扰乱执行,最好将其描述为将周期更改为接近零。不会产生错误。

下面是一些用于创建任务数组的示例代码:每个任务项都由要做的事情和延迟组成。该数组基本上是由一个计时器遍历的,它应该根据当前的任务延迟来改变它的周期。

function obj = Scheduler(~)
    obj.scheduletimer = timer(...
        'TimerFcn',@obj.OnTimer,...
        'BusyMode','queue',...
        'TasksToExecute',length(obj.tasklist),...
        'ExecutionMode','fixedRate');
end
function OnTimer(obj,source,event)
    obj.Start(); // Executed task, schedule next
end
function Start(obj)

    // Stop timer if needed
    if(strcmp(obj.scheduletimer.Running,'on'))
        stop(obj.scheduletimer);
    end;

    // Set new period and resume
    if(~isempty(obj.tasklist))
        obj.scheduletimer.Period = obj.tasklist(1).something;
        start(obj.scheduletimer);
    end;
end

当我不弄乱 OnTimer 中的计时器时,一切显然都可以正常工作,但我想在每次迭代时更改 Period。

编辑:我尝试实施 Pursuit 建议的 pingpong 解决方案,但仍然无法正常工作。请注意,切换计时器的想法确实有效,但似乎仍然没有应用周期。

function obj = Scheduler(~)
    obj.timer1 = timer(...
        'TimerFcn',@obj.OnTimer);
     obj.timer2 = timer(...
        'TimerFcn',@obj.OnTimer);
end
function OnTimer(obj,source,event)
    obj.Start(); // Executed task, schedule next
end
function Start(obj)
    if(strcmp(obj.timer1.Running,'on'))
        obj.timer2.Period = obj.tasklist{1}{2};
        start(obj.timer2);
    else
        obj.timer1.Period = obj.tasklist{1}{2};
        start(obj.timer1);
    end;
end

啊。

4

2 回答 2

3

使用两个计时器,(例如timerNamePingtimerNamePong)。在每个计时器的动作结束时,设置下一个计时器以单次模式执行一次,并有一些延迟。

这避免了不断拆除和创建新计时器的需要,并避免了当您尝试编辑当前正在执行的计时器时发生的错误。

这是一个演示的工作示例:

function setupPingPong

timerPing = timer;
timerPong = timer;

timerPing.TimerFcn = @(~,~)pingPongActivity(true,  timerPing, timerPong);
timerPing.Name = 'PingTimer';

timerPong.TimerFcn = @(~,~)pingPongActivity(false, timerPing, timerPong);
timerPong.Name = 'PongTimer';

timerPing.StartDelay = 0;
start(timerPing);

function pingPongActivity(isPing, timerPing, timerPong)
    if isPing
        disp(['PING (' datestr(now,'yyyy-mm-dd HH:MM:SS.FFF') ')'])
    else
        disp(['PONG (' datestr(now,'yyyy-mm-dd HH:MM:SS.FFF') ')'])
    end
    delayTime = ceil(rand*10);
    display(['    delaying '  num2str(delayTime) ' sec.'])
    if isPing
        nextTimer = timerPong;
    else
        nextTimer = timerPing;
    end
    set(nextTimer,'StartDelay', delayTime);
    start(nextTimer);

一旦发生这种情况,为了停止疯狂,我使用:

t = timerfind; stop(t); delete(t)
于 2013-03-22T19:04:15.677 回答
1

我再次使用计时器对象中的“StopFcn”属性来重新启动计数器。

像这样的东西('TimerScale' 改变下一个时期)

在里面 :

Timer_OBJ = timer(  'ExecutionMode', 'singleShot', ...
                                    'StartDelay', SystemTicksSecs/TimerScale, ...
                                    'TimerFcn', @(src,evt)obj.TimerCallBack,...
                                    'StopFcn', @(src,evt)obj.TimerStopCallBack );

                start(Timer_OBJ);

在 TimerStopCallBack 里面

  set(Timer_OBJ, 'StartDelay', SystemTicksSecs/TimerScale);                

    start(Timer_OBJ);
于 2016-05-31T06:44:15.263 回答