Raspberry Pi

Raspberry Piのシリアルポート設定(UART)を理解する

Raspberry Piのシリアルポート設定(UART)を分かりやすく解説します。

Raspberry Piで使用できるUARTにはPL011(16550互換)とmini UARTの2種類があります。mini UARTは機能に制限があるUARTになります。

プライマリUARTは、シリアルコンソールとして使うか、汎用シリアルとして使うかの割り当てが可能です。

また、Raspberry Pi 4ではUART2~UART5の4つのPL011が追加されています。

準備

Raspberry PiのすべてのUARTは3.3Vで動作します。そのため、通常のシリアルポートに接続する場合や、5Vのシステムに接続する場合には変換アダプターを使用して接続します。

USB to TTLシリアルケーブル

パソコンと接続するために、USB to TTLシリアルケーブルを用意しました。

adafruit製のUSB to TTL Serial Cable(954)にしました。

理由としては、2016/12/21以降の出荷品については、Prolific PL2303HXチップセットから、SiLabs CP2102チップセットに変わっているようです。ドライバの安定性が向上していて、高速通信も安定しているような事が書いてあったのでこれにしました。115200bpsより早い、921600bpsまで設定ができます。

adafruitの製品ページ

USB to TTL シリアルケーブル

SiLabs CP2102チップセットのドライバーをダウンロードしてインストールします。

SiLabs CP210xチップセットのドライバーをダウンロードページ

SiLabs CP2102チップセットのドライバーをダウンロードページ

ドライバインストール後に、USB to TTLシリアルケーブルを接続すると次のようにデバイスが認識します。

ドライバインストール後のデバイスマネージャー

USB to TTLシリアルケーブルをRaspberry Piに接続

今回はプライマリUARTに接続します。

接続先は、Raspberry PiのGPIOの対応を次の図で確認します。

シリアルケーブルの5V電源は接続しません。

シリアルケーブルのGNDは、Raspberry PiのGNDに接続します。(6番PIN)

シリアルケーブルのRXDは、Raspberry PiのTXD(GPIO14)に接続します。(8番PIN)

シリアルケーブルのTXDは、Raspberry PiのRXD(GPIO15)に接続します。(10番PIN)

引用 : Raspberry Pi公式HP GPIO

GPIOの対応は、Raspberry Piのターミナルにて「pinout」コマンドでも確認できます。

「pinout」コマンド
USB to TTLシリアルケーブルの説明
シリアルケーブル Raspberry Pi GPIO
赤 : 5V出力 未接続
黒 : GND GND(6番PIN)
白 : RXD GPIO14 TXD(8番PIN)
緑 : TXD GPIO15 RXD(10番PIN)
Raspberry Piに接続した図

パソコン側のターミナルソフト(Tera Term)

ターミナルソフトとしての定番のTera Termをダウンロードしてインストールします。

Tera Termのダウンロードページ

Tera Term

Raspberry Pi側のターミナルソフト(GtkTerm)

Raspberry Pi側での動作確認用のターミナルソフトとしてGtkTermを使います。

次のコマンドにてインストールします。

$ sudo apt install gtkterm

「スタートメニュー」-「アクセサリ」-「Serial Port terminal」が追加されるので、クリックしてGtkTermを起動します。

スタートメニュー
GtkTerm

Raspberry Piのシリアルポート設定

シリアルポートはデフォルトでは無効になっています。そのため、設定で有効にする必要があります。

シリアルコンソールとして使う

Raspberry Pi 4では、シリアルコンソールとしてmini UARTがプライマリポートとして有効になります。(設定で入れ換えない場合)

GUIで設定する場合

「スタートメニュー」-「設定」-「Raspberry Piの設定」でRaspberry Piの設定プロパティを開きます。

「インターフェイス」タブをクリックして、「シリアルポート」・有効、「シリアルコンソール」・有効に設定して、「OK」をクリックします。

Raspberry Piの設定

再起動確認画面になるので、「はい」をクリックします。再起動するとシリアルコンソールが有効になります。

再起動確認画面

パソコンとシリアルを接続しておくと、次のようにlogin画面が表示されます。

シリアルポートの設定は次の設定にします。

  • ボーレート  ・・・ 115200
  • データビット ・・・ 8bit
  • パリティ   ・・・ none
  • ストップビット・・・ 1bit
  • フロー制御  ・・・ none
