【便利】STM32CubeIDEでprintf【UART編】

printfは非常に有用なデバッグ手段で、STM32CubeIDEでprintfを使いたいという方もいらっしゃるでしょう。本記事ではUARTを使って、STM32CubeIDEでprintfが使えるようにするまでの手順をわかりやすく解説します。

 

はじめに下記の画像をご覧になってください。STM32CubeIDEのデバッグ実行中の画面をキャプチャしてものです。printfで『Hello World!!』を出力するコードを書いて、それが画面下部のターミナルで出力されていることがわかるかと思います。

 

UARTを使ってIDE上でprintf出力

 

printfの実現方法はいくつかありますが、UARTを使う方法では、以下のメリットがあります。

 

  • デバッグ機能とprintf出力を平行して利用できる
  • IDE内のターミナルでprintfの出力を見ることができる
  • そこそこ速い通信ができるため、処理の邪魔になりにくい

 

 

UARTを使ったprintfシステム

 

とても便利な方法ですが、デメリットもあります。

 

  • UARTを1つ潰してしまう

 

当たり前ですがUARTを使う以上仕方ないことですね。UARTを1つ潰してしまいますが、上記のメリットを考えると、かなり便利でおすすめできる方法です。

前置きが長くなりましたが、ここからは実際にprintfできるまでの方法を解説していきます。

 

1.前提条件

今回は下記の環境を前提に話を進めます。NUCLEOとはUSBケーブルで接続しているだけですが、デバッグ通信とUART2との通信(仮想シリアルポート)の両方の通信ができます。

もちろんこの環境でなくても、パソコンとデバッグケーブル・UART(シリアルポート)が繋がっている環境であれば大丈夫です。

 

  • STM32CubeIDE ver.1.00
  • NUCLEO-F401RE

 

2.printfの準備

2-1.UARTの初期化コード生成

まずはDevice Configuration Tool(CubeMX)を使ってプロジェクトを作りましょう。ここではUARTの設定だけ説明しますね。

 

  • Pinout & Configurationタブ→Connectivity→USART2→Mode
  • ModeをDisableからAsynchronousに変更してください
  • それ以外の設定は下記の画像にならって設定してください

 

USART2の設定

 

Baud Rateは通信速度なので、もっと高速にしたい時はもっと大きな値にしてください。

 

設定が終わったらコードを自動生成してください。

 

2-2.printfの実装

printfを実装してUARTでテキストを送信するようにしてあげましょう。下記のコードをコピペしてください。

 

main.c

/* USER CODE BEGIN 4 */
int _write(int file, char *ptr, int len)
{
  HAL_UART_Transmit(&huart2,(uint8_t *)ptr,len,10);
  return len;
}
/* USER CODE END 4 */

 

printfの内部で実際に書き込み処理をしているのは_write()関数です。_write()関数はweak宣言されているので、新しく作って上書きした形になります。

 

2-3.printfの初期化

printfはこれだけでは動作せず、初期化してあげる必要があります。printfを呼び出す前に、例えば下記のように1回だけ実行してあげてください。

 

main.c

