超お求め易い価格で多機能、そして何かと話題のRISC-V搭載のマイコン・ボード、Longan nanoにも大分慣れてきました。オンボードのLCD、LEDそしてDACという順番に動かしてきましたが、この辺でシリアルポートにprintfできるようにしておきたい。原始的とそしられても、あれば使ってしまうprintfデバッグであります。
※「鳥なき里のマイコン屋」投稿順Indexはこちら
まず、シリアルポートを使う前に正直に申告しておきます。LEDの点灯、消灯ルーチン、間違っていました。別にprintfデバッグの結果ではありません。
LCDにREDと表示出ているのに、LEDは赤く光ってないな~
という至極あたりまえな現象に気付いたからであります。LEDの色が変わっていくので、OKなどと思い込んでおりました。あっと思ってみてみたら、LOW出力で点灯なのに、HIGH出力で点灯のように関数を逆につかっていました。よって、赤のつもりが、青と緑の混合で水色になっていた。。。BUGをFIX。ちゃんと「観察」するのが一番のデバッグであります。
また、もひとつ前から気になっていたメモリ容量も確認しました。というのも私が購入させてもらった価格より、さらに「お求めやすい価格」になっているLongan nanoを発見、ただし、メモリ容量が小さくなっているようであったのです。手元のバージョンは本当にメモリが大きいのだよね、と。PlatformIOでのビルド時の出力をしげしげと眺めました。以下の通り。
Linking .pio\build\sipeed-longan-nano\firmware.elf Building .pio\build\sipeed-longan-nano\firmware.hex Building .pio\build\sipeed-longan-nano\firmware.bin Checking size .pio\build\sipeed-longan-nano\firmware.elf Advanced Memory Usage is available via "PlatformIO Home > Project Inspect" RAM: [= ] 7.1% (used 2328 bytes from 32768 bytes) Flash: [= ] 12.2% (used 15968 bytes from 131072 bytes)
よかった、フラッシュ128Kバイト、RAM32Kバイトでした。でも今回のような小さなプログラムであれば、よりお求めやすいフラッシュ64Kバイト、RAM20Kバイト版でも十分です。追加購入するときはそちらの版も仕入れようかしら。
ようやく本題です。USARTでprintf。複数チャネルのUSARTが搭載されていますが、少ない端子のやりくり厳しいなか、この目的に使いやすいのはUSART0に「決まって」います。ボードの端面に8ピンがかなり無理やり感のある立て方で接続されているのですが、ここに出ているのが以下だからです。
-
- JTAG4ピン(RSTはなし)
- USART0のRXとTX
- GND
- 3V3
3V3はJTAGデバッグ時のVREFに使え、ということだと思います。JTAG4ピンはボード裏面側から引き出されており、ボード表面にはRX,TX,GND,3V3がでています。JTAGデバッグならGND, 3V3, JTAGの6本、UARTシリアルであればRX,TX,GNDの3本を使えば接続できそうです。当然、RX, TXしか出ていないので、ハード的にはUSARTですが、UARTとしての使用で、かつ、他の制御信号なども使用しない方法となります。USARTを使ったprintfの実装は、例のExamplesの中にサンプルコードがあるので、それを参考にしながら、前回のプログラムに追加して行きます。
初期化はまず、USART0にもクロックを与えておかねばなりませぬ。
rcu_periph_clock_enable(RCU_GPIOC); rcu_periph_clock_enable(RCU_GPIOA); rcu_periph_clock_enable(RCU_DAC); rcu_periph_clock_enable(RCU_USART0);
GPIOAの9番がUSART0のTX, 10番がRXなので端子の初期化も追加します。
gpio_init(GPIOC, GPIO_MODE_OUT_PP, GPIO_OSPEED_50MHZ, GPIO_PIN_13); // LED_RED gpio_init(GPIOA, GPIO_MODE_OUT_PP, GPIO_OSPEED_50MHZ, GPIO_PIN_1 | GPIO_PIN_2); // LED_GREEN, LED_BLUE gpio_init(GPIOA, GPIO_MODE_AIN, GPIO_OSPEED_50MHZ, GPIO_PIN_4); //DAC0 gpio_init(GPIOA, GPIO_MODE_AF_PP, GPIO_OSPEED_50MHZ, GPIO_PIN_9); // USART0 TX gpio_init(GPIOA, GPIO_MODE_IN_FLOATING, GPIO_OSPEED_50MHZ, GPIO_PIN_10); // USART0 RX
そして、USART0自体の初期化。RX使ってシリアル入力をするとなると、割り込みとか、バッファリングとかいろいろ面倒ですが、ここでは、printfで垂れ流し出力のみなので、最小限の設定のみ。
void usart0_config(void) { usart_deinit(USART0); usart_baudrate_set(USART0, 115200U); usart_word_length_set(USART0, USART_WL_8BIT); usart_stop_bit_set(USART0, USART_STB_1BIT); usart_parity_config(USART0, USART_PM_NONE); usart_hardware_flow_rts_config(USART0, USART_RTS_DISABLE); usart_hardware_flow_cts_config(USART0, USART_CTS_DISABLE); usart_receive_config(USART0, USART_RECEIVE_ENABLE); usart_transmit_config(USART0, USART_TRANSMIT_ENABLE); usart_enable(USART0); }
そして、最後に忘れてならないのは、printfが内部で呼び出しているらしい_put_char()関数のオーバライドでした。
int _put_char(int ch) { usart_data_transmit(USART0, (uint8_t) ch ); while ( usart_flag_get(USART0, USART_FLAG_TBE)== RESET){ } return ch; }
ここまで準備すると、普通にstdio.hをインクルードしてprintfすると、USART0から出力文字列が垂れ流されていきます。今回は、アイキャッチ画像のようにLongan nanoに取り付けたお手製「アダプタ」の先には、定番の
秋月電子 FT232RL USB-シリアル変換モジュール
を接続しております。PlatformIOのシリアルモニタは、仮想COMポートを適当に探してくれるみたい(複数あったらどれか指定しないといけないのだと思う)なので、platformio.iniのmonitor_portは設定せず、
monitor_speed = 115200
のみ記入。幾つかprintfをちりばめたプログラムを書き込み、動かしてみたところがこちら。
--- Miniterm on COM4 115200,8,N,1 --- --- Quit: Ctrl+C | Menu: Ctrl+T | Help: Ctrl+T followed by Ctrl+H --- DAC : 00ff DAC : 01ff LOOP : 1 DAC : 02ff DAC : 03ff DAC : 04ff LOOP : 2 DAC : 05ff DAC : 06ff DAC : 07ff LOOP : 3 DAC : 08ff DAC : 09ff DAC : 0aff
1ループ9秒設定(ハンディDMMで電圧を読み取れるようにゆるゆる)、その中で3秒毎DACの設定値を更新している様子が観察できました。
また、一歩前進したな、次は何?