stm32f中能否用硬件定时器控制两个独立的进程

Can we control two independent processes with hardware timers in stm32f

我正在尝试为基于 STM32 的微控制器实现固件

两个任务,任务A和任务B都是相互独立的。是否可以在不同的时间实例生成中断,以便固件在到达时间后切换回任务 例如:taskA 应该每 500us 运行 一次,而 taskB 应该每 100us 运行 一次。我建议使用硬件定时器 (TIM),因为它们比操作系统的定时器更准确。你能帮忙吗?或者您有更好的主意吗?

每 100us 产生一次中断

每次中断都会给 TASKA 信号量、任务通知或在队列中放置一些东西

每五个中断给 TASKB 一个信号量、任务通知或在队列中放置一些东西

然后在中断请求结束时进行上下文切换。

另一种选择 - 使用软件定时器 https://www.freertos.org/FreeRTOS-Software-Timer-API-Functions.html

请记住,freeRTOS 中的进程不是 运行 并发的 - 您需要交还控制权以在它们之间切换(或在配置文件中为具有相同优先级的任务启用循环调度)。

编辑:这个答案假定不使用任何 RTOS,正如问题中没有提到的那样——忽略(可能不恰当!)set 标签。使用 RTOS,解决方案将有所不同!


taskA should run once every 500us, and taskB should run once every 100us

这听起来不像您实际上依赖于任务抢占,而不是您想要定期 运行 缩短任务。这可以非常简单地实现,甚至不需要中断:

  1. 将定时器配置为 运行 全范围(16 位计数器的 ARR 寄存器 = 0xffff)。
  2. 配置预分频器,使计数器每 us 增加一次(对于 80Mhz,这将是 80 的预分频器,您在 PSC 寄存器中少写入一个,即 79)。
  3. 照常启动定时器(CR1 寄存器中的 CEN 位)。

现在你只需测量时间:

uint16_t timestampA = timer->CNT - 500; // so that tasks will be run immediately
uint16_t timestampB = timer->CNT - 100;

for(;;) // main loop
{

    if(timer->CNT - timestampB > 100)
    {
        timestampB = timer->CNT;
        runTaskB();
    }
    if(timer->CNT - timestampA > 500)
    {
        timestampA = timer->CNT;
        runTaskA();
    }
}

因为示例任务B的频率是任务A频率的倍数,所以我先检查了任务B,所以任务A总是在任务B之后立即开始,所以不会偏离期望的周期(如果你反过来,任务B每5次启动都会延迟任务A的处理时间)。

如果这种情况无法避免(考虑 200 us 和 300 us),您可以添加额外的时移(如果您完全依赖这种精度):

uint16_t timestampA = timer->CNT - 200;
uint16_t timestampB = timer->CNT - (300 - 50);

当然,轮班时间应该比其他任务需要的时间长 运行。

旁注:无需关心溢出,无符号减法是稳健的,因为所有计算都是通过模 216.

完成的