Saya akhirnya mendapatkan pemahaman lengkap (ish) dari file header driver bcm2835.h, jadi saya pikir saya akan memposting dan menjawab pertanyaan saya sendiri untuk orang lain.
Bit yang relevan dari header:
PWM
BCM2835 mendukung PWM perangkat keras pada subset pin GPIO yang terbatas. Pustaka bcm2835 ini menyediakan fungsi untuk mengkonfigurasi dan mengendalikan output PWM pada pin ini.
BCM2835 berisi 2 saluran PWM independen (0 dan 1), yang masing-masing dihubungkan ke subset terbatas pin GPIO. Pin GPIO berikut dapat dihubungkan ke saluran PWM berikut:
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
Agar pin GPIO memancarkan output dari saluran PWM, itu harus diatur ke Fungsi Alt yang diberikan di atas. Perhatikan baik-baik bahwa versi saat ini dari Raspberry Pi hanya memperlihatkan salah satu dari pin ini (GPIO 18 = RPi Pin 1-12) pada header IO, dan oleh karena itu ini adalah satu-satunya pin IO pada RPi yang dapat digunakan untuk PWM. Selanjutnya harus diatur ke ALT FUN 5 untuk mendapatkan output PWM.
Kedua saluran PWM digerakkan oleh clock PWM yang sama, yang clock-dvider-nya dapat divariasikan menggunakan bcm2835_pwm_set_clock()
. Setiap saluran dapat diaktifkan secara terpisah bcm2835_pwm_set_mode()
. Output rata-rata saluran PWM ditentukan oleh rasio DATA / RANGE untuk saluran itu. Gunakan bcm2835_pwm_set_range()
untuk mengatur rentang dan
bcm2835_pwm_set_data()
untuk mengatur data dalam rasio itu
Setiap saluran PWM dapat berjalan dalam mode Balanced atau Mark-Space. Dalam mode Seimbang, perangkat keras mengirimkan kombinasi pulsa clock yang menghasilkan pulsa DATA keseluruhan per pulsa RANGE. Dalam mode Mark-Space, perangkat keras mengatur output TINGGI untuk lebar pulsa clock DATA, diikuti oleh RENDAH untuk pulsa clock RANGE-DATA.
Jam PWM dapat diatur untuk mengontrol lebar pulsa PWM. Jam PWM berasal dari jam 19.2MHz. Anda dapat mengatur pembagi apa pun, tetapi beberapa pembagi umum disediakan olehbcm2835PWMClockDivider
Misalnya, Anda ingin mengendarai motor DC dengan PWM sekitar 1kHz, dan mengontrol kecepatan kenaikan 1/1024 dari 0/1024 (berhenti) hingga 1024/1024 (penuh). Dalam hal ini Anda dapat mengatur pembagi jam menjadi 16, dan RANGE ke 1024. Frekuensi pengulangan pulsa akan menjadi 1.2MHz / 1024 = 1171.875Hz.
bcm2835PWMClockDivider
Menentukan pembagi yang digunakan untuk menghasilkan jam PWM dari jam sistem. Gambar di bawah ini menunjukkan pembagi, periode jam, dan frekuensi jam. Jam dibagi berdasarkan tingkat clock dasar PWM nominal 19,2MHz. Frekuensi yang ditunjukkan untuk setiap pembagi telah dikonfirmasi oleh pengukuran
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;
Singkatnya:
Jika Anda menginginkan perangkat keras PWM - Anda terjebak dengan pin 12 (BCM18), pin GPIO lainnya akan menggunakan perangkat lunak PWM.
Anda mungkin perlu mengatur mode PWM ke mode 'Mark-Space' untuk kebanyakan kasus penggunaan dan alasan kewarasan seperti dijelaskan di atas.
Dalam mode ini, durasi setiap 'pulsa' adalah TINGGI vs RENDAH ditentukan oleh rasio data PWM dengan rentang PWM - ini terlepas dari kecepatan clock PWM.
Rentang PWM secara efektif adalah 'resolusi' atau jumlah 'divisi' yang mungkin dari setiap pulsa. Semakin banyak pembagian semakin tinggi resolusinya dan dengan demikian semakin banyak negara yang disandikan untuk lebar pulsa yang diberikan.
'Siklus tugas' adalah rasio data PWM dengan rentang PWM yang dinyatakan sebagai persentase. Rentang PWM 10 dengan data PWM 8 adalah siklus tugas 80%.
Kecepatan clock PWM adalah kekuatan dua pembagi. Jadi kecepatan clock yang Anda pilih untuk PWM harus divisor & (divisor -1) == 0
Meskipun nilai-nilai yang valid tercantum di atas.
Membagi frekuensi clock PWM dengan frekuensi output yang diinginkan memberikan nilai rentang pulsa.
Ketika saya sedang encoding audio dan menggunakan sounder piezo saya membutuhkan siklus tugas 50% untuk memaksimalkan osilasi piezo dan volume. Nilai data PWM karenanya selalu setengah dari nilai kisaran PWM - 50% TINGGI 50% RENDAH.
Untuk menghitung frekuensi yang diperlukan, pilih pembagi jam yang masuk akal untuk aplikasi Anda - saya memilih 16, yang setara dengan 1.2Mhz. Begitu:
Nada A adalah 440Hz, F # adalah 370Hz, C # adalah 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;
Anda dapat dengan mudah menggeser rentang PWM naik dan turun oktaf dalam beberapa - rentang * 2 akan menurunkan satu oktaf, kisaran * 0,5 akan mengambilnya satu.
Jika Anda ingin mengendarai servo di katakan 50Hz perhitungan rentang yang sama berlaku:
PWM Range = PWM frequency / Desired Output Frequency
(Nilai kisaran PWM maksimum menurut beberapa posting secara anekdot adalah 4096 - dalam pengalaman saya ini tidak benar dalam memainkan C # seperti di atas memberikan rentang PWM 4332 yang berfungsi seperti yang diharapkan.)
Seperti kebanyakan hal - mudah ketika Anda tahu caranya.
~ N