软件PWM没有破坏CPU?

时间:2012-03-14 12:22:43

标签: c embedded pthreads gpio

这是一个学术问题(我不一定计划这样做),但我很好奇它是如何运作的。我正在考虑用户软件(而不是硬件)解决方案。

我想生成PWM信号(比如说,少数数字GPIO引脚,但超过1)。我可能会编写一个创建Pthread的程序,然后在该线程中使用适当的sleep() s等无限循环占空比,以使比例正确。

这不会破坏CPU的可怕性吗?我想这个频率大约在100赫兹左右。我之前没有做过这样的事情,但我可以想象,不断循环,上下文切换等对于多任务处理或CPU使用来说并不是很好。

在这种情况下,有关CPU的任何建议都使用和多任务处理? FWIW我想到的是单核处理器。我有一种感觉答案的范围可以从'这将使您的系统无法使用'所涉及的数字小于对数字产生影响的数量级一个现代化的处理器'

假设C因为它似乎最合适。

编辑:在可访问硬件GPIO引脚的机器上假设Linux或其他一般用途POSIX操作系统。

编辑:我曾经假设我将如何在睡眠时实现PWM。为避免疑问,可以这样:

while (TRUE)
{
    // Set all channels high
    for (int c = 0; x < NUM_CHANNELS)
    {
        set_gpio_pin(c, 1);
    }

    // Loop over units within duty cycle
    for (int x = 0; x < DUTY_CYCLE_UNITS; x++)
    {   
        // Set channels low when their number is up
        for (int c = 0; x < NUM_CHANNELS)
        {
            if (x > CHANNELS[c])
            {
                set_gpio_pin(c, 0);
            }
        }

        sleep(DUTY_CYCLE_UNIT);
    }
}

7 个答案:

答案 0 :(得分:2)

你没有非常清楚地说明这个的最终目的,但是既然你已经标记了这个嵌入式和pthreads,我将假设你有一个运行linux变体的专用芯片。

在这种情况下,我建议创建PWM输出的最佳方法是通过主程序循环,因为我认为PWM是更大控制应用程序的一部分。大多数简单的嵌入式应用程序(无UI)可以在单个线程中运行,并定期更新主线程中的GPIO。

例如:

InitIOs();

while(1)
{
   // Do stuff
   UpdatePWM();
}  

话虽如此,检查您的芯片规格,在大多数嵌入式设备中都有专用的PWM输出引脚(也可以作为GPIO),可以通过设置占空比并根据需要更新占空比,在硬件中简单配置这些引脚。 。在这种情况下,硬件将为您完成工作。

如果你能澄清一下你的情况,我可以给你一个更详细的答案。

答案 1 :(得分:2)

如果可以,请使用驱动程序。如果您的嵌入式设备有一个PWM控制器,那么很好,否则专用硬件定时器来产生PWM间隔并驱动GPIO引脚。

如果必须在用户级别执行此操作,将进程/线程提升到高优先级并使用sleep()调用肯定会产生大量抖动和较差的脉冲宽度范围。

答案 2 :(得分:1)

更好的方法可能是使用某种中断驱动的方法。我想这取决于你的系统,但IIRC Arduino使用PWM中断。

答案 3 :(得分:1)

100Hz似乎与用户空间相关。典型的OS任务调度程序时间片也大约为10ms,因此您的CPU在大约该时间间隔内已经是多任务处理。您可能希望使用高进程优先级(低漂亮度)来确保睡眠不会超出(多),并跟踪实际的墙壁时间并根据反馈调整您的睡眠值以避免漂移。您还需要确保内核在硬件上使用的计时器具有足够高的分辨率!

如果内存非常低并且交换频繁,则可能会遇到将程序分页到磁盘的问题。此外,如果内核正在执行其他CPU密集型操作,这也会引入不可接受的延迟。 (其他优先级较低的用户空间任务应该没问题)如果保持频率不变是至关重要的,那么最好在内核中解决这个问题(甚至运行实时内核)。

答案 4 :(得分:1)

使用线程并在不是RTOS的操作系统上休眠不会产生非常准确或一致的结果。

更好的方法是使用定时器中断并切换ISR中的GPIO。与在硬件定时器上使用硬件PWM输出不同,此方法允许您将单个定时器用于多个信号以及用于其他目的。您仍然可能会看到更多的抖动,硬件PWM以及实际频率范围和脉冲分辨率将远低于硬件可实现的值,但至少抖动将在几微秒而不是几毫秒的数量级。

答案 5 :(得分:1)

如果你有一个定时器,每次需要一个新的PWM边沿时,你可以设置一个定时器。通过一些巧妙的编码,您可以对它们进行排队,以便中断处理程序知道许多PWM通道中的哪一个以及是否需要高或低的边沿,然后为下一个所需的边缘安排自己。

如果你有足够的这些定时器,那么它更容易,因为你可以为每个PWM通道分配一个。

在具有低延迟中断响应的嵌入式控制器上,这可以产生令人惊讶的良好结果。

答案 6 :(得分:0)

我无法理解你为什么要在软件中进行PWM操作,其中包含中断服务和软件交互将引入的所有固有时序抖动(例如,当中断被禁用时,PWM中断命中,处理器正在为长期不间断指令提供服务,或其他服务例程处于活动状态)。大多数现代微控制器(ARM-7,ARM Cortex-M,AVR32,MSP,......)都有定时器,可配置为生成或专用为PWM发生器。这些将产生多个摇滚稳定的PWM信号,一旦建立,就需要零处理器输入以保持运行。根据应用的要求,可以配置这些PWM输出,使两个信号不重叠或同时具有边沿。

如果您依靠OS睡眠功能来设置PWM边沿之间的时间,那么这将运行缓慢。休眠功能将设置任务激活之间的最短时间,以及任务切换延迟这些时间之间的时间,存在更高优先级的线程或其他运行的内核函数。