シリアルコンソールのログイン画面

raspi-configで設定する場合

Raspberry Piにてターミナルソフトを起動して、次の「sudo raspi-config」コマンドを実行します。

$ sudo raspi-config

「3 Interface Options」を選択します。

3 Interface Options

「P6 Serial Port Enable/disable」を選択します。

P6 Serial Port Enable/disable

ログインシェルにシリアル経由でアクセスするか確認になるので、「はい」を選択します。

「はい」を選択

「了解」を選択します。

「了解」を選択

メニュー画面に戻るので、「Finish」を選択します。

「Finish」を選択

再起動確認になるので「はい」を選択して、Raspberry Piを再起動します。これでシリアルコンソールが有効になります。

「はい」を選択

汎用シリアルとして使う

Raspberry Pi 4では、汎用シリアルとしてmini UARTがプライマリポートとして有効になります。(設定で入れ換えない場合)

GUIで設定する場合

「スタートメニュー」-「設定」-「Raspberry Piの設定」でRaspberry Piの設定プロパティを開きます。

「インターフェイス」タブをクリックして、「シリアルポート」・有効、「シリアルコンソール」・無効に設定して、「OK」をクリックします。

Raspberry Piの設定

再起動確認画面になるので、「はい」をクリックします。再起動すると汎用シリアルが有効になります。

再起動確認画面

パソコンとシリアルを接続して、パソコン側とRaspberry Pi側のシリアルポートの設定を次のようにして通信確認をします。

シリアルポートの設定は次の設定にします。

  • ボーレート  ・・・ 115200
  • データビット ・・・ 8bit
  • パリティ   ・・・ none
  • ストップビット・・・ 1bit
  • フロー制御  ・・・ none

Raspberry Pi側のGtkTerm設定

GtkTermを起動して、「Configuration」-「Port」を選択します。

GtkTerm

Portの設定は、候補に表示されない時には直接キーボードでLinuxデバイス名を入力します。Baud Rateなど正しい設定にします。

Portの設定

パソコンとRaspberry Piとの通信確認

パソコン側でTera Termでキー入力すると、Raspberry Pi側のGtkTermに入力したキーの文字が表示されます。

反対に、Raspberry Pi側でキー入力すると、パソコン側のTera Termに入力したキーの文字が表示されます。

これで送受信の確認ができます。

ターミナルにて入力した文字が表示

raspi-configで設定する場合

Raspberry Piにてターミナルソフトを起動して、次の「sudo raspi-config」コマンドを実行します。

$ sudo raspi-config

「3 Interface Options」を選択します。

3 Interface Options

「P6 Serial Port Enable/disable」を選択します。

P6 Serial Port Enable/disable

ログインシェルにシリアル経由でアクセスするか確認になるので、「いいえ」を選択します。

「いいえ」を選択

シリアルポートのハードウェアを有効にするか確認になるので、「はい」を選択します。

「はい」を選択

「了解」を選択します。

「了解」を選択

メニュー画面に戻るので、「Finish」を選択します。

「Finish」を選択

再起動確認になるので「はい」を選択して、Raspberry Piを再起動します。これで汎用シリアルが有効になります。

「はい」を選択

シリアルポートの構成説明

Raspberry Piで使用できるUARTにはPL011(16550互換)とmini UARTの2種類があります。

設定によってプライマリUARTがどちらになるかが変わります。この入れ替わる機能が分かりにくい部分だと思います。

また、Raspberry Pi 4ではUART2~UART5の4つのPL011が追加されています。

参照 : Raspberry Pi 公式 UART設定のページ

Raspberry Pi Zero、1、2、3は2つのUARTを持っています

名前 タイプ
UART0 PL011
UART1 mini UART

Raspberry Pi 4は6つのUARTを持っています。

名前 タイプ
UART0 PL011
UART1 mini UART
UART2 PL011
UART3 PL011
UART4 PL011
UART5 PL011

プライマリUARTとセカンダリUARTの構成

デフォルトでは、UART0のみが有効になっています。次の表はデフォルトでのUARTの割り当てをまとめた物です。

mini UARTは、プライマリまたはセカンダリ関係なく、デフォルトでは無効になっています。

