概要
Andy Brown氏によるSTM32向けC++ライブラリである stm32plus(andysworkshop / stm32plus) を使用する際のメモ.
便利なのだが,ザ・C++という感じのコードでC++にあまり馴染みがない人にとっては使いづらいと思うので,コードの解説も加えながらメモを残したい.
なお,最新の情報はstm32plusのGitHubレポジトリに掲載されているので,併せて確認してほしい.
セットアップ
stm32plusはスタティックライブラリとしてプロジェクトに組み込むことを想定しているため,事前にビルドが必要である.
下準備
確かWindowsだとコマンドプロンプトの仕様上8192文字以上のコマンドを受け付けてくれなくてビルドが失敗するので,CygwinやMingW32などを使用したほうが良いかもしれない.
ほかにもSConsと呼ばれるmake系のツールを使用するので,それを予めインストールしておく.
Ubuntuなら,
$ sudo apt-get install scons
|
でインストールできる.
また,Doxygenでドキュメントを生成できるようになっているため,
$ sudo apt-get install doxygen
|
しておくと便利.
レポジトリをclone
$ git clone https://github.com/andysworkshop/stm32plus.git $ cd stm32plus
|
ビルド
$ scons mode=debug mcu=f4 hse=12000000 -j9
|
SConsに渡すオプションは以下の通り.
名称 |
説明 |
値 |
mode |
最適化のかけ方を変える |
debug (デバッグ情報あり,最適化なし), fast (-O3 に相当), small (-Os に相当) |
mcu |
シリーズの選択 |
f1hd (STM32F103), f1cle (STM32F107), f1mdvl (STM32F100), f4 (STM32F4XX) |
hse |
外部クロックの周波数(Hz) |
数値(12MHzなら12000000 ) |
上記の -j9 はコンパイルに使用するスレッド数.
どっかで((論理コアの数)+1)を指定すると良いという噂を聞いたので9にしてみた.
ビルド途中に"crt0.oがありません"と怒られる場合は,SConstruct
を編集
ドキュメントの生成
$ cd lib $ doxygen Doxyfile
|
すると,lib/build/doc/htmlの下にhtmlファイルが大量にできる.
index.htmlをブラウザで開けばドキュメントを見られる.
各機能
GPIO
まず最初にstm32plusを使用するにあたって最もベーシックなGPIOを取り上げる.
といってもベーシックでないように見えるのはC++の機能がふんだんに用いられているからである.(それによるメリットも後述する.)
LED点灯
はじめにLEDを点灯させるだけのコードを見てみよう.
このコードはstm32plusのexamples/blinkディレクトリにあるものに少し手を加えたものである.
PC8のピンをLOWにするという動作を行うコードである.
STM32VLDiscovery上で実行すると,右下にある青色のLEDが点灯する.
main関数の中では,Ledクラスの実体化と,on関数の呼び出しが行われている.
Ledクラスのon関数の内容を見ていく.
この行では,PC8をデジタル出力のピンとして設定し,GPIOCを扱うためのインスタンスpcを生成している.
そして,この行でPC8をLOWに設定している.
<バリエーション>
- GpioCでなくGpioA
- PA8でなくPA9
- PA8も9も10も
もしくは
LED消灯
消灯する場合はresetをsetに書き換えれば良い.
だがそれだけでは芸がないのでC++風に書いてみる.
Ledクラスのメンバ変数としてpcを宣言した.
これによってLedクラスがインスタンス化される時にGPIOCが初期化される.
ボタンによる入力
EXTIを用いたボタン入力の割り込み処理
Timing
SysTickによるLED点滅
最も単純に時間を得る方法としてSysTickを用いることが多い.
stm32plusではSysTick自体は隠蔽されていて,timingという区分でRTCなどと一緒に実装されている.
LEDを点滅させるいわゆる「Lチカ」を行うために,SysTickを利用したdelay関数を使用してみる.
まず
でミリ秒精度のSysTickタイマを設定し,
で1000msのディレイを作り出している.
<バリエーション>
- 500msのディレイ
MicrosecondDelayを用いた高精度ディレイ
通常のタイマをマイクロ秒オーダーの高精度ディレイを実現するために使用する機能が実装されている.
MicrosecondDelayはデフォルトでTIM6を使用する設定になっているが,MicrosecondDelayTemplateを用いると,その他のタイマにこの機能を割り当てることができる.
<バリエーション>
- TIM7を使う
RTCを用いた時刻の取得
<デバイスないので未検証>
Timer
TimerはTimingとは異なりSTM32のタイマの機能をそのまま使うためのものである.
STM32のタイマの数と機能は非常に豊富かつ多彩で,それをオブジェクト指向的にかつ簡単に扱うことができるのもstm32plusの魅力である.
Timerを走らせるだけ
PWM出力的なのを手動で書いてみた.
変なことをやっているが,これはTIMx->CNTを取得するための苦肉の策である.
重要なコードは以下の2つである.
これは,タイマをカウントアップモードにし,5kHz(1秒間に5000回)でカウントし,6000回カウントしたら0にリセットするという設定をするコードである.
StdPeriphLibでいうTIM_TimeBaseInit関数にあたる.
もうひとつはこのコードである.
これは,タイマを有効化する関数で,StdPeriphLibでいうTIM_InitとTIM_Cmd関数にあたる.
<バリエーション>
- TIM7を使う
- 6000Hzでカウントアップする
コンペアマッチ出力
タイマの機能であるコンペアマッチ出力を使用して,カウンタがある値に等しくなったときにピンの出力を反転させるプログラムを書く.
STM32VLDiscoveryの青LED(PC8)は,ピン機能のリマップを使用するとTIM3のCH3に割り当てることができる.(データシート参照)
出力を反転させる処理はハードウェア的に行われるため,設定だけしてタイマを走らせれば勝手にLEDがチカチカする.
このコードによって,コンペアマッチに指定する値(と処理内容:デフォルトでは出力反転)を記述できる.
<バリエーション>
- PWM出力
PWM出力にすることも可能.
PWMの出力
前項のバリエーションで記述した指定方法ではDuty比を変えるのが面倒である.
そこで,このような記法が用意されている.
<バリエーション>
- 初期Duty比を設定したい
- PWM2モードを使いたい
- 百分率ではなくカウント数を直接指定したい
Timerによる割り込み
TimerInterruptFeatureをテンプレート引数に追加して,割り込みハンドラをバインド(紐付け)する処理を行うだけで,割り込みの設定も記述することができる.
ロータリエンコーダを読む