Ich habe endlich ein vollständiges (ish) Verständnis von der bcm2835.h-Treiber-Header-Datei erhalten, also dachte ich, ich würde meine eigene Frage für andere posten und beantworten.
Die relevanten Bits aus dem Header:
PWM
Der BCM2835 unterstützt Hardware-PWM auf einer begrenzten Teilmenge von GPIO-Pins. Diese bcm2835-Bibliothek bietet Funktionen zum Konfigurieren und Steuern der PWM-Ausgabe an diesen Pins.
Der BCM2835 enthält 2 unabhängige PWM-Kanäle (0 und 1), von denen jeder mit einer begrenzten Teilmenge von GPIO-Pins verbunden ist. Die folgenden GPIO-Pins können mit den folgenden PWM-Kanälen verbunden werden:
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
Damit ein GPIO-Pin einen Ausgang von seinem PWM-Kanal ausgeben kann, muss er auf die oben angegebene Alt-Funktion eingestellt sein. Beachten Sie sorgfältig, dass aktuelle Versionen des Raspberry Pi nur einen dieser Pins (GPIO 18 = RPi-Pin 1-12) in den E / A-Headern freigeben. Daher ist dies der einzige E / A-Pin im RPi, der für PWM verwendet werden kann. Außerdem muss ALT FUN 5 eingestellt sein, um die PWM-Ausgabe zu erhalten.
Beide PWM-Kanäle werden von demselben PWM-Takt angesteuert, dessen Taktgeber mit variiert werden kann bcm2835_pwm_set_clock()
. Jeder Kanal kann separat mit aktiviert werden bcm2835_pwm_set_mode()
. Die durchschnittliche Ausgabe des PWM-Kanals wird durch das Verhältnis von DATA / RANGE für diesen Kanal bestimmt. Verwenden Sie bcm2835_pwm_set_range()
diese Option , um den Bereich und
bcm2835_pwm_set_data()
die Daten in diesem Verhältnis festzulegen
Jeder PWM-Kanal kann entweder im Balanced- oder im Mark-Space-Modus ausgeführt werden. Im symmetrischen Modus sendet die Hardware eine Kombination von Taktimpulsen, die insgesamt DATA-Impulse pro RANGE-Impulse ergibt. Im Mark-Space-Modus setzt die Hardware den Ausgang für DATA-Taktimpulse auf HIGH, gefolgt von LOW für RANGE-DATA-Taktimpulse.
Der PWM-Takt kann eingestellt werden, um die PWM-Impulsbreiten zu steuern. Der PWM-Takt wird von einem 19,2-MHz-Takt abgeleitet. Sie können jeden Teiler einstellen, aber einige gebräuchliche werden von der bereitgestelltbcm2835PWMClockDivider
Angenommen, Sie möchten einen Gleichstrommotor mit PWM bei etwa 1 kHz betreiben und die Drehzahl in Schritten von 1/1024 von 0/1024 (gestoppt) bis 1024/1024 (voll eingeschaltet) steuern. In diesem Fall können Sie den Taktteiler auf 16 und den BEREICH auf 1024 einstellen. Die Impulswiederholungsfrequenz beträgt 1,2 MHz / 1024 = 1171,875 Hz.
bcm2835PWMClockDivider
Gibt den Teiler an, der zum Generieren des PWM-Takts aus dem Systemtakt verwendet wird. Die folgenden Abbildungen geben den Teiler, die Taktperiode und die Taktfrequenz an. Die geteilte Taktung basiert auf der nominalen PWM-Basistaktrate von 19,2 MHz. Die für jeden Teiler angezeigten Frequenzen wurden durch Messung bestätigt
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;
Zusammenfassend:
Wenn Sie Hardware-PWM möchten - Sie stecken mit Pin 12 (BCM18) fest, verwenden andere GPIO-Pins Software-PWM.
Wahrscheinlich müssen Sie den PWM-Modus für die meisten Anwendungsfälle und aus Gründen der Vernunft wie oben beschrieben auf "Mark-Space" -Modus einstellen.
In diesem Modus wird die Dauer, in der jeder 'Impuls' HOCH gegen NIEDRIG ist, durch das Verhältnis der PWM-Daten zum PWM-Bereich bestimmt - dies ist unabhängig von der PWM-Taktrate.
Der PWM-Bereich ist effektiv die "Auflösung" oder Anzahl möglicher "Teilungen" jedes Impulses. Je mehr Teilungen vorhanden sind, desto höher ist die Auflösung und desto mehr Zustände können für eine bestimmte Impulsbreite codiert werden.
Das "Tastverhältnis" ist das Verhältnis von PWM-Daten zu PWM-Bereich, ausgedrückt als Prozentsatz. Ein PWM-Bereich von 10 mit PWM-Daten von 8 ist ein Arbeitszyklus von 80%.
Die PWM-Taktrate ist eine Potenz von zwei Teilern. Ihre gewählte Taktrate für PWM muss also sein, divisor & (divisor -1) == 0
obwohl die 12 gültigen Werte oben aufgeführt sind.
Das Teilen der PWM-Taktfrequenz durch die gewünschte Ausgangsfrequenz ergibt den Impulsbereichswert.
Da ich Audio codierte und einen Piezo-Echolot verwendete, benötigte ich ein Tastverhältnis von 50%, um die Piezo-Schwingung und damit die Lautstärke zu maximieren. Der PWM-Datenwert ist daher immer die Hälfte des PWM-Bereichswerts - 50% HIGH 50% LOW.
Um Ihre erforderliche Frequenz zu berechnen, wählen Sie einen Taktteiler, der für Ihre Anwendung sinnvoll ist - ich habe 16 gewählt, was 1,2 MHz entspricht. Damit:
Die Note von A ist 440 Hz, F # ist 370 Hz, C # ist 277 Hz
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;
Sie können den PWM-Bereich ganz einfach um ein Vielfaches nach oben und unten verschieben - Bereich * 2 verringert ihn um eine Oktave, Bereich * 0,5 erhöht ihn um eine Oktave.
Wenn Sie ein Servo mit beispielsweise 50 Hz fahren möchten, gilt dieselbe Bereichsberechnung:
PWM Range = PWM frequency / Desired Output Frequency
(Der maximale PWM-Bereichswert gemäß einigen Beiträgen beträgt anekdotisch 4096 - meiner Erfahrung nach trifft dies nicht zu, da das Spielen eines C # wie oben einen PWM-Bereich von 4332 ergibt, der wie erwartet funktioniert.)
Wie die meisten Dinge ist es einfach, wenn Sie wissen wie.
~ N.