Model first PL011(UART0) mini UART
Raspberry Pi Zero プライマリ セカンダリ
Raspberry Pi Zero W/WH セカンダリ(Bluetooth) プライマリ
Raspberry Pi 1 プライマリ セカンダリ
Raspberry Pi 2 プライマリ セカンダリ
Raspberry Pi 3 セカンダリ(Bluetooth) プライマリ
Raspberry Pi 4 セカンダリ(Bluetooth) プライマリ

プライマリUARTは、GPIO 14 (TXD)とGPIO 15(RXD)に存在するUARTの1つとして選択されます。Linuxシリアルコンソールとして使用した場合には、このプライマリUARTで通信します。

セカンダリUARTは、通常GPIOコネクタにはありません。BluetoothコントローラーがあるModelでは、Bluetoothに接続されています。

シリアルポートのLinuxデバイス名

Linuxデバイス名 説明
/dev/ttyS0 mini UART
/dev/ttyAMA0 first PL011(UART0)
/dev/serial0 プライマリUART0
/dev/serial1 セカンダリUART1

「/dev/serial0」と「/dev/serial1」は、「/dev/ttyS0」または「/dev/ttyAMA0」のどちらかを指すシンボリックリンクになっていて、設定によって変わります。

PL011とmini UARTの相違点

mini UARTはPL011に比べて次のような欠点があります。

  • PL011より少ないFIFO(送信および受信用の8シンボル深さのFIFO)
  • Break信号検出ができない
  • フレーミングエラーの検出ができない
  • パリティビットが検出できない
  • 受信タイムアウト割込みなし
  • DCD、DSR、DTR、RI信号なし

mini UARTの詳細については、SoC周辺機器のドキュメントを参照してください。

SoC周辺機器のドキュメント

シリアルポートの設定とGPIOとの対応関係

Raspberry Pi 4を元にシリアルポートの設定とGPIOとの対応関係を説明します。

「/boot/config.txt」の設定パラメータは、「dtoverlay -h uart0」コマンドで確認できます。「uart0」の所をuart1、uart2などに変えれば各ポートのHelpが確認できます。

$ dtoverlay -h uart0
Name:   uart0

Info:   Change the pin usage of uart0

Usage:  dtoverlay=uart0,<param>=<val>

Params: txd0_pin                GPIO pin for TXD0 (14, 32 or 36 - default 14)

        rxd0_pin                GPIO pin for RXD0 (15, 33 or 37 - default 15)

        pin_func                Alternative pin function - 4(Alt0) for 14&15,
                                7(Alt3) for 32&33, 6(Alt2) for 36&37



「raspi-gpio」コマンドを使うと、現在のGPIOの設定で有効になっている機能が分かります。

次の例では、シリアルポート(UART1)が有効になっているので、「TXD1」「RXD1」がGPIO 14、GPIO 15に割り当てられています。

$ raspi-gpio get 0-15
GPIO 0: level=1 fsel=0 func=INPUT pull=UP
GPIO 1: level=1 fsel=0 func=INPUT pull=UP
GPIO 2: level=1 fsel=0 func=INPUT pull=UP
GPIO 3: level=1 fsel=0 func=INPUT pull=UP
GPIO 4: level=1 fsel=0 func=INPUT pull=UP
GPIO 5: level=1 fsel=0 func=INPUT pull=UP
GPIO 6: level=1 fsel=0 func=INPUT pull=UP
GPIO 7: level=1 fsel=0 func=INPUT pull=UP
GPIO 8: level=1 fsel=0 func=INPUT pull=UP
GPIO 9: level=0 fsel=0 func=INPUT pull=DOWN
GPIO 10: level=0 fsel=0 func=INPUT pull=DOWN
GPIO 11: level=0 fsel=0 func=INPUT pull=DOWN
GPIO 12: level=0 fsel=0 func=INPUT pull=DOWN
GPIO 13: level=0 fsel=0 func=INPUT pull=DOWN
GPIO 14: level=1 fsel=2 alt=5 func=TXD1 pull=NONE
GPIO 15: level=1 fsel=2 alt=5 func=RXD1 pull=UP

デフォルトのシリアルポート無効

デフォルトの状態として、次の設定の時にRaspberry Piがどうなっているか説明します。

