前回はインプットキャプチャ機能を使用してみました。インプットキャプチャ機能と対にして使われるのがアウトプットコンペア機能です。STM32版のMicroPythonでは両機能が併用可能です。外部で発生するイベントを検出し、イベントから一定時間後に何かの制御を行うということをハードウエアの正確なタイミングで行えます。
※「MicroPython的午睡」投稿順 Indexはこちら
実験に使用しているMicroPythonと参照ドキュメント
使用しているMicroPythonは第77回でインストールしたSTマイクロエレクトロニクス社製Nucleo-F401REボード用のものです。同じSTM32マイコン搭載のpyboard版のドキュメントがほぼほぼ流用可能と思われます。Timerに関しては以下のページが参考になります。
class Timer — control internal timers
ハードウエア構成と動作
前回はNucleo-F401REボードのArduino互換ピンソケットのD7端子を入力キャプチャ用に使用しました。今回はお隣のD8端子を出力コンペア用に使用してみます。使用するタイマはSTM32が持つ「アドバンスド・コントロール・タイマ」Timer1です。
冒頭のアイキャッチ画像にインプットキャプチャとアウトプットコンペア併用の概念図を掲げました。動作としてはこんな感じです。
-
- タイマ1の16ビットカウンタは「フリーラン」状態で走ってます。
- インプットキャプチャ端子(今回はD7端子)が事前に設定した状態になると上記の16ビットカウンタの値がチャネル(今回はチャネル1)のキャプチャレジスタに保存されます。
- ソフトウエアで上記のキャプチャレジスタの値を読み取って、上記のイベントから必要なインターバル時間後に相当する「将来のカウンタ値」を計算して第2のチャネルのコンペアレジスタにセットします。
- 第2のチャネルは設定したカウンタ値(将来時刻)に到達するとアウトプットコンペア端子の状態を変更(今回はトグル)します。
ソフトウエアが介入するのは3の部分だけです。2の入力から4の出力までの時間は、ハードウエアによって正確に(カウンタのレゾリューションどおりに)確保されます。制御向きの機能であります。
今回使用のソースコード
今回使用のソースコードは、例によって前回使用のもののチョイ直しです。そのため、上記のステップのうち3番目のソフトウエアのところは通常割り込みでトリガをかけるべきところ、手抜きのポーリングでやってます。まあ、割り込み化は次回かね。
入力キャプチャは立ち上がりを見る設定です。出力コンペアは出力レベルをトグルさせてます。
#STM32: Timer 1 IC Test, callback #Timer1 CH1 ... PA8(D7) #Timer1 CH2 ... PA9(D8) import pyb import machine import time def main(): tim = pyb.Timer(1, prescaler=1023, period=0xffff) print("STM32F401RE Timer 1 IC/OC Test.") print("Source Freq: {0} Hz".format(tim.source_freq())) print("Timer 1 Freq: {0} Hz".format(tim.freq())) icCH = tim.channel(1, pyb.Timer.IC, polarity=pyb.Timer.RISING, pin=machine.Pin.board.D7) ocCH = tim.channel(2, pyb.Timer.OC_TOGGLE, pin=machine.Pin.board.D8) diffV = 1000 while True: oldV = icCH.capture() nV = icCH.capture() while oldV == nV: nV = icCH.capture() newTGL = nV + diffV if newTGL > 0xffff: newTGL -= 0xffff ocCH.compare(newTGL) if __name__ == "__main__": main()
実機での実験結果
黄色C1がインプットキャプチャへの入力信号の波形です。10Hzの矩形波をテスト用に入れてます。青色C2がアウトプットコンペアの出力波形です。黄色の立ち上がりエッジから「一定期間後」にトグルするように設定したので、周波数的には2分周でほぼ5Hzの波形が観測できてます。
肝心な部分は、黄色の立ち上がりエッジから、トグルまでの期間です。以下の測定は、上記ソースのdiffVの値が1000のときです。カーソルのΔ約12.2m秒とな。
つづいて、diffVの値を2000に変更してみました。カーソルのΔ約24.1m秒とな。
コンペアレジスタに設定する値で出力タイミングを制御できてるみたいです。あたりまえか。