int main(void)
{
  /* USER CODE BEGIN 1 */
    setbuf(stdout, NULL);
  /* USER CODE END 1 */

 

後、stdio.hのインクルードは忘れずにしておいてくださいね。言うまでもないとは思いますが、念のため。

 

main.c

/* USER CODE BEGIN Includes */
#include <stdio.h>
/* USER CODE END Includes */

 

2-4.printfの追加

とりあえず今回は定期的に『Hello World!!』を出力するようなプログラムを書きました。

 

main.c

/* USER CODE BEGIN WHILE */
while (1)
{
  /* USER CODE END WHILE */
    printf("Hello World!!\r\n");
    HAL_Delay(1000);
  /* USER CODE BEGIN 3 */
}
/* USER CODE END 3 */

 

3.printfの動作確認

最終的にはSTM32CubeIDE上のターミナルで確認しますが、準備に時間がかかりますし、ここまでの内容に問題がないか確認するために、Tera Termなどを使って動作確認しておきましょう。

Tera Termなどのターミナルがない方や、自身のある方は読み飛ばしていただいても構いません。

 

Tera Termの設定を、先ほどのUARTの設定に合わせてあげます。

 

TeraTermの設定

 

STM32CubeIDEでデバッグ実行を開始して、Tera Termに『Hello World!!』が出力されることを確認しましょう。

 

TeraTermの出力

 

出力されましたね!

これだけでもprintfを使ったデバッグはできますが、ターミナルプログラムを別途立ち上げておくのは、やはり面倒です。以降では、ターミナルをSTM32CubeIDEの中で立ち上げる方法を解説します。

 

4.STM32CubeIDEにターミナルを入れる

STM32CubeIDEにターミナルを入れるのはちょっと面倒ですが、くじけずやりましょう。難しいところはないので安心してください。

 

ソフトウェア構成を図示すると下記のようになります。

TM Terminalがターミナルプログラム本体で、Eclipseのプラグインです。RXTXはシリアル通信するためのプログラムです。2つありますが、Javaにインストールする方が基本ソフトウェアで、もう1つの方がそれを利用するEclipseのプラグインです。

 

TM Terminalのソフトウェア構成

 

4-1.RXTXをJavaにインストール

下記のURLから『RXTXcommon.jar』と『rxtxSerial.dll』の2つのファイルをダウンロードしてください。

http://jlog.org/rxtx-win.html

 

ダウンロードしたファイルはそれぞれ下記の表の通りにコピーしてください。

 

ファイル コピー先
RXTXcommon.jar C:\ST\STM32CubeIDE_1.0.0\STM32CubeIDE\jre\lib\ext
rxtxSerial.dll C:\ST\STM32CubeIDE_1.0.0\STM32CubeIDE\jre\bin

 

4-2.RXTXのプラグインをインストール

  • STM32CubeIDEのメニュー→Help→Install New Software…
  • Addボタンをクリックして下記のURLを追加してください
    http://rxtx.qbang.org/eclipse
  • 最新版のRXTXをインストールしてください

 

RXTXプラグインのインストール

 

4-3.TM Terminalをインストール

  • STM32CubeIDEのメニュー→Help→Install New Software…
  • Work with:でEclipseのリポジトリを選択してください
    https://download.eclipse.org/releases/2019-03
    ※2019-03はIDEのバージョンによって変わります
  • General Purpose Toolsの中にある『TM Terminal』と『TM Terminal Serial Connector Extensioons』を選択し、インストールしてください

 

TM Terminalのインストール

 

5.STM32CubeIDEのターミナルにprintf出力

準備が整いましたのでSTM32CubeIDE内でターミナルを起動し、printf出力を確認しましょう。

 

5-1.ターミナルの起動

  • メニュー→Window→Show View→Other…
  • Terminal→Terminalをクリックしてください
  • Terminalビューのパソコンのマークをクリックし、下記の画像を参考にシリアルターミナルの設定をしてください

 

シリアルターミナルの設定

 

5-2.デバッグを実行

デバッグを実行してください。Terminalビューにprintfの出力が表示されます。

 

printf出力

 

出力されましたね!

 

6.おわりに

printfを使ったデバッグは今でも有用なデバッグ手段です。本記事では、UARTを使ってprintfを実現する方法を解説しました。

UARTを使うことで、デバッグ実行と並行した利用、IDE内のターミナルでの出力確認、そこそこの高速通信というメリットがあります。UARTを1つ潰す以上の価値があるでしょう。

この記事で皆さんのデバッグが少しでも楽になれば幸いです。

 

関連:STM32CubeIDEのprintfでfloatが使えない件の対処方法

関連:STM32CubeIDEでprintf【SWO編】

関連:STM32CubeIDEでprintf【Semihosting編】