繁体   English   中英

我们可以在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,正如问题中没有提到的那样——忽略(可能不恰当)设置标签,使用 RTOS,解决方案看起来会有所不同!


taskA 应该每 500us 运行一次,taskB 应该每 100us 运行一次

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

  1. 将定时器配置为在全范围内运行(ARR 寄存器 = 16 位计数器的 0xffff)。
  2. 配置预分频器,使计数器每增加一次(对于 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 之后立即启动,因此不会出现与所需周期的偏差(如果您反向,每 5 次任务 B 的开始将被任务 A 的处理时间延迟)。

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

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

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

旁注:不需要关心溢出,无符号减法是稳健的,因为所有计算都是通过模 2 16完成的。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM