多个计时器或多个计数器的单个任务?

时间:2017-05-18 11:54:06

标签: arduino embedded stm32

假设你有一些函数必须在不同的时间点被调用,但是连续的(每个250毫秒,每个2秒,每个5分钟)的常量任务。 使用专用于任务的4-5个定时器或者更好地编写较小任务中的所有内容然后使用计数器变量来运行其他函数是否更好?

e.g。

//callback each 250ms
void 250ms_TASK(){
    if (counter % 8 != 0){ //250ms*8 = 2s
        return;
    }

    // do 2 sec stuff

    if (counter != 4800){ //250ms*4800 = 20min
        return;
    }
    //do 20min stuff
    counter = 0;
}

假设你想要避免/防范这样的情况:

  • 在做2秒之前你必须确保计算出第8个250ms的任务。

  • 在做20分钟之前你必须确保计算出第4800个250毫秒和第600个2s任务。

这个问题与最佳实践和表现有关。

此外,最好在回调中执行这些计算还是使用回调来修改标志并在主循环中执行计算?

5 个答案:

答案 0 :(得分:0)

我假设您使用STM32,因为您标记了STM32。

除非您的应用程序非常重要,否则您需要使用抢占式和异步式计时器中断(例如,5分钟任务非常重要,所以即使在 >一个分开的250ms回调任务正在运行),使用多个定时器中断只是浪费定时器,你需要使用尽可能少的中断恕我直言。计算变量并不昂贵,所以可以这样做。

真正的考虑因素是任务的长度。 ISR应该尽可能短,所以如果定时器回调任务很长,你应该使用标志并在主循环中使用轮询操作。轮询标志更为可取,尤其是在单个计时器ISR中使用多个回调时。想象一下,应该在ISR中调用250ms,2s和20min的回调,ISR将比平常花费3倍。

顺便说一句,如果您决定使用单个计时器,为什么不使用SysTick? SysTick定时器在每个Cortex M MCU中提供,其操作在MCU系列中是相同的。您可以非常轻松地将其配置为1ms中断计时器。至于你在主循环中使用轮询1ms中断必须没问题。 Systick有很多教程(例如,part1part2

答案 1 :(得分:0)

对于非时间关键的任务执行此操作的标准方法是实现单个计时器,每毫秒触发一次。

然后该计时器通过一个已注册的“软件计时器”列表,并检查是否该时间被执行。如果是,则计时器调用包含特定于计时器的代码的函数指针。也就是说,计时器驱动程序调用的回调函数。

如果这些功能保持最小,例如只设置一个标志,你可以从主计时器ISR执行它们。

答案 2 :(得分:0)

这里没有正确的答案,最佳实践是实施设计以满足要求,因为项目的要求因项目而异,没有单一的正确答案。一种常见的解决方案将无法适用于各种产品,另一种常见解决方案也是如此。您可以强制使用一个解决方案,但这可能会增加许多被黑客攻击的创可贴,只会增加项目的风险,可能导致失败和/或召回或现场升级,这些都是使产品和公司看起来不好的必要条件。做你的系统工程,大多数情况下,正确的解决方案只是出现在自己身上,不做你的系统工程,故障就会出现。

答案 3 :(得分:0)

您可以就功耗和实时定时器要求提出各种论点。这真的取决于你的应用程序。但是这些问题可以为初学者,甚至更有经验的开发人员提供富有洞察力的答案。此处的关键字为 scheduling

我更喜欢的典型设置,裸机实时:

  • Main运行所有低优先级和空闲任务。主要基于每1毫秒勾选的systick计时器的这些时间:if( (now - then) > delay ){ then = now; foo(); }
    除关键区域(使用ISR线程空间数据时)外,所有内容都可以中断这些任务。 低优先级任务是闪烁LED和处理通信。
  • 有外设中断和定时器设置IRQ挂起位,以便发出实时工作信号。例如:在溢出之前读取uart或adc寄存器。
  • 设置中断优先级和定时器的方式是在正确的时间以正确的顺序完成工作。例如:处理ADC采样时,硬件报警IRQ到达时,会立即处理。

这样我就可以处理DMA信号样本,而较低频率的同步定时器为过程循环设置IRQ待定。过程循环必须在样本之后运行,因此在NVIC中具有较低的优先级。

优势:当通讯渠道溢出数据时,不会妨碍实时性能。
缺点: cpu永远不会长时间睡觉 ISR的实时任务可能不会超过其时间窗口。这是Windowed Watchdog Timers非常有用的地方。此外,空闲任务只会在有空余时间运行。他们可能会迟到。

此处类似的选项是使用实时操作系统。就像ChibiOS一样。

但是,当您使用电池时,您不希望MCU每秒唤醒。您希望MCU仅在必须完成工作时唤醒。你可以用两种方式做到这一点。

  1. 多个硬件定时器发出唤醒事件的信号 这需要多个计时器继续运行,并且可能仍然会消耗太多能量。

  2. 无人值守操作。您使用一个计时器,芯片唤醒并在到达时间时工作。然后重新加载计时器与下一个截止日期的时间比较。如果您的间隔时间足够长,您可以使用RTC来实现超低功耗。

  3. 优势:根据工作量,芯片可以长时间进入睡眠状态 缺点:设计实现和调试要复杂一些。

    此处类似的选项是使用无滴答操作系统。

答案 4 :(得分:0)

假设您没有使用实时操作系统,我会使用计时器来执行时间关键的事情(如果它用几个时钟周期处理)和长计时器计数器通过中断并且在主循环中使用非时间关键的东西和更长的时间段(有或没有看门狗定时器/睡眠)。

中断会中断主循环内容,因此您可以确保在需要时发生时间关键的事情,关键时刻发生的事情就越少。

您可以在主循环中使用状态机来执行逻辑操作,以确保所有操作都以正确的顺序完成,检查,加载,读取传感器等等。