ポート 設定
シリアルポート 無効
Bluetooth 有効
シリアルポート設定

シリアルポート無効設定なので、「/boot/config.txt」の「enable_uart=0」になります。

[all]
enable_uart=0

次の図のように、UART0がBluetoothに接続されていて、UART1は無効になっていて使えない状態です。

シリアルポート無効の場合

Linuxデバイスとしても、「/dev/ttyAMA0」しか有効になっていません。

$ ls -l /dev/ttyAMA*
crw-rw---- 1 root dialout 204, 64  6月  7 01:01 /dev/ttyAMA0
$ ls -l /dev/serial*
lrwxrwxrwx 1 root root 7  6月  7 01:01 /dev/serial1 -> ttyAMA0

シリアルポート有効、mini UARTがプライマリ

シリアルポートを有効にした状態として、次の設定の時にRaspberry Piがどうなっているか説明します。

ポート 設定
シリアルポート 有効
Bluetooth 有効
シリアルポートの設定

シリアルポートを有効にしたので、「/boot/config.txt」の「enable_uart=1」になります。

[all]
enable_uart=1

次の図のように、UART0がBluetoothに接続されていて、UART1が有効になりました。

シリアルポート有効

Linuxデバイスとして、「/dev/ttyAMA0」と「/dev/ttyS0」が有効になり、GPIOの14,15にTXDとRXDが割り当てられます。

$ ls -l /dev/ttyAMA*
crw-rw---- 1 root dialout 204, 64  6月  7 21:25 /dev/ttyAMA0
$ ls -l /dev/ttyS*
crw-rw---- 1 root dialout 4, 64  6月  7 21:25 /dev/ttyS0
$ ls -l /dev/serial*
lrwxrwxrwx 1 root root 5  6月  7 21:25 /dev/serial0 -> ttyS0
lrwxrwxrwx 1 root root 7  6月  7 21:25 /dev/serial1 -> ttyAMA0

$ raspi-gpio get 14-15
GPIO 14: level=1 fsel=2 alt=5 func=TXD1 pull=NONE
GPIO 15: level=1 fsel=2 alt=5 func=RXD1 pull=UP

シリアルポート有効、PL011をプライマリに変更

シリアルポートを有効にした状態として、次の設定の時にRaspberry Piがどうなっているか説明します。

ポート 設定
シリアルポート 有効
Bluetooth 有効
PL011 プライマリに変更
mini UART Bluetoothに変更

シリアルポートを有効にしたので、「/boot/config.txt」の「enable_uart=1」になります。

「vi」や「nano」などのエディタにて次の項目を追記します。

$ sudo nano /boot/config.txt

mini UARTをBluetoothに変更するため、「dtoverlay=miniuart-bt」を追記します。

mini UARTを正常に使うために、クロック設定「core_freq=250」を追記します。(このクロック設定の変わりに、「force_turbo=1」でも大丈夫です。どちらかを設定してください。)

追記したら、Raspberry Piを再起動すると設定が反映されます。

[all]
enable_uart=1
dtoverlay=miniuart-bt
core_freq=250

次の図のように、UART0がシリアルポートになり、UART1にBluetoothが接続されます。また、プライマリとセカンダリが入れ替わります。

mini UARTにBluetooth接続

Linuxデバイスとして、「/dev/ttyAMA0」と「/dev/ttyS0」が有効になり、プライマリ「/dev/serial0」のリンク先が「ttyAMA0」に変わり、セカンダリ「/dev/serial1」のリンク先が「ttyS0」に変わります。

$ ls -l /dev/ttyAMA*
crw-rw---- 1 root dialout 204, 64  6月  7 23:31 /dev/ttyAMA0
$ ls -l /dev/ttyS*
crw-rw---- 1 root dialout 4, 64  6月  7 23:31 /dev/ttyS0
$ ls -l /dev/serial*
lrwxrwxrwx 1 root root 7  6月  7 23:31 /dev/serial0 -> ttyAMA0
lrwxrwxrwx 1 root root 5  6月  7 23:31 /dev/serial1 -> ttyS0

$ raspi-gpio get 14-15
GPIO 14: level=1 fsel=4 alt=0 func=TXD0 pull=NONE
GPIO 15: level=1 fsel=4 alt=0 func=RXD0 pull=UP

