LoginSignup
0
2

More than 3 years have passed since last update.

初めてのRaspberry Pi Pico ⑯ C言語 PWM その1

Posted at

 第6回のように、pico/examplesではなく、pico/worksで作業をしています。
 pico/examples/pwm/からhello_pwmフォルダをpico/works/フォルダにコピーしてきます。pico/works/フォルダにあるCMakeLists.txtを次のように、最後に1行追加します。

cmake_minimum_required(VERSION 3.12)

# Pull in SDK (must be before project)
include(pico_sdk_import.cmake)

project(pico_examples C CXX ASM)
set(CMAKE_C_STANDARD 11)
set(CMAKE_CXX_STANDARD 17)

set(PICO_EXAMPLES_PATH ${PROJECT_SOURCE_DIR})

# Initialize the SDK
pico_sdk_init()

# Add blink example
add_subdirectory(blink)
add_subdirectory(cmake)
add_subdirectory(LED7seg_74HC595)
add_subdirectory(bus_scan)
add_subdirectory(lcd_1602_i2c)
add_subdirectory(CRC8)
add_subdirectory(adt7410)
add_subdirectory(hello_pwm)

 /home/pi/pico/works/hello_pwmには、CMakeLists.txtとhello_pwm.cの二つのファイルが入っています。CMakeLists.txtは次のように、最後の行をコメントアウトします。

add_executable(hello_pwm
        hello_pwm.c
        )

# Pull in our pico_stdlib which pulls in commonly used features
target_link_libraries(hello_pwm pico_stdlib hardware_pwm)

# create map/bin/hex file etc.
pico_add_extra_outputs(hello_pwm)

# add url via pico_set_program_url
#example_auto_set_url(hello_pwm)

 第6回とは異なり、二つのCMakeLists.txtでは、urlのセットを使っていません(消しています。コメントアウトしています)。残したまま(生かしたまま)でも、支障はありません。

 hello_pwm.cを次のように修正します。元はGPIO0とGPIO1にPWM出力を出していますが、この二つは、printfの出力に使っているので避けます。

/**
 * Copyright (c) 2020 Raspberry Pi (Trading) Ltd.
 *
 * SPDX-License-Identifier: BSD-3-Clause
 */

// Output PWM signals on pins 0 and 1

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

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

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

    /// \tag::setup_pwm[]

    // Tell GPIO 0 and 1 they are allocated to the PWM
    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 of 4 cycles (0 to 3 inclusive)
    pwm_set_wrap(slice_num, 3);
    // Set channel A output high for one cycle before dropping
    pwm_set_chan_level(slice_num, PWM_CHAN_A, 1);
    // Set initial B output high for three cycles before dropping
    pwm_set_chan_level(slice_num, PWM_CHAN_B, 3);
    // Set the PWM running
    pwm_set_enabled(slice_num, true);
    /// \end::setup_pwm[]

    // Note we could also use pwm_set_gpio_level(gpio, x) which looks up the
    // correct slice and channel for a given GPIO.
}

make

/home/pi/pico/works/buildにおります。

cmake ..

 これは一度だけ実行します。最初になかったhello_pwmができているので、このディレクトリにおります。

make -j4

make -j4を実行すると、このフォルダ内にhello_pwm.uf2ができています。
 第6回で作ったResetボタンを使います。Resetボタンを押したまま、BOOTSELボタンを押し、Resetボタンを放してから、BOOTSELボタンを放します。これでRPI-RP2ディスクがマウントができます。これにhello_pwm.uf2をドロップします。
 cmakeは1回だけ実行、makeはソースを修正するたびに実行します。ビルドされるとき、リンクされるライブラリ類は最初の1回だけコンパイルされるので、時間がかかるのは最初の1回だけです。

 その前に、第3回で解説した「標準出力を用意」でターミナルを動かしておきます。このターミナルに「start GPIO 2,3」のメッセージが出力されます。
 GPIO2,3をオシロスコープで見ます。黄色(上)がGPIO2、下の緑色がGPIO3です。
Screen 0.png

パラメータを変えて何が変化するのかを確認する

 2か所変更します。wrapを3から5へ、Bのchan_levelを3から5へ変更します。

    // Set period of 4 cycles (0 to 3 inclusive)
    pwm_set_wrap(slice_num, 5);  // 3->5
    // Set channel A output high for one cycle before dropping
    pwm_set_chan_level(slice_num, PWM_CHAN_A, 1);
    // Set initial B output high for three cycles before dropping
    pwm_set_chan_level(slice_num, PWM_CHAN_B, 3);  //3->5

 波形です。周波数が下がりました。GPIO3のHigh期間が長くなりました。
