J'ai finalement obtenu une compréhension complète (ish) du fichier d'en-tête du pilote bcm2835.h, alors j'ai pensé publier et répondre à ma propre question pour les autres.
Les bits pertinents de l'en-tête:
PWM
Le BCM2835 prend en charge le PWM matériel sur un sous-ensemble limité de broches GPIO. Cette bibliothèque bcm2835 fournit des fonctions pour configurer et contrôler la sortie PWM sur ces broches.
Le BCM2835 contient 2 canaux PWM indépendants (0 et 1), chacun étant connecté à un sous-ensemble limité de broches GPIO. Les broches GPIO suivantes peuvent être connectées aux canaux PWM suivants:
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
Pour qu'une broche GPIO émette une sortie de son canal PWM, elle doit être réglée sur la fonction Alt indiquée ci-dessus. Notez soigneusement que les versions actuelles du Raspberry Pi exposent uniquement l'une de ces broches (GPIO 18 = RPi Pin 1-12) sur les en-têtes IO, et c'est donc la seule broche IO du RPi qui peut être utilisée pour PWM. De plus, il doit être réglé sur ALT FUN 5 pour obtenir une sortie PWM.
Les deux canaux PWM sont pilotés par la même horloge PWM, dont l'horloge peut être modifiée à l'aide de bcm2835_pwm_set_clock()
. Chaque canal peut être activé séparément avec bcm2835_pwm_set_mode()
. La sortie moyenne du canal PWM est déterminée par le rapport DONNÉES / PLAGE pour ce canal. Utilisez bcm2835_pwm_set_range()
pour définir la plage et
bcm2835_pwm_set_data()
définir les données dans ce rapport
Chaque canal PWM peut fonctionner en mode symétrique ou Mark-Space. En mode équilibré, le matériel envoie une combinaison d'impulsions d'horloge qui se traduit par une impulsion de données globale par impulsions de plage. En mode Mark-Space, le matériel définit la sortie HIGH pour les impulsions d'horloge DATA large, suivie de LOW pour les impulsions d'horloge RANGE-DATA.
L'horloge PWM peut être réglée pour contrôler les largeurs d'impulsion PWM. L'horloge PWM est dérivée d'une horloge de 19,2 MHz. Vous pouvez définir n'importe quel séparateur, mais certains sont communs fournis par lebcm2835PWMClockDivider
Par exemple, supposons que vous vouliez piloter un moteur à courant continu avec PWM à environ 1 kHz et contrôler la vitesse par incréments de 1/1024 de 0/1024 (arrêté) à 1024/1024 (complètement activé). Dans ce cas, vous pouvez régler le diviseur d'horloge sur 16 et la plage sur 1024. La fréquence de répétition des impulsions sera de 1,2 MHz / 1024 = 1171,875 Hz.
bcm2835PWMClockDivider
Spécifie le diviseur utilisé pour générer l'horloge PWM à partir de l'horloge système. Les figures ci-dessous donnent le diviseur, la période d'horloge et la fréquence d'horloge. L'horloge divisée est basée sur une fréquence d'horloge de base PWM nominale de 19,2 MHz. Les fréquences affichées pour chaque diviseur ont été confirmées par mesure
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;
En résumé:
Si vous voulez du PWM matériel - vous êtes coincé avec la broche 12 (BCM18), les autres broches GPIO utiliseront le logiciel PWM.
Vous devrez probablement régler le mode PWM sur le mode 'Mark-Space' pour la plupart des cas d'utilisation et pour des raisons de raison comme décrit ci-dessus.
Dans ce mode, la durée pendant laquelle chaque «impulsion» est ÉLEVÉE par rapport à BASSE est déterminée par le rapport des données PWM à la plage PWM - ceci indépendamment de la vitesse d'horloge PWM.
La plage PWM est en fait la «résolution» ou le nombre de «divisions» possibles de chaque impulsion. Plus il y a de divisions, plus la résolution est élevée et donc plus d'états codables pour une largeur d'impulsion donnée.
Le «cycle de service» est le rapport des données PWM à la plage PWM exprimé en pourcentage. Une plage PWM de 10 avec des données PWM de 8 est un rapport cyclique de 80%.
La vitesse d'horloge PWM est une puissance de deux diviseurs. Votre vitesse d'horloge choisie pour PWM doit donc être divisor & (divisor -1) == 0
Bien que les 12 valeurs valides soient répertoriées ci-dessus.
La division de la fréquence d'horloge PWM par la fréquence de sortie souhaitée donne la valeur de la plage d'impulsions.
Comme j'encodais l'audio et que j'utilisais un sondeur piézo, j'avais besoin d'un rapport cyclique de 50% pour maximiser l'oscillation piézo et donc le volume. La valeur des données PWM est donc toujours la moitié de la valeur de la plage PWM - 50% HIGH 50% LOW.
Pour calculer votre fréquence requise, choisissez un diviseur d'horloge qui a du sens pour votre application - j'ai choisi 16, ce qui équivaut à 1,2 MHz. Donc:
La note de A est 440Hz, F # est 370Hz, C # est 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;
Vous pouvez facilement décaler la gamme PWM de haut en bas d'octaves par multiples - la plage * 2 la fera descendre d'une octave, la plage * 0,5 la fera monter d'une octave.
Si vous vouliez piloter un servo à 50 Hz par exemple, le même calcul de plage est vrai:
PWM Range = PWM frequency / Desired Output Frequency
(La valeur maximale de la plage PWM selon certains articles est anecdotique de 4096 - selon mon expérience, ce n'est pas vrai car jouer un C # comme ci-dessus donne une plage PWM de 4332 qui fonctionne comme prévu.)
Comme la plupart des choses - c'est facile quand on sait comment.
~ N