シリアルポート有効、Bluetooth無効

シリアルポートを有効にした状態として、次の設定の時にRaspberry Piがどうなっているか説明します。

ポート 設定
シリアルポート 有効
Bluetooth 無効

シリアルポートを有効にしたので、「/boot/config.txt」の「enable_uart=1」になります。

「vi」や「nano」などのエディタにて次の項目を追記します。

$ sudo nano /boot/config.txt

Bluetoothを無効にするため、「dtoverlay=disable-bt」を追記します。

追記したら、Raspberry Piを再起動すると設定が反映されます。

[all]
enable_uart=1
dtoverlay=disable-bt

次の図のように、UART0がシリアルポートになり、UART1は存在するがどこにも接続されなくて、Bluetoothが無効になります。

Bluetooth無効

タスクバーの左側のBluetoothアイコンが消えます

Bluetoothアイコンが消える

Linuxデバイスとして、「/dev/ttyAMA0」が有効になり、「/dev/ttyS0」も存在していますが、シリアル通信では使えません。

$ ls -l /dev/ttyAMA*
crw-rw---- 1 root dialout 204, 64  6月  7 23:46 /dev/ttyAMA0
$ ls -l /dev/ttyS*
crw-rw---- 1 root dialout 4, 64  6月  7 23:46 /dev/ttyS0
$ ls -l /dev/serial*
lrwxrwxrwx 1 root root 7  6月  7 23:46 /dev/serial0 -> ttyAMA0
lrwxrwxrwx 1 root root 5  6月  7 23:46 /dev/serial1 -> ttyS0

$ raspi-gpio get 14-15
GPIO 14: level=1 fsel=4 alt=0 func=TXD0 pull=NONE
GPIO 15: level=1 fsel=4 alt=0 func=RXD0 pull=UP

「/dev/ttyS0」(UART1)が通信で使えない理由として、UART0とUART1のデフォルトのポートがどちらも同じGPIO14、GPIO15が割り当てられます。

「raspi-gpio get 14-15」コマンドで有効なのは「TXD0」「RXD0」なので、UART0が割り当てられています。

Helpを確認すると、オプションでGIPOの割り当てを変更できるようですが、GPIO32、GPIO33などはRaspberry Piの40PINのコネクタには存在しないため通常の方法では使えません。

$ dtoverlay -h uart0
Name:   uart0

Info:   Change the pin usage of uart0

Usage:  dtoverlay=uart0,<param>=<val>

Params: txd0_pin                GPIO pin for TXD0 (14, 32 or 36 - default 14)

        rxd0_pin                GPIO pin for RXD0 (15, 33 or 37 - default 15)

        pin_func                Alternative pin function - 4(Alt0) for 14&15,
                                7(Alt3) for 32&33, 6(Alt2) for 36&37

$ dtoverlay -h uart1
Name:   uart1

Info:   Change the pin usage of uart1

Usage:  dtoverlay=uart1,<param>=<val>

Params: txd1_pin                GPIO pin for TXD1 (14, 32 or 40 - default 14)

        rxd1_pin                GPIO pin for RXD1 (15, 33 or 41 - default 15)

UART2を有効、シリアルポート有効

シリアルポートを有効にした状態として、次の設定の時にRaspberry Piがどうなっているか説明します。

ポート 設定
シリアルポート 有効
Bluetooth 有効
UART2 有効

シリアルポートを有効にしたので、「/boot/config.txt」の「enable_uart=1」になります。

「vi」や「nano」などのエディタにて次の項目を追記します。

$ sudo nano /boot/config.txt

UART2を有効にするため、「dtoverlay=uart2」を追記します。

追記したら、Raspberry Piを再起動すると設定が反映されます。

[all]
enable_uart=1
dtoverlay=uart2

次の図のように、UART0はBluetoothに接続され、UART1とUART2が有効になります。

UART2を追加

Linuxデバイスとして、「/dev/ttyAMA0」と「/dev/ttyS0」が有効になり、UART0用にGPIOの14,15にTXDとRXDが割り当てられます。さらに「/dev/ttyAMA1」が追加有効になって、UART2用にGPIO0,1にTXDとRXDが割り当てられます。