pwm101.png

 slice_numは0~7の範囲を取り、物理的なピン番号GPIOxを論理的な数値として扱います。slice_numはAとBがそれぞれあるので、扱えるチャネル数は16になります。GPIOは30個ありますが、

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

 で、どのピンをPWMように使うかをセットし(物理ピン番号ではなくGPIOxのxの数値で指定)、

uint slice_num = pwm_gpio_to_slice_num(2);

 GPIO2を論理番号slice 0に割り当てています。

 wrapは、カウンタを0からffffまでカウントアップして'1'となります。すぐに0にもどり、カウントアップします。カウンタの周波数は、ここでは不明です。
 最初のプログラムではwrapは4でした。変更してwarpを6にしました。
 31.4MHzの周期は31.8471nsです。20.9MHzの周期は47.8469nsです。1warp=7.961775もしくは7.97448です。7.97nsとして逆数は125470kHzです。

クロックの情報をもっと調べる

 clkで検索して、それらしいソースをマニュアルから見つけ、追加しました。

/**
 * Copyright (c) 2020 Raspberry Pi (Trading) Ltd.
 *
 * SPDX-License-Identifier: BSD-3-Clause
 */

// Output PWM signals on pins 0 and 1

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

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

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

    /// \tag::setup_pwm[]

    // Tell GPIO 0 and 1 they are allocated to the PWM
    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 of 4 cycles (0 to 3 inclusive)
    pwm_set_wrap(slice_num, 5);
    // Set channel A output high for one cycle before dropping
    pwm_set_chan_level(slice_num, PWM_CHAN_A, 1);
    // Set initial B output high for three cycles before dropping
    pwm_set_chan_level(slice_num, PWM_CHAN_B, 5);
    // Set the PWM running
    pwm_set_enabled(slice_num, true);
    /// \end::setup_pwm[]

    // Note we could also use pwm_set_gpio_level(gpio, x) which looks up the
    // correct slice and channel for a given GPIO.
uint f_pll_sys = frequency_count_khz(CLOCKS_FC0_SRC_VALUE_PLL_SYS_CLKSRC_PRIMARY);
uint f_pll_usb = frequency_count_khz(CLOCKS_FC0_SRC_VALUE_PLL_USB_CLKSRC_PRIMARY);
uint f_rosc = frequency_count_khz(CLOCKS_FC0_SRC_VALUE_ROSC_CLKSRC);
uint f_clk_sys = frequency_count_khz(CLOCKS_FC0_SRC_VALUE_CLK_SYS);
uint f_clk_peri = frequency_count_khz(CLOCKS_FC0_SRC_VALUE_CLK_PERI);
uint f_clk_usb = frequency_count_khz(CLOCKS_FC0_SRC_VALUE_CLK_USB);
uint f_clk_adc = frequency_count_khz(CLOCKS_FC0_SRC_VALUE_CLK_ADC);
uint f_clk_rtc = frequency_count_khz(CLOCKS_FC0_SRC_VALUE_CLK_RTC);

printf("pll_sys = %dkHz\n", f_pll_sys);
printf("pll_usb = %dkHz\n", f_pll_usb);
printf("rosc = %dkHz\n", f_rosc);
printf("clk_sys = %dkHz\n", f_clk_sys);
printf("clk_peri = %dkHz\n", f_clk_peri);
printf("clk_usb = %dkHz\n", f_clk_usb);
printf("clk_adc = %dkHz\n", f_clk_adc);
printf("clk_rtc = %dkHz\n", f_clk_rtc);
printf("-----\n");

}

ターミナルには、次のように表示が出ました。

pll_sys = 125000kHz                             
pll_usb = 48000kHz                              
rosc = 5093kHz                                  
clk_sys = 125000kHz                             
clk_peri = 125000kHz                            
clk_usb = 48000kHz                              
clk_adc = 48000kHz                              
clk_rtc = 47kHz   

 1warpは125470kHzでした。システム・クロックにほぼ等しいと推定できます。
周波数カウンタHP 5334Bで測ると20.8333794MHzでした。1warp=7.99998231nsは125000.2764kHzです。システム・クロックclk_sysそのものですね。

0
2
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
2