前回、Nucleo-F401REボード用のMicroPythonでUARTを使ってみたのですが、釈然としない部分がありました。今回はその落穂ひろいです。前回疑問だったUART1が使えない理由は、MicroPythonのソースレベルで原因部分は判明。ソースを改変して再ビルドしたらば動くのかなあ?どうなんだろう。
※「MicroPython的午睡」投稿順 Indexはこちら
※ST Microelectronics社製Nucleo-F401REボード上で使用しているSTM32版MicroPythonについてはこちら
UART1が使えない直接原因
Nucleo-F401REボードのマイコン、STM32F401REには3本のUSART(同期、非同期両方に使えるのでUARTでなくUSARTです)「1」「2」「6」が存在します。そのうち「2」はSTLinkのハードを経由してホストのUSBの仮想シリアルに接続しているので、通常は使用不可です。よって「1」と「6」の2本が使える筈なのですが、前回MicroPython上で動作確認できたのは「6」だけでした。「1」はエラーになって動かせませぬ。
その件について、MicroPythonのソースコードを確認してみました。直接の問題個所は直ぐに判明。MicroPythonのソースインストールディレクトリ配下の
ports/stm32/NUCLEO_F401RE/mpconfigboard.h
上記のようにUART2とUART6の TX, RXピンが定義されていますが、UART1のTX,RXピンのアサインがないのです。UARTポートの在、不在はMICROPY_HW_UARTx_TX および _RXが存在すれば在、存在しなければ不在と判断されるので、UART1を使おうとするとエラーになるのでした。なぜUART1の記述が無いのか、何か別な目的に使っているのか、は不明です。後でこの部分を勝手改変してUART1を使えるかどうか見てみようかしらん。メンドイけど。
なお、ついでにUART2はMicroPythonからでも「一応」使えるのね、という件についても確認。上記のようにUART2は定義されているのでエラーにはなりません。USBシリアル相手に通信もできます。しかし、Thonny IDEのようにUSBシリアルでREPLを動かしている場合、その制御を取り上げてしまうので、IDEが使えなくなってしまいます。
UARTからの「行入力待ち」
前回、UART6に接続した「端末」にプロンプトを出して入力待ちに入り、1行入力してRETURNキーを押したらば処理をするような操作を書こうとしたら、readlineのデフォルトのタイムアウトが短すぎるのか、うまく行きませんでした。そこで今回は、行入力待ちを自前で実装してみました。
from pyb import UART import time uart6 = UART(6, 9600) uart6.init(9600, bits=8, parity=None, stop=1) def readLineBlocking(): inFlag = True buf = "" while inFlag: if uart6.any(): rc = uart6.readchar() if (rc >= 0x20) and (rc < 0x80): uart6.write(chr(rc)) buf += chr(rc) elif rc == 13: inFlag = False time.sleep_ms(10) return buf def main(): print("STM32F401RE UART6 readLine Test.") i = 1 while True: uart6.write(str(i)) uart6.write('>') i+=1 tmp = readLineBlocking() uart6.write(' = ') uart6.write(tmp) uart6.write('<\r\n') if tmp.startswith("."): break if __name__ == "__main__": main()
上記の readLineBlocking()は、キャリッジリターン(0x0D)コードが入力されるまで待つルーチンです。アスキー可読文字+0x7Fについては入力された文字を即座に返すので、相手先はローカルエコーしなくても入力文字が「見えます」。
上のプログラムをCOM11上の仮想端末相手に動かしているところが以下に。
今のところ、行編集は何もできませんが、おいおい追加しておきたいと思います。でもREPL用にそういう関数がどこかに定義されている筈だなあ、またソース内を探してみるか。