Raspberry Pi PicoとMOSFET ④ PWM 分周
前回、wrapを使って、システム・クロック125MHzを1MHzに落としました。もう一つの分周器を使って、もっと周波数を下げます。
●固定小数点形式
uint8_t div = 2;
uint8_t fract = 8;
pwm_set_clkdiv_int_frac(slice_num, div, fract);
整数部分をdiv、小数点部分をfractとします。divは8ビットなので最大256、fractは4ビットなので、1が最小単位になり、0b0001は、
0 * 1/2^1 + 0 * 1/2^2 + 0 * 1/2^3 + 1 * 1/2^4 = 1/16 = 0.0625
が最大分解能になります。
fract =8は0b1000なので、
1 * 1/2^1 + 0 * 1/2^2 + 0 * 1/2^3 + 0 * 1/2^4 = 1/2 = 0.5
div=2なので合成すると2.5になります。したがって、1MHz/2.5=400kHzです。
#include "pico/stdlib.h"
#include <stdio.h>
#include "hardware/pwm.h"
int main() {
stdio_init_all();
printf("\nHello, PWM GP2/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 0 (it's slice 0)
uint slice_num = pwm_gpio_to_slice_num(2);
// Set period of 10 cycles (0 to 3 inclusive)
pwm_set_wrap(slice_num, 124);
// Set channel A output high for one cycle before dropping
pwm_set_chan_level(slice_num, PWM_CHAN_A, 12);
// Set initial B output high for three cycles before dropping
pwm_set_chan_level(slice_num, PWM_CHAN_B, 63);
uint8_t div = 2;
uint8_t fract = 8;
pwm_set_clkdiv_int_frac(slice_num, div, fract);
// Set the PWM running
pwm_set_enabled(slice_num, true);
return 0;
}
●もう1セットPWMを起動
GP2/3をスライス2で動作させています。GP4/5をスライス4で動かして波形を見ます。デューティ比はすべて20%にしました。
スライス2とスライス4がそれぞれ同期しています。つまり、チャネルAとBは同じタイミングで起動されるということです。
このずれはどこで生じるのでしょうか。最後のPWMをスタートさせる部分を入れ替えました。
// Set the PWM running
pwm_set_enabled(slice_num2, true);
pwm_set_enabled(slice_num, true);
変わりませんでした。
●pwm_set_mask_enabled
この関数は、 複数のPWMスライスを同時に有効/無効にできます。
static void pwm_set_mask_enabled (uint32_t mask)
マスクはGP2、GP4をONにするため、0b00000110にしました。希望通り、波形の位置関係が同じになりました。
マスクの使いかたは、下記のページを参照してください。
Raspberry Pi Picoでプログラミング ⑰ gpioファンクション MASK
プログラムです。
#include "pico/stdlib.h"
#include <stdio.h>
#include "hardware/pwm.h"
int main() {
stdio_init_all();
printf("\nHello, PWM GP2/3,GP4/5\n");
gpio_set_function(2, GPIO_FUNC_PWM);
gpio_set_function(3, GPIO_FUNC_PWM);
gpio_set_function(4, GPIO_FUNC_PWM);
gpio_set_function(5, GPIO_FUNC_PWM);
// Find out which PWM slice is connected to GPIO 0 (it's slice 0)
uint slice_num = pwm_gpio_to_slice_num(2);
uint slice_num2 = pwm_gpio_to_slice_num(4);
// Set period of 10 cycles (0 to 3 inclusive)
pwm_set_wrap(slice_num, 1249);
// Set channel A output high for one cycle before dropping
pwm_set_chan_level(slice_num, PWM_CHAN_A, 256);
// Set initial B output high for three cycles before dropping
pwm_set_chan_level(slice_num, PWM_CHAN_B, 256);
pwm_set_wrap(slice_num2, 1249);
pwm_set_chan_level(slice_num2, PWM_CHAN_A, 256);
pwm_set_chan_level(slice_num2, PWM_CHAN_B, 256);
// Set the PWM running
//pwm_set_enabled(slice_num, true);
//pwm_set_enabled(slice_num2, true);
pwm_set_mask_enabled(0b00000110);
return 0;
}