
前回、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用にそういう関数がどこかに定義されている筈だなあ、またソース内を探してみるか。

