Raspberry Pi Pico W(以下 PicoW)にはメインプロセッサとは独立して動作する、Programmable Input/Output(以下 PIO)と呼ばれる2機のプロセッサがあります。
それぞれのPIOにはステートマシンと呼ばれる、4個の独立して動作する処理ユニットがあり、PIO用のアセンブラ(以下 PIOASM)を使ってGPIOを制御できます。
センサー等の電子部品をPicoWに複数接続して処理する場合、一部の電子部品の制御に処理時間を取られ、別の電子部品の処理に支障をきたす場合があります。
たとえば、LEDとスイッチをPicoWに接続し、LEDの制御に時間を取られた場合、スイッチからの入力を検知できないことが考えられます。
PIOでスイッチ等の一部の電子部品を制御することで、この問題を解決することができます。
このようにPIOはI/Oに特化したプロセッサと言えます。
詳細はRP2040 Datasheet: A microcontroller by Raspberry Piを参照してください。
GPIOピン(以下 GPピン)にプッシュスイッチと赤、緑、青の3つのLEDを接続し、プッシュスイッチでPIO機能の割込みを発生させて、赤、緑、青の3つのLEDを制御するプログラムをC/C++で作成します。
赤と緑のLEDが500ms間隔で交互に点灯・消灯をしている途中で、プッシュスイッチを押すと、赤と緑のLEDの点灯・消灯が停止します。
その後、青のLEDが500ms間隔で点灯・消灯を3回繰り返した後、消灯し、再び赤と緑のLEDが500ms間隔で交互に点灯・消灯します。
実験準備
実験に必要な機器と部品を準備します。
機器
「Windows PCとC/C++でRaspberry Pi Pico Wの開発を始めよう。」記事で書きましたラズパイPicoWと、Visual Studio Code(以下 VSCode)をインストールしたWindows PCを準備します。
使う部品
LED(発光ダイオード)、固定抵抗など実験に使う部品を準備します。
部 品 名 | 規 格 | 数 量 | 取扱い店(参考) |
LED | 5mm 赤色 | 1 | 電子工作ステーション |
LED | 5mm 緑色 | 1 | 電子工作ステーション |
LED | 5mm 青色 | 1 | 電子工作ステーション |
タクトスイッチ | 高さ5mm | 1 | 電子工作ステーション |
カーボン抵抗 | 1/4W 330Ω | 3 | 電子工作ステーション |
ブレッドボード | 830穴 (訳アリ品を除く) | 1 | 電子工作ステーション |
ジャンパーワイヤ | オス-メス(約20cm) | 1 | 電子工作ステーション |
配線
GPIOピン(以下 GPピン)に接続された2つのLEDを、PIOを使って交互に点灯、消灯させるプログラムをC/C++で作成します。
配線リスト
ラズパイPicoWのGPピンと抵抗、LED、プッシュスイッチを接続します。
ラズパイPicoW | 部 品 | 部 品 |
GP26 | カーボン抵抗 R1 | LED1 アノード(足の長い方) |
GP27 | カーボン抵抗 R2 | LED2 アノード(足の長い方) |
GP16 | カーボン抵抗 R3 | LED3 アノード(足の長い方) |
GP17 | SW 2 | ー |
GND | SW 1 | ー |
GND | LED1 カソード(足の短い方) | ー |
GND | LED2 カソード(足の短い方) | ー |
GND | LED3 カソード(足の短い方) | ー |
配線図

