驱动PWM输出频率


8

经过数小时无能为力的搜索和阅读,我仍然不完全了解如何以及为什么不使用其他人的“黑匣子”从RPi上的硬件PWM引脚输出特定频率。

关于具体细节以及使用的各种术语,似乎有很多不准确或不完整的信息-“时钟分频器”,“占空比”,“ PWM范围”和PWM数据本身,以及它们之间的关系一起输出特定的频率-就我而言,是将特定的音频频率驱动到压电发声器之外。

Answers:


14

我终于从bcm2835.h驱动程序头文件中获得了一个完整的理解,因此以为我会为他人发布并回答我自己的问题。

标头中的相关位:

脉宽调制

BCM2835在GPIO引脚的有限子集上支持硬件PWM。该bcm2835库提供了用于配置和控制这些引脚上的PWM输出的功能。

BCM2835包含2个独立的PWM通道(0和1),每个通道都连接到GPIO引脚的有限子集。以下GPIO引脚可以连接到以下PWM通道:

  GPIO PIN    RPi pin  PWM Channel    ALT FUN
  12                    0             0
  13                    1             0
  18          1-12      0             5
  19                    1             5
  40                    0             0
  41                    1             0
  45                    1             0
  52                    0             1
  53                    1             1

为了使GPIO引脚从其PWM通道发出输出,必须将其设置为上面给出的Alt功能。请注意,当前版本的Raspberry Pi仅在IO接头连接器上暴露这些引脚之一(GPIO 18 = RPi引脚1-12),因此这是RPi上唯一可用于PWM的IO引脚。此外,必须将其设置为ALT FUN 5以获得PWM输出。

两个PWM通道均由相同的PWM时钟驱动,可使用改变其时钟分频器bcm2835_pwm_set_clock()。每个通道可以通过分别启用bcm2835_pwm_set_mode()。PWM通道的平均输出由该通道的DATA / RANGE之比确定。使用bcm2835_pwm_set_range()设置的范围内, bcm2835_pwm_set_data()在该比率设置数据

每个PWM通道均可在平衡或标记空间模式下运行。在平衡模式下,硬件发送时钟脉冲的组合,从而导致每个RANGE脉冲总的DATA脉冲。在Mark-Space模式下,硬件将DATA时钟脉冲的输出设置为高电平,然后将RANGE-DATA时钟脉冲的输出设置为低电平。

可以设置PWM时钟来控制PWM脉冲宽度。PWM时钟源自19.2MHz时钟。您可以设置任何分频器,但是一些常用的分频器由bcm2835PWMClockDivider

例如,假设您想用大约1kHz的PWM驱动直流电动机,并以1/1024的增量控制速度,从0/1024(停止)到1024/1024(全开)。在这种情况下,您可以将时钟分频器设置为16,将RANGE设置为1024。脉冲重复频率将为1.2MHz / 1024 = 1171.875Hz。

bcm2835PWMClockDivider指定用于从系统时钟生成PWM时钟的分频器。下图给出了分频器,时钟周期和时钟频率。时钟分频基于19.2MHz的标称PWM基本时钟速率。每个分频器显示的频率已通过测量确认

typedef enum
{
    BCM2835_PWM_CLOCK_DIVIDER_2048  = 2048,    /*!< 2048 = 9.375kHz */
    BCM2835_PWM_CLOCK_DIVIDER_1024  = 1024,    /*!< 1024 = 18.75kHz */
    BCM2835_PWM_CLOCK_DIVIDER_512   = 512,     /*!< 512 = 37.5kHz */
    BCM2835_PWM_CLOCK_DIVIDER_256   = 256,     /*!< 256 = 75kHz */
    BCM2835_PWM_CLOCK_DIVIDER_128   = 128,     /*!< 128 = 150kHz */
    BCM2835_PWM_CLOCK_DIVIDER_64    = 64,      /*!< 64 = 300kHz */
    BCM2835_PWM_CLOCK_DIVIDER_32    = 32,      /*!< 32 = 600.0kHz */
    BCM2835_PWM_CLOCK_DIVIDER_16    = 16,      /*!< 16 = 1.2MHz */
    BCM2835_PWM_CLOCK_DIVIDER_8     = 8,       /*!< 8 = 2.4MHz */
    BCM2835_PWM_CLOCK_DIVIDER_4     = 4,       /*!< 4 = 4.8MHz */
    BCM2835_PWM_CLOCK_DIVIDER_2     = 2,       /*!< 2 = 9.6MHz, fastest you can get */
    BCM2835_PWM_CLOCK_DIVIDER_1     = 1        /*!< 1 = 4.6875kHz, same as divider 4096 */
} bcm2835PWMClockDivider;

