前回タイマとPWM出力端子の関係を調べました。調べ忘れがひとつ。MicroPython的には freq=xxx という形で指定すればよきに計らってくれるので使い方によっては知る必要ないのです。しかし入力キャプチャ機能を使おうなどと考えるとTimerに与えられているソースクロックの周波数を知らずにはいられませぬ。
※「MicroPython的午睡」投稿順 Indexはこちら
参照ドキュメント
本件、手がかりとなるのは、以下のページではなかろうかと思います。pyboard版のTimerに関する記事です。
class Timer — control internal timers
以前述べたように、STM32F401RE用にビルドしたMicroPythonは、御本家pyboard版に「きわめて近く」、pyboard用のpybクラスなど使用可能です。上記ページは多いに役に立つ気がします。ただしハードウエア(MCU)は同じSTM32でも異なる機種です。そのため上記のドキュメントでは、例えば
-
- Timer5はサーボモータ制御用
- Timer6はADC/DACの読み書きタイミング制御用
につかうことをレコメンドしていますが、STM32F401REにはTimer6は存在しないです。この辺は、前回、前々回あたりで調べたことをベースに、矛盾がないように勝手にアサインしていくしかない、と思います。
今回実験用のソースコード
今回実験には「アドバンスド・コントロール・タイマ」Timer 1 を使ってみました。Timer 1は、前々回調べたとおり、PWMなどで主力?となるAPB1側のTimer 2/3/4/5とはことなり、機能が限られているタイマであるTimer9/10/11と同じAPB2側にぶら下がっているタイマです。ただし「アドバンスド」うたっているだけあって、Timer1はTimer2/3/4/5を上回る入出力チャネル機能を実装しています。
MicroPython的にすべての入出力チャネル機能を使えるわけではないですが、そこそこ使えそうな感じがします。そこで今回からTimer 1でタイマの入出力機能を試してみる意図です。
ソースは前回のもののチョイ変。一番のポイントは、タイマ周期を周波数で指定するのではなく、ハードウエアのプリスケーラ値とカウンタのリロード値をダイレクトで指定しているところ。以下のxxxx, yyyyに適切な値を書き込むことで、「お任せ」の周波数でなくハードのレジスタ値を指定できます。
-
- prescale=xxxx
- period=yyyy
今回はカウンタはフリーラン的な動作としたいので、フルスケールの16ビット0xFFFF指定固定です。操作してみたのはプリスケーラ値部分。プリスケーラ値+1が分周比となる筈。
やっていること自体は前回と変わらぬPWM出力です。出力される周波数を外部で測れば動作周波数が実機で確認できると。
#STM32: Timer 1 Test #Timer1 CH1 ... PA8(D7) import pyb import machine def main(): print("STM32F401RE Timer 1 Test.") tim = pyb.Timer(1, prescaler=1, period=0xffff) pwmCH = tim.channel(1, pyb.Timer.PWM, pin=machine.Pin.board.D7) pwmCH.pulse_width_percent(50) print("Source Freq: {0} Hz".format(tim.source_freq())) print("Timer 1 Freq: {0} Hz".format(tim.freq())) print("End of test.") if __name__ == "__main__": main()
実機確認
前回動かしているので、さっさと出力周波数を実機で確認してみました。こんな感じ。
いくつかのプリスケーラ値に対して、上記の測定で検出した周波数と、その値から推定できる元クロック周波数をまとめてみました。こんな感じ。
prescaler | measured PWM freq[Hz] | Est.Source Freq[Hz] |
---|---|---|
1023 | 1.3034 | 87.469M |
511 | 2.6024 | 87.322M |
63 | 20.504 | 86M |
15 | 81.412 | 85.366M |
1 | 651.21 | 85.355M |
それに対して、プログラムの後半でMicroPython処理系に、元クロックとTimer1カウンタの動作周波数を「自己申告」してもらっています。プリスケーラに1をたてたときは、こんな感じ。
MicroPython的には、84MHzのクロックでTimer1を動作させているつもりなのね。当方実測値は若干「公式見解」より早いっす(追及しない奥ゆかしさ?)
またTimer1のFreqとして報告されている640.8691Hzと84MHzの関係は以下のとおりです。
640.8691Hz * 65536 * 2 = 84.000 MHz
プリスケーラ=1のときのカウンタ値のレゾリューション(設定値)は23.81nsなり。マイクロ秒単位くらいの測定であれば余裕でないかい。知らんけど。