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での標準入出力についてです。