综上所述:

  1. 如果您需要硬件PWM,则必须固定在引脚12(BCM18)上,其他GPIO引脚将使用软件PWM。

  2. 如上所述,出于大多数使用情况和理智的原因,您可能需要将PWM模式设置为“标记空间”模式。

  3. 在此模式下,每个“脉冲”的持续时间为高电平与低电平的时间取决于PWM数据与PWM范围的比值,这与PWM时钟速度无关。

  4. PWM范围实际上是每个脉冲的“分辨率”或可能的“分度”数。除法越多,分辨率越高,因此对于给定的脉冲宽度,可编码的状态越多。

  5. “占空比”是PWM数据与PWM范围的比率,以百分比表示。PWM数据为8时,PWM范围为10,占空比为80%。

  6. PWM时钟速度是两个除数的幂。因此,您为PWM选择的时钟速度必须为。divisor & (divisor -1) == 0尽管上面列出了12个有效值。

  7. 将PWM时钟频率除以所需的输出频率可得出脉冲范围值。

  8. 当我编码音频并使用压电发声器时,我需要50%的占空比,以使压电振荡和音量最大化。因此,PWM数据值始终为PWM范围值的一半-高50%低50%。

要计算所需的频率,请选择适合您的应用的时钟分频器-我选择了16,等于1.2Mhz。所以:

A的音符为440Hz,F#为370Hz,C#为277Hz

PWMClock = 16; // 1.2Mhz

const A4_RANGE = 1.2e6 / 440;  // 1.2Mhz/440Hz
A4Data = A4_RANGE / 2;

const F4S_RANGE = 1.2e6 / 370;  // 1.2Mhz/370Hz
F4SData = F4S_RANGE / 2;

const C4S_RANGE = 1.2e6 / 277;  // 1.2Mhz/277Hz
C4SData = C4S_RANGE / 2;

您可以轻松地将PWM范围的倍数上下移动八度-范围* 2将其降低八度,范围* 0.5将其降低一个八度。

如果要以50Hz的频率驱动伺服器,则相同的范围计算适用:

PWM Range = PWM frequency / Desired Output Frequency

(根据一些帖子,最大PWM范围值是4096,根据我的经验,这不是正确的,因为如上所述玩C#时,PWM范围为4332,可以正常工作。)

像大多数事情一样-当您知道如何时,这很容易。

〜N


3
请注意,“仅12针”位适用于26针型号。40针型号有三个(13、18和19),但是仍然只有2个时钟通道,并且针与另一个针具有硬线关联(针12和18是通道0,13和19是通道) 1); 按照上面引用的文档libbcm2835,您可以配置两个通道和所有四个引脚。每个引脚的ALT功能不同。此处有一张表,其中很多直接从Broadcom SoC数据表中提取。划掉的条目仅适用于40针型号。
goldilocks

7

在最新的Pis(具有40针扩展头和计算模块的Pis)上,GPIO 12/13/18/19可用于提供硬件PWM信号。

PWM时钟源不必是19.2MHz的晶体,piggio使用500MHz的PLLD。

有关设置硬件PWM频率的简单命令行方法,请参见http://abyz.me.uk/rpi/pigpio/pigs.html#HP

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.