前回、STM32F446をUSART3経由とUSB経由で書込みができました。回路的には問題なさそうです。
今回は、パソコン↔STM32F446間でUART通信を行います。
UARTの設定
前回、STM32F446 CubeMXセットでUSART3の設定を行いました。
その続きとなります。
プロジェクトコピー
STM32CubeIDEで新たにプロジェクトを作成しますが、毎回STM32CubeMXの設定をするのは面倒なので、前回作ったLED_Blinkをもとにコピー&ペーストしてきます。
Project nameの変更をします。
各種設定が入っているiocファイルもRenameします。
Uartと入力してOKを押す。
次は、デバッグファイルの削除を行います。makefileに前回のプロジェクトの設定が残っているようです。
最後に、Clean Projectを押して、
Run Uart Debugをすれば(Configurationsは再設定することになる)、無事ST-LINK経由で書込みができます。
これでプロジェクトのコピーは完了です。
周波数の再設定
周波数の設定を前回やりましたが、よくよく見返すと外付けの共振子に切り替えていなかったので、各種マイコン周辺機能を最大性能で使えるようにしてみます。
Uart.iocのClock Configurationタブを開きます。
STM32F446はCPU周波数を最大180MHzまで行けるようなので、PLL(Phase Locked Loop:位相同期ループ)を色々変更してみました。STM32は細かい調整ができて便利です。
最大で使おうとすると、USB部分で赤い設定不可のところが出てきました。
USBを使う場合は、48MHzにする必要があるため、若干調周波数を落としてみました。
とりあえず、この設定で進めてみます。
UARTの設定
STM32CubeMXのUSART3→Configuration→Parameter Settingsで、ボーレート等が変更できます。今回はデフォルトのままにします。
これで保存を押すと、ソースコードが自動生成されます。
main.cをみてみます。MX_USART3_UART_Init()関数が生成されており、ボーレート等も入力済みです。上のコメント書式を見ると、Doxygenに対応しているようですね。
Doxygen
試しにDoxygenで表示してみます。
GUIとグラフィカル表示オプションもついでにインストール。
$ sudo apt-get install doxygen doxygen-gui graphviz
Doxygenウィザードを起動します。
$ doxywizard
各種設定をして、
HTML出力して、ファイルを開くと、こんな感じで表示されました。
main.c は特に何かしてるわけでもないので、中身は説明が書いてあるくらい。
プログラム
HALドキュメントを見ると3つの操作モードのAPIが用意されているようです。
- Polling mode IO operation(順次処理モード)
- Interrupt mode IO operation(割り込みモード)
- DMA mode IO operation(DMAモード)
送信プログラム
簡単そうな、Polling mode IO operationのHAL_UART_Transmit関数を試しに使ってみます。
この関数を使う場合、以下のファイルを使うはずなので、どうなってるか見てみました。
- stm32f4xx_hal_uart.c
- stm32f4xx_hal_uart.h
そうすると、以下のようにincludeされていました。
main.h
/* Includes ------------------------------------------------------------------*/ #include "stm32f4xx_hal.h"
stm32f4xx_hal.h
/* Includes ------------------------------------------------------------------*/ #include "stm32f4xx_hal_conf.h"
stm32f4xx_hal_conf.h
#define HAL_UART_MODULE_ENABLED //コメント外れて有効化
#ifdef HAL_UART_MODULE_ENABLED #include "stm32f4xx_hal_uart.h" #endif /* HAL_UART_MODULE_ENABLED */
抽象化されててわかりづらいですが、便利に使えるようにしてあるみたいです。
関数内部の引数ですが、1つ目は既に自動でコード生成されています。
main.c
UART_HandleTypeDef huart3;
main.cに以下を追加して、実行する。
/* USER CODE BEGIN 2 */ char databuff[] = "Hello World!\r\n"; HAL_UART_Transmit(&huart3, (uint8_t *)databuff, sizeof(databuff), 100); /* USER CODE END 2 */
端末でシリアル接続を行ってみる。
$ sudo screen /dev/ttyUSB0 115200
リセットボタンを押すと、1度だけHello Word!が表示される。
ctrl+a,k,yでscreen終了。
受信プログラム
送信関数と対を成す、HAL_UART_Receive関数が用意されています。
HAL_StatusTypeDefという構造体で定義された関数のリターン値を使って、PCから受信したかどうかを判断するようです。データシートを参照します。
HAL_OKでいいようです。
割り込みを使わない受信は、while文の中にいれるので、
/* USER CODE BEGIN 2 */ char databuff1[] = "Hello World!\r\n"; char databuff2[1]; HAL_UART_Transmit(&huart3, (uint8_t *)databuff1, sizeof(databuff1), 100); /* USER CODE END 2 */
/* USER CODE BEGIN WHILE */ while (1) { /* USER CODE END WHILE */ /* USER CODE BEGIN 3 */ if(HAL_UART_Receive(&huart3, (uint8_t *)databuff2, sizeof(databuff2), 10) == HAL_OK){ HAL_UART_Transmit(&huart3, (uint8_t *)databuff2, sizeof(databuff2), 100); } } /* USER CODE END 3 */
実行すると、シリアルターミナル画面はキーボード入力を返信するようになります。
次は、USB通信を行います。
参考サイト:
Linuxにおけるシリアルポートのトラブルシューティング
Doxygen マニュアル
STM32でシリアル通信してみる ポーリング編