マイコンを扱うなら必ずシリアルで通信する日が訪れるでしょう。
シリアル通信は、パソコンや周辺機器と有線で接続して、データの送受信を行うことができます。このシリアル通信の中でもUART(ユーアート)通信はよく使います。
近年、Bluetoothを始めたした無線化が進んでいる一方で、有線であるUART通信は今でも使われ続けています。多くのマイコンに内蔵されており、2本の通信線を機器に接続するだけで簡単にデータの送受信ができるので難易度は比較的低いからだと思います。
この記事では、RL78のUART通信のプログラムについて解説していますので、これからUART通信をする方は是非参考にしてみてくださいね。
UART通信についてもっと詳しく解説
このUARTとは、Universal Asynchronous Receiver Transmitter(直訳すると汎用非同期式送受信機)の略で、コンピュータが周辺機器装置とのデータ送受信で使用される標準規格です。
データを送信するための信号とデータを受信するための信号の2種類を使って通信を行います。この信号については以下の単語を使いますので覚えておきましょう。
- TXD:データを送信する信号
- RXD:データを受信する信号
周辺機器のデバイスと接続するときは、TXDとRXDの組み合わせで接続します。
データの通り道を1つにして、TXDからRXDに1バイト8ビットのデータの塊を送ります。この接続が双方向にあるので、2台のデバイスは自由にデータの交換をすることができるのです。
シリアル通信の条件を設定してデバイス間で通信をさせます。UARTではボーレートやパリティ等に様々なバリエーションがあり、用途に合わせて条件の設定を行います。 太字で強調されている文字は、一般的に設定される条件です。
ボーレート | 4800, 9600, 19200, 38400, 115200 等 |
---|---|
データビット | 7, 8, 9 |
ストップビット | 1, 1.5, 2 |
パリティビット | なし, Odd, Even |
フロー制御 | なし, ハードウェア, ソフトウェア |
条件毎に説明を以下に記載しています。
- ボーレート:1秒間に何ビット送信するかを設定します。数値が大きいほど速くデータを送信することができます。
- スタートビット:1バイトのデータを送信する前に、通信を開始する合図を立下りエッジで知らせます。
送信側は立下りエッジから1バイトだけLow(0V)にします。 - データビット: 送信するデータの長さを指定します。通常8バイトの長さでデータを送信します。
- パリティビット:誤り検出符号ビットで、通信の信頼性を確保するために設定します。
奇数、偶数、なしを使用することができ、ハードウェアで自動的に処理されます。 - ストップビット:ストップビットは1 バイトの通信が終了する時のビット数を設定します。
送信側は、指定したビットの時間だけHighになります。ストップビット検出後もHighが維持されますので、続けてスタートビットを送信してデータを連続で送信することが可能です。
コードを実装前にコード生成を行おう
コード生成は、GUIベースでマイコン周辺機能を設定します。誤った設定をチェックする機能も装備しており、設定に合わせてコード生成をするので、すぐに動かせるプログラムが作成できます。
今回はUART通信をコード生成してみましょう。
プロジェクト・ツリー内にあるコード生成(設計ツール)を展開し、シリアルを選択します。SAU0タブ内のチャンネルタブを選択します。
チャンネル0をUART0、送信/受信機能を選択します。
続けて、UART0の受信と送信の設定をします。まずは、受信の設定から行います。お好みで設定することができます。下図はUART通信で一般的に設定される条件で設定をしています。
受信と送信の設定が分かれており、送信タブを選択して忘れずに設定をしておきましょう。受信と送信の設定内容は基本的に同じで問題ないです。
UART通信の動作仕様説明について
RenesasのサンプルコードをもとにUART通信のプログラムを実装します。UART通信で受信した1文字のデータに対応したデータを送信するサンプルになります。
- 受信データが ”T” の場合、”OK” を接続機器に送信する。
- 受信データが ”t” の場合、”ok” を接続機器に送信する。
- 上記以外の場合、”UC” を接続機器に送信する。
プログラムを実装しよう
コード生成した時に自動で作成されたソースコードにUART通信に関連する関数を使うことで簡単にプログラムを実装することができます。
#include "iodefine.h" // 端子の基本設定読み込み
#include "r_cg_macrodriver.h" // uint8_t、uint16_tの読み込み
#include "r_cg_wdt.h" // ウォッチドッグタイマー
#include "r_cg_serial.h" // UART設定
uint8_t g_uart0_rx_buffer = 0U; // UART0 receive buffer
uint8_t g_uart0_rx_error = 0U; // UART0 receive error status
MD_STATUS g_uart0_tx_end = 0U; // UART0 transmission end
static const uint8_t message_ST[7U] = {"START\r\n"}; // UART開始メッセージ
static const uint8_t message_OK[4U] = {"OK\r\n"}; // "T"が受信されたら、"OK"を送信
static const uint8_t message_ok[4U] = {"ok\r\n"}; // "t"が受信されたら、"ok"を送信
static const uint8_t message_UC[4U] = {"UC\r\n"}; // それ以外が受信されたら、"UC"を送信
void user_main(void)
{
long i; // 空ループ用
R_UART0_Start(); //UART開始
R_UART0_Send((unsigned char *)message_ST,7); //送信
while(1)
{
R_UART0_Receive(&g_uart0_rx_buffer, 1U); // UART受信バッファの取得
// 受信データの確認
switch (g_uart0_rx_buffer)
{
// 受信がない場合
case 0x00:
break;
// "T"が受信された場合
case 'T':
R_UART0_Send((uint8_t *)message_OK, 4U); // "OK"を送信
break;
// "t"が受信された場合
case 't':
R_UART0_Send((uint8_t *)message_ok, 4U); // "ok"を送信
break;
// それ以外が受信された場合
default:
R_UART0_Send((uint8_t *)message_UC, 4U); // "UC"を送信
break;
}
//受信バッファをクリア
g_uart0_rx_buffer = 0x00;
for(i=0;i<100000;i++); //空ループ
R_WDT_Restart(); //ウォッチドッグタイマーリセット
}
}
それでは、user_mainに記述しているソースコードについて1つずつみていきましょう。
UART動作開始
UART通信送受信の処理を記述する前に、R_ UART0_Start(関数名)を記述します。これがないとUART通信が開始されないので、注意しましょう。
概要 | UART0 動作開始処理 |
---|---|
ヘッダ | r_cg_macrodriver.h 、r_cg_serial.h |
宣言 | R_ UART0_Start(void) |
説明 | シリアル・アレイ・ユニット0、1 のチャネル0 を動作開始させ、通信待機状態にします。 |
データの送信
データを送信する時は、R_UART0_Send(関数名)を記述します。この関数の引数に送信データとデータサイズを渡してあげます。R_UART0_Send(送信データ, データサイズ)の1行で送信できちゃいます。とても簡単ですね。
概要 | UART0 データ送信関数 |
---|---|
ヘッダ | r_cg_macrodriver.h 、r_cg_serial.h |
宣言 | MD_STATUS R_UART0_Send(uint8_t* tx_buf, uint16_t tx_num) |
説明 | UART0 送信の初期設定を行い、データ送信を開始します。 |
引数 | uint8_t *tx_buf : [送信データバッファのアドレス] uint16_t tx_num : [送信データバッファのサイズ] |
リターン値 | [MD_OK]の場合:送信設定完了 [MD_ARGERROR]の場合:送信設定失敗 |
データの受信
データを受信する時は、R_UART0_Receive(関数名)を使うのですが、この関数は受信したデータを取得する関数ではなく、受信したデータの格納先を指定する関数です。この関数の引数に受信データの格納先のアドレスと格納先のサイズを渡します。こうすると、データを受信した時に格納先のアドレスにデータを受け渡されます。
今回は1文字だけ受信しますので、格納先のサイズは1U(Uをつけると整数)です。
概要 | UART0 受信ステータス初期化関数 |
---|---|
ヘッダ | r_cg_macrodriver.h 、r_cg_serial.h |
宣言 | MD_STATUS R_UART0_Receive(uint8_t *rx_buf, uint16_t rx_num) |
説明 | UART0 受信の初期設定をします。 |
引数 | uint8_t *rx_buf : [受信データバッファのアドレス] uint16_t rx_num : [受信データバッファのサイズ] |
リターン値 | [MD_OK]の場合:受信設定完了 [MD_ARGERROR]の場合:受信設定失敗 |
動作を確認してみましょう
動作確認では、パソコンとマイコンをシリアルケーブルで接続します。パソコン側ではTeraTermを起動して、COMポートを選択して、マイコンで設定した通信条件と同じ条件を指定して接続します。
端末の設定を開いて、改行コードの受信をAUTOにし、送信コードをCR+LFにします。また、ローカルエコーにチェックを追加します。
TeraTermに、”T” や “t” などの文字を打ち込んでみましょう。
上の様に打ち込んだ文字に対して、マイコンから応答があれば完成です。
UART通信の方法は複数あり、通信状態をポーリングして受信データがあれば読み出しする方法やリングバッファに受信データを格納する方法があります。