皆さん こんにちは。
今回は UART で受信してみます。
サンプルにもあるもので何か受信すると値を+1して返信するというシンプルなエコーバックです。
環境構築やプロジェクトのつくり方
環境構築やプロジェクトのつくり方、VSCodeの起動については、このブログの一番最初の記事に書きました。
環境構築してみたい方は こちら をご覧になってください。
プロジェクトの作成
以下の設定でプロジェクトを作成します。
Project Name: picoUartRx
Console Options の Console over UART のチェックをはずす
IDE Options の Create VSCode project をチェックする
Debugger: は PicoProbe を選択する

VSCodeを起動する
起動後、何かファイルが開いてたら File – Close Folder で閉じた後、File – Open Folder から picoUartRx のフォルダーを辿って選択します。
こちらの環境では C:\Users\m3925\Documents\Pico\pico-project-generator\picoUartRx です。
m3925の部分は皆さんのユーザー名に置き換えてください。
vscode関連の json ファイルは前回作成済のプロジェクトのものをドラッグ&ドロップでコピー&ペーストすると楽です。
ソースコードを書く
VSCodeのツリーから picoUartRx.c を選択して次のように編集し、保存します。
#include "pico/stdlib.h"
void other_works();
int main() {
stdio_init_all();
uart_init(uart0, 115200);
// 7bit + パリティだと 8bit を指定するらしい
uart_set_format(uart0, 8, 1, UART_PARITY_EVEN);
// 7bit + パリティはそのまま設定すれば OK です
// PC側の設定に合わせれば OK です。
uart_set_format(uart0, 7, 1, UART_PARITY_EVEN);
gpio_set_function(0, GPIO_FUNC_UART);
gpio_set_function(1, GPIO_FUNC_UART);
while (true) {
uint8_t c;
while (uart_is_readable(uart0)) {
c = uart_getc(uart0);
if (uart_is_writable(uart0)) {
c++;
uart_putc_raw(uart0, c);
}
}
other_works();
}
return 0;
}
void other_works() { sleep_ms(10); }
PC側の準備
通信の確認用として Tera Term を使います。
お持ちでない方は こちら からダウンロードしてお使いください。
インストール後、 Tera Term を起動し、シリアルポートでPicoprobeのCOMポートを選択します。
もしCOMポートが複数ある場合には、Picoprobe以外の通信ケーブルをはずしてデバイスマネージャーでCOMポート番号を確認しておきます。

起動後、設定メニューのシリアルポートから以下の設定を行います。
スピート : 115200
データ : 7 bit
パリティ : even
ストップビット : 1
フロー制御 : none
これらの値は送受信する相手と合わせておく必要があります。

プログラムの説明
ピンにペリフェラル(機能)を割り当てる。
GPIOにUART0を割り当てる
以下の図をご覧ください。
UART0は赤枠で囲ったいずれかのピンで使うことができます。

GP0 というのは GPIO0 を意味します。
GPIO28 も UART0 TX を割り当てられるはずですが図にはありませんね。
誤記でしょうか。
ラズピコからPicoprobeには 1番ピン(GPIO0)を接続していますので、ここに UART0 TX を割り当てます。
そして同様にPicoprobeに接続しているラズピコの2番ピン(GPIO1)に UART0 RX を割り当てます。
コードでは以下の部分になります。
gpio_set_function(0, GPIO_FUNC_UART);
gpio_set_function(1, GPIO_FUNC_UART);
第1引数 : GPIOの番号を指定します。
第2引数 : gpio_function(機能)を指定します。
機能は以下の通りに enum で定義されています。
enum gpio_function {
GPIO_FUNC_XIP = 0 , GPIO_FUNC_SPI = 1 , GPIO_FUNC_UART = 2 , GPIO_FUNC_I2C = 3 ,
GPIO_FUNC_PWM = 4 , GPIO_FUNC_SIO = 5 , GPIO_FUNC_PIO0 = 6 , GPIO_FUNC_PIO1 = 7 ,
GPIO_FUNC_GPCK = 8 , GPIO_FUNC_USB = 9 , GPIO_FUNC_NULL = 0x1f
}
uart_init()で初期化します。
ペリフェラルは概ね、 xxx_init() で初期化されるようです。
xxx の部分はペリフェラル名 i2c とか、spi など。
第1引数 : UARTのインスタンス(0 or 1)を指定します。
第2引数 : 通信速度を指定します。
uart_set_format()で通信パラメーターを指定します。
通信速度だけは別になっているのですね。
第1引数 : UARTのインスタンス(0 or 1)を指定します。
第2引数 : データビットを指定します。
第3引数 : ストップビットを指定します。
第4引数 : パリティを指定します。
uart_is_readable()は受信する文字があるか確認する関数です。
あれば true が返ります。
第1引数 : UARTのインスタンス(0 or 1)を指定します。
uart_getc()は1文字読み込みます。
第1引数 : UARTのインスタンス(0 or 1)を指定します。
uart_is_writable()は受信する文字があるか確認する関数です。
あれば true が返ります。
第1引数 : UARTのインスタンス(0 or 1)を指定します。
uart_putc_raw()は1文字送信する関数です。
uart_putc()という関数がありますが、関数の中で変換することがあるようでやや特殊なので使いませんでした。
第1引数 : UARTのインスタンス(0 or 1)を指定します。
第2引数 : 送信する文字を指定します。
RP2040のUARTは2つですから uart0 または uart1 を使います。
パリティは以下の通りに enum で定義されています。
今回は even (偶数)を指定しました。(データビット等も気まぐれで決めただけで特に根拠はありません)
enum uart_parity_t { UART_PARITY_NONE , UART_PARITY_EVEN , UART_PARITY_ODD }
プログラムを動作させる
それでは VScode にフォーカスをあてて、F5キーを押してプログラムを動作させます。
Tera Term にフォーカスをあてて何かキーを押し、(c++しているので) その次のASCIIコードが返ってくれば成功です。
その次のコードとは例えば a を押したら b 、 1 を押したら 2 です。
いかがでしたか?
うまく受信できましたか?
今回のプログラムのように時々受信バッファにデータがあるか確認する方法をポーリングと呼んでいます。
この方式には欠点があり、それ以外の処理(ここでは other_works())にかかる時間が長いとデータを取りこぼす可能性があります。
次回は割り込みを使って改善案を検討してみます。
お疲れさまでした。