別投稿でIAR様の無償評価版の上限にひっかかってUARTに出力できなかった、と書きましたが、それはUARTが悪いのではなくprintf()などという重い関数を使おうとしたからでした。直接UARTに書き込んでやれば、容量制限など余裕でクリアでUART出力が行えました。その上、前回、釈然としなかった外部12MHzクリスタルを使って。
※「鳥なき里のマイコン屋」投稿順Indexはこちら
UARTは、とりあえずデバッグ用にメッセージを「垂れ流す」目的であります。最近、容量に余裕のあるMCUばかり使っているので、ついprintf()で出力しようなどとしたばかりに失敗しました。無償評価版の場合、昔のMCU思い出して、直接低レベルの関数を呼び出して使うようにすれば、大丈夫な筈。
待ち受けるPC側には、歴戦のFT232RL搭載の秋月製USB-シリアルを接続してあります。なお、Nuvoton NUC120はIO電圧5VのクラシックなMCUなのでUSBシリアルのボード上のジャンパ設定を忘れずに5Vにしておきます。
多分、確実にIAR様のIDEにもシリアル・モニタが組み込まれているのではないかと思うのですが、今回は使い慣れた TeratermでUSB-シリアルの仮想シリアルポートを眺めています。
さて、本題のNUC120側ですが、まず必要なドライバ類を組み込むためのヘッダ類はこれだけであります。DrvSYSはクロック等の設定のため、DrvGPIOはピンの設定用、そしてDrvUARTがUART制御のための低レベルの関数群です。Nuvoton社のこのBSPの場合、周辺を操作する低レベル関数は全てDrvから始まっているので分かり易い。
#include <stdio.h> #include "NUC1xx.h" #include "Driver\DrvSYS.h" #include "Driver\DrvGPIO.h" #include "Driver\DrvUART.h"
UARTに文字列を垂れ流すために最低必要だった変数が以下の2つであります。構造体の方は、UARTの初期化のときに与える制御用。配列の方は送信する文字データを格納しておくため。今回は配列にはテスト用にアスキーコード0x40から0x4Fまでのキャラクタを別途書き込んであります。
STR_UART_T sParam; uint8_t TxBuf[16];
さて、次がいろいろな初期化ですが、前回のSystickの設定がそのまま残っているので若干、UARTだけのためでなくなっています。
今回は、12MHzの外部クリスタルのクロックをUARTへ供給したかったので、DrvSYS_SetOscCtrl()関数で12MHzオシレータをスタートさせた後、DrvSYS_SelectIPClockSource()という関数で、UARTのクロックソースに外部12MHzオシレータを意味する0を指定しています。この関数はUARTだけでなく、「末端」系の周辺機能いろいろに与えるクロックソースを選択するのに使える関数のようです。
今回使用したUARTは1の方です。0の方はRX端子が別な目的(LED点灯)に使われてしまっているので、「フリー」だったUART1にいたしました。
UNLOCKREG(); DrvSYS_SetOscCtrl(E_SYS_XTL12M, 1); /* Enable 12MHz EXT. OSC. */ DrvSYS_Delay(5000); /* wait 12MHz. Delay by SysTick timer */ SystemCoreClockUpdate(); /*set GPB0/1 output*/ DrvGPIO_Open(E_GPB,0, E_IO_OUTPUT); DrvGPIO_Open(E_GPB,1, E_IO_OUTPUT); SysTick_Config(SystemCoreClock / 100); /* Set UART1, PIN8(PB4)=RX1, PIN9(PB5)=TX1 */ DrvGPIO_InitFunction(E_FUNC_UART1); /* Select UART Clock Source From 12MHz */ DrvSYS_SelectIPClockSource(E_SYS_UART_CLKSRC, 0); /* UART Setting */ sParam.u32BaudRate = 115200; sParam.u8cDataBits = DRVUART_DATABITS_8; sParam.u8cStopBits = DRVUART_STOPBITS_1; sParam.u8cParity = DRVUART_PARITY_NONE; sParam.u8cRxTriggerLevel= DRVUART_FIFO_1BYTES; /* Set UART Configuration */ DrvUART_Open(UART_PORT1, &sParam);
DrvUART_Open()でUARTを開けば、もうUARTへの出力ができる状態になっています。そして、printf()のような「高水準」の関数を呼ばず、低レベルの出力関数、DrvUART_Write()に出力文字列へのポインタと、出力バイト数(ここでは16)を与えます。
DrvUART_Write(UART_PORT1, TxBuf, 16);
さすれば、以下のようにTxBufに事前に書き込んであった文字列がPC上のTeraterm画面に送られてまいります。ループの中でLチカする度に出力するようにしたので、延々と。
なんか、容量制限あっても一通り周辺機能を動かせそうかも。