記事概要
STM32 CubeIDEが公開されたことを記念して,STM32の基本的な使い方を確認します.
本記事では,マイコン内蔵のADコンバータを使ってアナログ的にピンの電圧を読み取るプログラムを作成します.
本ブログを書くにあたって下記リンク先を大いに参考にさせていただいています.
ADC in STM32 using HAL Libraries - Controllerstech.com
STM32でADCをやってみる1(レギュラ変換) - がれすたさんのDIY日記
http://jazz-love.ddo.jp/wordpress/2016/03/02/stm32アナログ入力を試す/
環境
- STM32CubeIDE 1.0.0
- macOS 10.14.5
- NUCLEO-F401RE
STM32 CubeIDEについて(読まなくてもよい)
STM32 CubeIDEはSTM32用の統合開発環境です.
2019年4月にリリースされたものですが,実態はこれまでも存在し,広く使われていた「STM32CubeMX」,「SW4STM32」の2つのアプリケーションを統合したものです.
CubeMXはマイコンの設定を作成するためのアプリケーションです.
SW4STM32はプログラムを書いて実行するためのアプリケーションです.
これまではCubeMXで作った設定データをSW4STM32に取り込んで作る必要がありましたが,Cube IDEで統合されたため,とてもわかりやすくなりました.
まだネット上にはCubeIDEを使った記事は少ないため,CubeMXやSW4STM32を使った情報が多くあります.
調べる際には上記のワードも覚えておくとよいでしょう.
CubeMX,SW4STM32は今後アップデートされなくなるため,今から始める方はSTM32CubeIDEで練習するのがよいでしょう.
環境構築について
STM32 CubeIDEのインストール方法はこちらをご覧ください.
プロジェクトの作成
プロジェクト作成方法はUART通信のときと同じです.こちらの記事をご覧ください.
CubeMX
プロジェクト作成をするとこの画面にたどり着くと思いますので,そこで設定が必要になります.
既存のプロジェクトを活用する人は左メニューの「(プロジェクト名).ioc」(黒丸で囲ったところ)をダブルクリックするとこの画面が開くはずです.
STM32ではマイコンの周辺機能(Peripheral)を様々なピンに割り当てることができます(緑のピンは割り当て済み).
この画面で,タイマーなどマイコンの機能をピンに割り当てることで,設定や初期化の内容がプログラムに反映されます.
今後機能を増やしていく際にはこちらの画面でピンを設定して,プログラムを記述という作業を繰り返していくことになります.
ADCのためのピン設定
ピンへの機能割り当て
ADCを使うためにはADCに対応しているポートを使う必要があります.
STM32F401REには16ピン分の処理に対応しているため,それらの対応ポートのうちからいずれかを選びます.
今回はArduino互換ポートのA0に接続されている,PA0に割り当てたいと思います.
PA0を選択して,一覧からADC1_IN0を選びます.
するとPA0が緑色になります.
今回は詳細の設定はいじりません.
いじる必要がある場合は下記の画像のようにメニューを出すことで設定があらわれます(今回は必要ありません).
それではプログラムに移動します.
ここで一旦保存します.
すると以下のダイアログが出てきます.Yesを押すことでピンの設定の情報がmain.cに書き加えられます.
さて,終わったらmainプログラムを開きましょう.
プログラムの編集
プログラムを書く上での注意
これがmainプログラムです.すでにたくさんの設定が書き込まれています.
mainプログラムを下にスクロールすると,main()関数が見えてきます.
main関数の中もいろいろと記述済みですが,こちらを追記していきます.
その際に注意しなければならないのが「自分で書いたプログラムが勝手に削除される場合がある」ことです.
main.cはマイコンの設定に応じて自動で書き換えられますが,その際,「指定の場所」以外に書かれたプログラムは削除されていしまいます.
必ず,
/*USER CODE BEGIN xxx */ /*USER CODE END xxx */
の間に記述するようにしてください.
またこのコメントを消さないでください.
インクルード文
今回はC言語の標準入出力関数などをインクルードして
- sprintf()
- strlen()
を使用したいので,
- stdio.h
- string.h
をインクルードします.
以下のように,「USER CODE BEGIN Includes」の下に2行追加します.
/* Includes ------------------------------------------------------------------*/ #include "main.h" /* Private includes ----------------------------------------------------------*/ /* USER CODE BEGIN Includes */ #include "stdio.h" #include "string.h" /* USER CODE END Includes */
main関数
main関数には「USER CODE BEGIN〜END 2」の中に2行と「USERCODE BEGIN〜END WHILE」の中に10行ほど追記します.
/* USER CODE BEGIN 2 */ int val; //AD変換後の数値を入れる char sval[100]; //UARTで送る文字列を入れる /* USER CODE END 2 */ /* Infinite loop */ /* USER CODE BEGIN WHILE */ while (1) { //ADC受け取り HAL_ADC_Start(&hadc1); HAL_ADC_PollForConversion(&hadc1, 100); //ADC変換終了を待機 HAL_ADC_Stop(&hadc1); val = HAL_ADC_GetValue(&hadc1); //UART送信 sprintf(sval , "%d\r\n",val); HAL_UART_Transmit( &huart2, sval, strlen(sval) + 1, 0xFFFF); //待機(100[ms]) HAL_Delay( 100 ); /* USER CODE END WHILE */ /* USER CODE BEGIN 3 */ } /* USER CODE END 3 */
HAL_ADC_Start()関数でAD変換処理を開始します.連続変換を設定しない場合、この関数の呼び出しは読み取るたびに必要です(呼ばないと値が変化しない).
HAL_ADC_PollForConversion()関数でAD変換処理の終了を待機します.100は最大の待ち時間[ms]です.
HAL_ADC_Stop()関数でAD変換処理を終了します.なお,この関数を呼ばなくても問題なく動きます.消費電力の削減効果でもあるのでしょうか.
val=HAL_ADC_GetValue()関数でAD返還後の値を変数valに格納します.
あとはこの値を定期的に送って表示するだけです.