ライセンス
プロジェクトのビルドに必要なソースファイル、ソースコードをビルドするための設定ファイル等は、3条項BSDライセンスのもとで配布します。
3条項BSDライセンスの概要(意訳)は次のとおりです。
- サンプルファイルのソースコードまたはバイナリ形式の再配布時には、著作権表示とライセンス条文を記載(SPDX-License-Identifier: BSD-3-Clauseなど)してください。
- サンプルファイルはコピー/配布/変更/変更後の配布/商用利用/有料販売など、自由に使うことができます。
- 書面による許可なしに、サンプルファイルから派生した製品の宣伝や販促に、本ライセンス記載の組織や貢献者(ラズパイ実験室)の名前を使うことはできません。
- サンプルファイルにはなんの保証もついていません。
サンプルファイルを利用し、なにか問題が発生した場合でも、作者(ラズパイ実験室)は一切の責任を負いませんので、使用に伴うリスクを理解し、自己責任で利用してください。
プロジェクト
GPIOに接続した2つのLEDを交互に点灯・消灯させるプロジェクト(pio_switch)をVSCodeのC/C++を使って作成します。
pio_switchプロジェクトは、コンパイルに必要な、ソースファイル(pio_switch.c)、ソースコードをビルドするための設定ファイル(CMakeLists.txt)、PicoのSDKインポート用のファイル(pico_sdk_import.cmake)で構成されています。
ソースコードをVSCodeにコピーしてビルドします。
プロジェクト・フォーマットの作成
プロジェクト作成のためのフォーマットを作成します。
作成方法については、こちらを参照してください。
「Basic Setting」は以下のように設定します。
項 目 | 説 明 |
Name | pio_switch |
Board type | Pico W |
Location | 任意(全角文字、半角カタカナが含まれていないこと。) ※自身のユーザ内に任意のファルダを作成します。 |
Select Pico SDK version | v2.1.1 |
Features | PIO interface :✔ |
Stdio support | Console over UART :✔ |
さ
「build」の中に「build.ninja」が存在し、2つのソースコード、「pio_switch.c」と「blink.pio」が作成されていることを確認します。
プロジェクトの作成
作成したプロジェクト・フォーマットに、ソースコードを入力またはコピーして、プロジェクトを作成します。
▶️pio_switch.cの作成
- 「エクスプローラー」アイコンをクリックして、「pio_switch.c」を表示します
- 現在、VSCodeに表示されている内容をすべて削除します
- 下記「pio_switch.c」のソースコードを入力またはコピー/貼り付けし保存します
【pio_switch.c】
//
// Copyright (c) 2025 ラズパイ実験室
//
// SPDX-License-Identifier: BSD-3-Clause
//
//********************************
//
//PIO機能でプッシュスイッチの割り込み処理
//
//********************************
#include <stdio.h>
#include <stdbool.h>
#include "pico/stdlib.h"
#include "hardware/pio.h"
#include "mypio1.pio.h"
//プッシュスイッチ接続 GPIOピン基準番号
#define INPUT_PIN_BASE 17
//Lプッシュスイッチ接続 GPIOピン数
#define NUM_INPUT_PIN 1
//クロック分周値(125000000Hz / 62500 = 2000Hz)
#define CLOCK_DIV 62500
//メイン処理で使うGPIOピン
#define LED_PIN_RED 27
#define LED_PIN_GREEN 26
#define LED_PIN_BLUE 16
//割り込みフラグ クリア
int blue_led_flg = 0;
//プッシュスイッチの割り込みハンドラ
void pio0_pushsw() {
irq_clear(PIO0_IRQ_0);
pio0_hw->irq = 1;
// 割り込みが視覚的に分かるようにLEDを光らせる
if (blue_led_flg == 0)
{
//割り込みフラグ セット
blue_led_flg = 1;
}
else
{
//割り込みフラグ クリア
blue_led_flg = 0;
}
}
int main()
{
stdio_init_all();
//メイン処理で使うLEDピン 初期化
gpio_init(LED_PIN_RED);
gpio_init(LED_PIN_GREEN);
gpio_init(LED_PIN_BLUE);
//メイン処理で使うLEDピンを出力ピンに設定
gpio_set_dir(LED_PIN_RED, GPIO_OUT);
gpio_set_dir(LED_PIN_GREEN, GPIO_OUT);
gpio_set_dir(LED_PIN_BLUE, GPIO_OUT);
//プッシュスイッチピン プルアップ
gpio_pull_up(INPUT_PIN_BASE);
//使用するPIO番号を指定
PIO pio = pio0;
//使用するステートマシン番号を指定
uint state_machine_id = 0;
//ステートマシン0からの割り込み(プッシュスイッチ)を有効化
//IRQ番号(PIO0_IRQ_0:7)に対応した割り込み処理ルーチンを設定
irq_set_exclusive_handler(PIO0_IRQ_0, pio0_pushsw);
//割り込みの有効化
irq_set_enabled(PIO0_IRQ_0, true);
pio0_hw->inte0 = PIO_IRQ0_INTE_SM0_BITS;
//指定したPIOの命令モリにプログラムをロードする
uint offset = pio_add_program(pio, &mypio1_program);
//PIOプログラムの呼び出しと起動
mypio1_program_init(pio, state_machine_id, offset, INPUT_PIN_BASE, NUM_INPUT_PIN, CLOCK_DIV);
//メイン処理
while (true) {
//割り込み未発生
if (blue_led_flg == 0)
{
//RED LED点灯
gpio_put(LED_PIN_RED, 1);
sleep_ms(500);
//RED LED消灯
gpio_put(LED_PIN_RED, 0);
//GREEN LED点灯
gpio_put(LED_PIN_GREEN, 1);
sleep_ms(500);
//GREEN LED消灯
gpio_put(LED_PIN_GREEN, 0);
}
else
{
//割り込み発生
int i;
for (i = 0; i < 3; i++)
{
gpio_put(LED_PIN_BLUE, 1);
sleep_ms(500);
gpio_put(LED_PIN_BLUE, 0);
sleep_ms(500);
}
//割り込みフラグ クリア
blue_led_flg = 0;
}
}
}
▶️ mypio1.pioの作成
- 「エクスプローラー」に表示されている「blink.pio」の名前を、右クリックして「mypio1.pio」に変更します
- 現在、VSCodeに表示されている「mypio1.pio」の内容をすべて削除します
- 下記「mypio1.pio」のソースコードを入力またはコピー/貼り付けし保存します
【mypio1.pio】
//
// Copyright (c) 2025 ラズパイ実験室
//
// SPDX-License-Identifier: BSD-3-Clause
//
.program mypio1
//.wrap_target~.wrap間の処理を繰り返し実行
.wrap_target
//プッシュスイッチが押される(High → Low)まで待つ
wait 0 pin 0
//チャタリング吸収(96ステップ X 0.5ms = 48ms)
nop [31]
nop [31]
nop [31]
//プッシュスイッチの割り込みを発生させる
irq 0
//プッシュスイッチが離される(Low → High)まで待つ
wait 1 pin 0
//チャタリング吸収(96ステップ X 0.5ms = 48ms)
nop [31]
nop [31]
nop [31]
.wrap
% c-sdk {
//GPIO出力を設定して、SMが指定されたピンに出力するように設定
static inline void mypio1_program_init(PIO pio, uint sm, uint offset, uint input_pin, uint num_input_pin, float clkdiv){
//指定したPIOステートマシンの初期設定情報をメモリに格納する
pio_sm_config config = mypio1_program_get_default_config(offset);
//ステートマシンのクロック分周値を設定する。125000000Hz / clkdiv(62500) = 2000Hz
sm_config_set_clkdiv(&config, clkdiv);
//GPIOをPIOに割り当てる
pio_gpio_init(pio, input_pin);
//指定したPIOで使用するステートマシンのGPIOピンの方向を入力に設定する
pio_sm_set_consecutive_pindirs(pio, sm, input_pin, num_input_pin, false);
//ステートマシンの入力ピンの基準点(プッシュスイッチのピン17)を設定する
sm_config_set_in_pins(&config, input_pin);
//指定したPIOで使用するステートマシンにメモリに格納された初期設定情報を適用する
pio_sm_init(pio, sm, offset, &config);
//指定したPIOで使用するステートマシンを起動する
pio_sm_set_enabled(pio, sm, true);
}
%}
▶️ CMakeLists.txtの変更
- 「エクスプローラー」に表示されている「CMakeLists.txt」をクリックすると、エディタエリアに内容が表示されます。
- 「Generate PIO header」のフィル名を、「blink.pio」から「mypio1.pio」に変更し、保存します。
# Generate PIO header
pico_generate_pio_header(pio_led_toggle ${CMAKE_CURRENT_LIST_DIR}/blink.pio)
pico_generate_pio_header(pio_led_toggle ${CMAKE_CURRENT_LIST_DIR}/mypio1.pio)
プログラムの実行
Raspberry Pi Pico Wに接続されているUSBケーブルを外し、「BOOTSEL」ボタンを押しながら、USBケーブルを差し込みます。

「F5」キーを押して実行すると、途中、Temporary breakpointsで一時停止します。

もう一度、「F5」キーを押して続行します。
赤と緑のLEDが500ms間隔で交互に点灯・消灯をしている途中で、プッシュスイッチを押すと、赤と緑のLEDの点灯・消灯が停止します。
その後、青のLEDが500ms間隔で点灯・消灯を3回繰り返した後、消灯し、再び赤と緑のLEDが500ms間隔で交互に点灯・消灯します。
確認後、「Shift + F5」キーを押して、停止します。
まとめ
GPIOピン(以下 GPピン)にプッシュスイッチと赤、緑、青の3つのLEDを接続し、プッシュスイッチでPIO機能の割込みを発生させて、赤、緑、青の3つのLEDを制御しました。
プッシュスイッチの状態の監視し、割り込みを発生させ、3つのLEDがスムーズに点灯・消灯できることで、メインプロセッサとは独立して動作する、Programmable Input/Output(PIO)のディジタル信号入力機能を確認することができました。
おすすめの一冊