$ ls -l /dev/ttyAMA*
crw-rw---- 1 root dialout 204, 64  6月  8 00:22 /dev/ttyAMA0
crw-rw---- 1 root dialout 204, 65  6月  8 00:22 /dev/ttyAMA1
$ ls -l /dev/ttyS*
crw-rw---- 1 root dialout 4, 64  6月  8 00:22 /dev/ttyS0
$ ls -l /dev/serial*
lrwxrwxrwx 1 root root 5  6月  8 00:22 /dev/serial0 -> ttyS0
lrwxrwxrwx 1 root root 7  6月  8 00:22 /dev/serial1 -> ttyAMA0

$ raspi-gpio get 0-15
GPIO 0: level=1 fsel=3 alt=4 func=TXD2 pull=NONE
GPIO 1: level=1 fsel=3 alt=4 func=RXD2 pull=UP
GPIO 2: level=1 fsel=0 func=INPUT pull=UP
GPIO 3: level=1 fsel=0 func=INPUT pull=UP
GPIO 4: level=1 fsel=0 func=INPUT pull=UP
GPIO 5: level=1 fsel=0 func=INPUT pull=UP
GPIO 6: level=1 fsel=0 func=INPUT pull=UP
GPIO 7: level=1 fsel=0 func=INPUT pull=UP
GPIO 8: level=1 fsel=0 func=INPUT pull=UP
GPIO 9: level=0 fsel=0 func=INPUT pull=DOWN
GPIO 10: level=0 fsel=0 func=INPUT pull=DOWN
GPIO 11: level=0 fsel=0 func=INPUT pull=DOWN
GPIO 12: level=0 fsel=0 func=INPUT pull=DOWN
GPIO 13: level=0 fsel=0 func=INPUT pull=DOWN
GPIO 14: level=1 fsel=2 alt=5 func=TXD1 pull=NONE
GPIO 15: level=1 fsel=2 alt=5 func=RXD1 pull=UP

UART3を有効、シリアルポート有効(UART4、UART5も同じ)

シリアルポートを有効にした状態として、次の設定の時にRaspberry Piがどうなっているか説明します。

ポート 設定
シリアルポート 有効
Bluetooth 有効
UART3 有効

シリアルポートを有効にしたので、「/boot/config.txt」の「enable_uart=1」になります。

「vi」や「nano」などのエディタにて次の項目を追記します。

$ sudo nano /boot/config.txt

UART3を有効にするため、「dtoverlay=uart3」を追記します。

追記したら、Raspberry Piを再起動すると設定が反映されます。

[all]
enable_uart=1
dtoverlay=uart3

次の図のように、UART0はBluetoothに接続され、UART1とUART3が有効になります。

UART3を追加

Linuxデバイスとして、「/dev/ttyAMA0」と「/dev/ttyS0」が有効になり、UART0用にGPIOの14,15にTXDとRXDが割り当てられます。さらに「/dev/ttyAMA1」が追加有効になって、UART3用にGPIO4,5にTXDとRXDが割り当てられます。

UART2~UART5の1つのポートのみを有効にした場合「/dev/ttyAMA1」が追加されます。

$ ls -l /dev/ttyAMA*
crw-rw---- 1 root dialout 204, 64  6月  8 00:37 /dev/ttyAMA0
crw-rw---- 1 root dialout 204, 65  6月  8 00:37 /dev/ttyAMA1
$ ls -l /dev/ttyS*
crw-rw---- 1 root dialout 4, 64  6月  8 00:37 /dev/ttyS0
$ ls -l /dev/serial*
lrwxrwxrwx 1 root root 5  6月  8 00:37 /dev/serial0 -> ttyS0
lrwxrwxrwx 1 root root 7  6月  8 00:37 /dev/serial1 -> ttyAMA0

