Tiva C EK-TM4C123GXLを使ってみるの9回目です。前回は、タイマと割り込みでしたが、今回は、UART通信です。
以下のメーカのサイトを見ながらプログラムを作っていきます。
Getting Started with the TIVA™ C Series TM4C123G LaunchPad
更に、このサイトで下の方の、Workshop MaterialのThe workbookを見ながら作ります。
直接のPDFファイルへのリンクは、The workbook PDF です。
このPDFファイルのLab12のプログラムそのままです。詳細は、このPDFファイルのLab12のあたりを参照して下さい。前回が、Lab4で急にLab12になりましたが、UARTはデバッグをはじめ、Tiva Cとの通信に何かと使えると思いましたので、先に試してみました。
UARTというのは、Universal Asynchronous Receiver Transmitter の略でシリアル通信デバイスのことです。もともとは、IC(集積回路)のことですが、現在では技術そのものをUARTと呼んでいるようです。詳細は私では説明出来ませんので、必要な場合は、お手数ですが以下のサイト等を参考にして下さい。
エレラボドットコム UART その1 基本
UART(RS-232C)について – ハードウェアとか研究所
ここでは、とりあえず動作させてみます。特に配線等は必要なく、デバッグ用のUSBケーブルだけで動きます。
ソース全体は以下です。コメントは私が適当に付けました。参考程度に見て下さい。
一応、毎回書こうと思いますが、TivaWare付属のサンプルプログラム等を見ていると、ROM_ で始まっている関数をよく見かけますが、ROM_ の方は、ROM内蔵版です。こちらを使うとプログラム全体の大きさが小さくなりますが、ここでは特にサイズを気にする程でもないので、普通にリンクして使う、ROM_ が付いていない通常版の関数を使います。
ソース全体は以下からダウンロード出来ます。
ポーリング版
割り込み版
#include <stdint.h> #include <stdbool.h> #include "inc/hw_memmap.h" #include "inc/hw_types.h" #include "driverlib/gpio.h" #include "driverlib/pin_map.h" #include "driverlib/sysctl.h" #include "driverlib/uart.h" int main(void) { //システムクロックの設定(これで結果的に50MHz) SysCtlClockSet(SYSCTL_SYSDIV_4 | SYSCTL_USE_PLL | SYSCTL_OSC_MAIN | SYSCTL_XTAL_16MHZ); //UARTとポートへのクロック供給(必須) SysCtlPeripheralEnable(SYSCTL_PERIPH_UART0); SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOA); //UARTとRX、TXの設定 GPIOPinConfigure(GPIO_PA0_U0RX); GPIOPinConfigure(GPIO_PA1_U0TX); GPIOPinTypeUART(GPIO_PORTA_BASE, GPIO_PIN_0 | GPIO_PIN_1); //通信速度、通信仕様の設定 UARTConfigSetExpClk(UART0_BASE, SysCtlClockGet(), 115200, (UART_CONFIG_WLEN_8 | UART_CONFIG_STOP_ONE | UART_CONFIG_PAR_NONE)); //プロンプトの表示 UARTCharPut(UART0_BASE, 'E'); UARTCharPut(UART0_BASE, 'n'); UARTCharPut(UART0_BASE, 't'); UARTCharPut(UART0_BASE, 'e'); UARTCharPut(UART0_BASE, 'r'); UARTCharPut(UART0_BASE, ' '); UARTCharPut(UART0_BASE, 'T'); UARTCharPut(UART0_BASE, 'e'); UARTCharPut(UART0_BASE, 'x'); UARTCharPut(UART0_BASE, 't'); UARTCharPut(UART0_BASE, ':'); UARTCharPut(UART0_BASE, ' '); //入力された文字を返す while (1) { if (UARTCharsAvail(UART0_BASE)) UARTCharPut(UART0_BASE, UARTCharGet(UART0_BASE)); } }
このプログラムでは、while()ループのポーリングで受信データがあった場合に、そのまま受信データを送信して返しています。これをここでは、Tera Termで動作確認しました。手順は以下です。
コンパイル(メイク)
まずは、このプログラムをコンパイルします。
Tera Term(通信ソフト)の起動
もちろん、Tera Termではなくても他の通信ソフトでも可能です。このプログラムは、プロンプトが起動時に表示されるので、先に通信ソフトを起動します。Tera Termの場合は以下の手順です。
ここで、通信設定を行います。メニューから設定→シリアルポートを選択します。
以上で、Tera Termの起動は完了です。
次にTiva C のプログラムを起動します。
Tiva C の方でデバッグを開始します。そうすると、通信が成功すれば、以下のプロンプトが表示されます。
ここで、Tera Termから何か文字を入力してみます。通信が成功すれば、入力された文字が表示されます。(Tiva Cから返ってきます。)
これで、Tera Termとの通信の確認が出来ました。
次に処理はほぼ同じですが、割り込みを使ったプログラムです。
ソース全体は以下です。やはりコメントは参考程度に見て下さい。
#include <stdint.h> #include <stdbool.h> #include "inc/hw_ints.h" #include "inc/hw_memmap.h" #include "inc/hw_types.h" #include "driverlib/gpio.h" #include "driverlib/interrupt.h" #include "driverlib/pin_map.h" #include "driverlib/sysctl.h" #include "driverlib/uart.h" /* 割り込みハンドラ (startup_ewarm.cのベクタテーブルに登録済み) */ void UARTIntHandler(void) { uint32_t ui32Status; //割り込みステータスの取得 ui32Status = UARTIntStatus(UART0_BASE, true); //割り込みクリア UARTIntClear(UART0_BASE, ui32Status); //文字数分の繰り返し while(UARTCharsAvail(UART0_BASE)) { //文字を返す UARTCharPutNonBlocking(UART0_BASE, UARTCharGetNonBlocking(UART0_BASE)); //echo character //LED 点灯と消灯 GPIOPinWrite(GPIO_PORTF_BASE, GPIO_PIN_2, GPIO_PIN_2); SysCtlDelay(SysCtlClockGet() / (1000 * 3)); GPIOPinWrite(GPIO_PORTF_BASE, GPIO_PIN_2, 0); } } int main(void) { //クロックの設定、供給 SysCtlClockSet(SYSCTL_SYSDIV_4 | SYSCTL_USE_PLL | SYSCTL_OSC_MAIN | SYSCTL_XTAL_16MHZ); SysCtlPeripheralEnable(SYSCTL_PERIPH_UART0); SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOA); //GPIOのUART設定 GPIOPinConfigure(GPIO_PA0_U0RX); GPIOPinConfigure(GPIO_PA1_U0TX); GPIOPinTypeUART(GPIO_PORTA_BASE, GPIO_PIN_0 | GPIO_PIN_1); //LEDのためのGPIO設定 SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOF); GPIOPinTypeGPIOOutput(GPIO_PORTF_BASE, GPIO_PIN_2); //UARTの通信設定 UARTConfigSetExpClk(UART0_BASE, SysCtlClockGet(), 115200, (UART_CONFIG_WLEN_8 | UART_CONFIG_STOP_ONE | UART_CONFIG_PAR_NONE)); //UARTでの割り込みの設定 IntMasterEnable(); IntEnable(INT_UART0); //UART0で割り込み化 UARTIntEnable(UART0_BASE, UART_INT_RX | UART_INT_RT); //RXとTXのみ //プロンプト出力 UARTCharPut(UART0_BASE, 'E'); UARTCharPut(UART0_BASE, 'n'); UARTCharPut(UART0_BASE, 't'); UARTCharPut(UART0_BASE, 'e'); UARTCharPut(UART0_BASE, 'r'); UARTCharPut(UART0_BASE, ' '); UARTCharPut(UART0_BASE, 'T'); UARTCharPut(UART0_BASE, 'e'); UARTCharPut(UART0_BASE, 'x'); UARTCharPut(UART0_BASE, 't'); UARTCharPut(UART0_BASE, ':'); UARTCharPut(UART0_BASE, ' '); //ここでは何もしない while (1) //let interrupt handler do the UART echo function { // if (UARTCharsAvail(UART0_BASE)) UARTCharPut(UART0_BASE, UARTCharGet(UART0_BASE)); } }
ここでは、割り込みを使っているので、ベクタテーブルへの登録が必要です。以下の前回を参照して下さい。ダウンロード出来るソースには登録してあります。
Tiva C EK-TM4C123GXL(その8) タイマと割り込み
動作はポーリングの場合と同じですが、文字の送受信時にLEDが点滅します。
今回はここまでです、次回は、UARTでの標準入出力についてです。