LoginSignup
0
1

More than 3 years have passed since last update.

初めてのRaspberry Pi Pico ㉗ C言語 PWM その3

Posted at

 PWMの周波数設定がわかりにくかったので、整理します。


// Output PWM signals on pins 2 and 3

#include "pico/stdlib.h"
#include "hardware/pwm.h"
#include <stdio.h>
#include "hardware/clocks.h"
#include <math.h>

int main() {
    stdio_init_all();  // need when UART 

    printf("\nstart GPIO 2,3\n");

    gpio_set_function(2, GPIO_FUNC_PWM);
    gpio_set_function(3, GPIO_FUNC_PWM);

    // Find out which PWM slice is connected to GPIO 2 (it's slice 0)
    uint slice_num = pwm_gpio_to_slice_num(2);

    // Set period
    pwm_set_wrap(slice_num, 99);

    // Set channel A output high for one cycle before dropping
    pwm_set_chan_level(slice_num, PWM_CHAN_A, 10);
    // Set initial B output high for three cycles before dropping
    pwm_set_chan_level(slice_num, PWM_CHAN_B, 50);
    // Set the PWM running
    pwm_set_enabled(slice_num, true);
}

 wrapを100回繰り返すと125MHz ÷ 100 = 1.25MHzになります。では1.0MHzはどうやって作るのでしょうか。
 分周ユニットは8.4の固定小数点で表現されます。整数が8ビット、小数点が4ビットです。

    pwm_set_wrap(slice_num, 99);

の後ろに、

    uint8_t div = 1;
    uint8_t fract = 4;
    pwm_set_clkdiv_int_frac(slice_num, div, fract);

 整数1は、倍率1です。
 小数点部分は1/2^nの重み付けになります。4は2進数では
0100 = 0 * 1/2^1 + 1 * 1/2^2 + 0 * 1/2^3 + 0 * 1/2^4
= 0.25
合成すると1.25なので、1.25MHz/1.25=1MHzになります。
Screen 0.png

もう一例。

    uint8_t div = 2;
    uint8_t fract = 8;
    pwm_set_clkdiv_int_frac(slice_num, div, fract);

 整数2は、倍率2です。
 小数点部分は1/2^nの重み付けになります。8は2進数では
1000 = 1 * 1/2^1 + 0 * 1/2^2 + 0 * 1/2^3 + 0 * 1/2^4
= 0.5
合成すると2.5なので、1.25MHz/2.5=500kHzになります。
Screen 1.png

最後に、980Hzが欲しいなら、

1.25MHz/980=1275.5102
整数部は2^8=256を超えているので設定できません。pwm_set_wrap(slice_num, 999);に設定し、基準となるクロックを125kHzまで落とします。
125kHz/980=127.551
 したがって、整数部を127に、小数点部分を8にしました。980.39Hzとほぼ近い周波数になりました。warpは16ビットなので、もっと基準となる周波数を下げれば、目的に周波数に近づけると思います。

Screen 2.png

// Output PWM signals on pins 2 and 3

#include "pico/stdlib.h"
#include "hardware/pwm.h"
#include <stdio.h>
#include "hardware/clocks.h"
#include <math.h>

int main() {
    stdio_init_all();  // need when UART 

    printf("\nstart GPIO 2,3\n");

    gpio_set_function(2, GPIO_FUNC_PWM);
    gpio_set_function(3, GPIO_FUNC_PWM);

    // Find out which PWM slice is connected to GPIO 2 (it's slice 0)
    uint slice_num = pwm_gpio_to_slice_num(2);

    uint16_t divCounter = 1000; // max 2^16 = 65536
    pwm_set_wrap(slice_num, divCounter-1);

    uint8_t div = 127;
    uint8_t fract = 9;
    pwm_set_clkdiv_int_frac(slice_num, div, fract);


    // duty 10%
    pwm_set_chan_level(slice_num, PWM_CHAN_A, (int)divCounter*0.1);
    //  duty 50%
    pwm_set_chan_level(slice_num, PWM_CHAN_B, (int)divCounter*0.5);
    // Set the PWM running
    pwm_set_enabled(slice_num, true);
}

0
1
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
1