$ raspi-gpio get 0-15
GPIO 0: level=1 fsel=0 func=INPUT pull=UP
GPIO 1: level=1 fsel=0 func=INPUT pull=UP
GPIO 2: level=1 fsel=0 func=INPUT pull=UP
GPIO 3: level=1 fsel=0 func=INPUT pull=UP
GPIO 4: level=1 fsel=3 alt=4 func=TXD3 pull=NONE
GPIO 5: level=1 fsel=3 alt=4 func=RXD3 pull=UP
GPIO 6: level=1 fsel=0 func=INPUT pull=UP
GPIO 7: level=1 fsel=0 func=INPUT pull=UP
GPIO 8: level=1 fsel=0 func=INPUT pull=UP
GPIO 9: level=0 fsel=0 func=INPUT pull=DOWN
GPIO 10: level=0 fsel=0 func=INPUT pull=DOWN
GPIO 11: level=0 fsel=0 func=INPUT pull=DOWN
GPIO 12: level=0 fsel=0 func=INPUT pull=DOWN
GPIO 13: level=0 fsel=0 func=INPUT pull=DOWN
GPIO 14: level=1 fsel=2 alt=5 func=TXD1 pull=NONE
GPIO 15: level=1 fsel=2 alt=5 func=RXD1 pull=UP

UART2~UART5を有効、シリアルポート有効

シリアルポートを有効にした状態として、次の設定の時にRaspberry Piがどうなっているか説明します。

ポート 設定
シリアルポート 有効
Bluetooth 有効
UART2 有効
UART3 有効
UART4 有効
UART5 有効

シリアルポートを有効にしたので、「/boot/config.txt」の「enable_uart=1」になります。

「vi」や「nano」などのエディタにて次の項目を追記します。

$ sudo nano /boot/config.txt

UART2~5を有効にするため、「dtoverlay=uart2」「dtoverlay=uart3」「dtoverlay=uart4」「dtoverlay=uart5」を追記します。

追記したら、Raspberry Piを再起動すると設定が反映されます。

[all]
enable_uart=1
dtoverlay=uart2
dtoverlay=uart3
dtoverlay=uart4
dtoverlay=uart5

次の図のように、UART0はBluetoothに接続され、UART1~UART5が有効になります。

Linuxデバイスとして、「/dev/ttyAMA0」と「/dev/ttyS0」が有効になり、UART0用にGPIOの14,15にTXDとRXDが割り当てられます。さらに「/dev/ttyAMA1」「/dev/ttyAMA2」「/dev/ttyAMA3」「/dev/ttyAMA4」が有効になって、UART2用にGPIO0,1、UART3用にGPIO4,5、UART4用にGPIO8,9、UART5用にGPIO12,13それぞれにTXDとRXDが割り当てられます。

$ ls -l /dev/ttyAMA*
crw-rw---- 1 root dialout 204, 64  6月  8 00:51 /dev/ttyAMA0
crw-rw---- 1 root dialout 204, 65  6月  8 00:51 /dev/ttyAMA1
crw-rw---- 1 root dialout 204, 66  6月  8 00:51 /dev/ttyAMA2
crw-rw---- 1 root dialout 204, 67  6月  8 00:51 /dev/ttyAMA3
crw-rw---- 1 root dialout 204, 68  6月  8 00:51 /dev/ttyAMA4
$ ls -l /dev/ttyS*
crw-rw---- 1 root dialout 4, 64  6月  8 00:51 /dev/ttyS0
$ ls -l /dev/serial*
lrwxrwxrwx 1 root root 5  6月  8 00:51 /dev/serial0 -> ttyS0
lrwxrwxrwx 1 root root 7  6月  8 00:51 /dev/serial1 -> ttyAMA0

$ raspi-gpio get 0-15
GPIO 0: level=1 fsel=3 alt=4 func=TXD2 pull=NONE
GPIO 1: level=1 fsel=3 alt=4 func=RXD2 pull=UP
GPIO 2: level=1 fsel=0 func=INPUT pull=UP
GPIO 3: level=1 fsel=0 func=INPUT pull=UP
GPIO 4: level=1 fsel=3 alt=4 func=TXD3 pull=NONE
GPIO 5: level=1 fsel=3 alt=4 func=RXD3 pull=UP
GPIO 6: level=1 fsel=0 func=INPUT pull=UP
GPIO 7: level=1 fsel=0 func=INPUT pull=UP
GPIO 8: level=1 fsel=3 alt=4 func=TXD4 pull=NONE
GPIO 9: level=1 fsel=3 alt=4 func=RXD4 pull=UP
GPIO 10: level=0 fsel=0 func=INPUT pull=DOWN
GPIO 11: level=0 fsel=0 func=INPUT pull=DOWN
GPIO 12: level=1 fsel=3 alt=4 func=TXD5 pull=NONE
GPIO 13: level=1 fsel=3 alt=4 func=RXD5 pull=UP
GPIO 14: level=1 fsel=2 alt=5 func=TXD1 pull=NONE
GPIO 15: level=1 fsel=2 alt=5 func=RXD1 pull=UP

動作確認

Raspberry Pi側はGtkTermで、パソコン側はTera Termを使用して以下の組み合わせで動作テストをしました。

2021/6/8現在のRaspberry Pi OSに「upgrade」コマンドにて最新にして動作確認をしています。

$ sudo apt-get update
$ sudo apt-get upgrade

Raspberry Pi OS
Release date: May 7th 2021
Kernel version: 5.10

$ uname -a
Linux raspberrypi 5.10.17-v7l+ #1421 SMP Thu May 27 14:00:13 BST 2021 armv7l GNU/Linux

〇印の所が同時にボートオープンしてテストしています。

ポート タイプ 組み合わせ
UART0 PL011
UART1 mini UART
UART2 PL011
UART3 PL011
UART4 PL011
UART5 PL011

GtkTermでのテストでは、上記の組み合わせでは問題なく動作しました。

シリアル通信、Pythonサンプルプログラム

Pythonにて、シリアル通信をするサンプルプログラムで「serial_sample.py」を作成します。

プログラムは起動すると、受信スレッドが立ち上がってパソコン側キーボード入力したキーコードを受信して、エコーバックします。

終了するためには、パソコン側で「Enter」キーを入力すると、受信スレッドが終了してプログラムも終了します。

import threading
import serial
import logging

logging.basicConfig(level=logging.DEBUG, format='%(threadName)s: %(message)s')

# シリアル通信ベースクラス
class SerialBase:
    def __init__(self):
        # commの初期化
        self.comm = ''
        # ポートオープンフラグ
        self.isOpen = False
        # タイムアウトフラグ
        self.isTimeOut = False
        # Threadの終了フラグ
        self.isStop = False
        # 受信データバッファ
        self.receiveBuffer = bytearray()

    def IsOpen(self):
        return self.isOpen

    def IsTimeOut(self):
        return self.isTimeOut

    def IsStop(self):
        return self.isStop

    def Stop(self):
        self.isStop = True

    def Write(self, data):
        self.comm.write(data)

    def Read(self):
        return self.comm.read()

    def Open(self, ser, port, baud='115200'):
        try:
            logging.debug("Serial port open.")
            self.comm = ser
            self.comm = serial.Serial(port, baud, timeout=0.01)
            self.isOpen = True
        except Exception as err:
            logging.error("Serial port open error.")
            logging.error(type(err))
            logging.error(err.args)
            logging.error(err)
            self.isOpen = False
        return self.isOpen
    
    def Close(self):
        self.Stop()
        if self.IsOpen():
            logging.debug("Serial port close.")
            self.comm.close()
            self.isOpen = False

# 受信スレッド
def receiveWorker(ser):
    logging.debug("receiveWorker Start.")

    # 受信データをエコーバックし、改行したら終了します
    while not ser.IsStop():
        buff = ser.Read()
        if len(buff) > 0:
            ser.Write(buff)
            if buff==b'\r':
                break

    logging.debug("receiveWorker Stop.")

def main():
    print("Serial sample.")

    # シリアルクラス
    ser = SerialBase()
    ser.Open(ser, '/dev/serial0', '115200')

    ser.Write(b'\r\nStart.\r\n')
    th = threading.Thread(target=receiveWorker, args=(ser,))
    th.start()

    th.join()
    ser.Close()

if __name__ == "__main__":
    main()

作成した「touch_sample.py」を次のコマンドにて実行します。

$ python3 serial_sample.py 

プログラムを実行すると「Start.」と表示されるので、適当なキーを入力します。終了する場合は「Enter」を押します。

パソコン側のターミナル画面

まとめ

Raspberry Piのシリアルポートは、mini UARTとPL011が設定によって、プライマリとセカンダリ入れ替わったりして分かりにくいと思います。

そういった分かりにくい部分が解消されたら幸いです。

以上、「Raspberry Piのシリアルポート設定(UART)を理解する」の内容でした。

-Raspberry Pi

© 2021 Toki Blog(トキブログ)