<V.3版>
PIC - Tera Term間
UARTモジュール制御
(Harmony コールバック関数編)
(→プロジェクトファイル(Harmony Ver.3版 MHC v3.6.0) ダウンロード)
Harmonyのコールバック関数を使用した PICとTeraTerm間の文字列送受信の例です。
<仕様>
・PIC32MZとPC間の文字列送受信通信をRS232C(正式にはEIA-574規格)を用いて行う。
・PIC32MZはPIC32MZ2048EFH100とする。
・PCの通信ソフトは Tera Termをつかうこと。
・通信条件 ボーレート:9600bps
データ長: 8ビット
パリティ: なし
ストップビット: 1ビット
フロー制御: なし
・PICが起動したら PC側に文字列 "Hellow World !!"を送信する。
・PC側でキーインした(Tera Term が送信した)文字を PIC側で受信したら文字列"data="を追加して
PC側に返信する。
例1: "b"を受信したら "data=b"を返信する。
例2: "4"を受信したら "data=4"を返信する。
・Tera Term 側の表示は エコーバックはしないで 送受信文字のみを表示する。
・‘PCのUSBポートとRS232Cポートの変換は、ラトックシステム(株)のUSBシリアルコンバーター REX-USB60Fを使用する。
・ Harmonyは、Ver.3を使うものとする。
・ Harmonyのライブラリ関数だけを使用し、レジスタ直接制御はしないこと
・UARTモジュールはダイナミックライブラリを使い、モジュールの諸元は以下とする。
モジュールID: U6
TXポート: RC2
RXポート: RG9
<回路図> (→PDFファイル)
<外観>
PIC32MZ評価ボード(→購入方法)を使った実験品の外観です。
<動作結果> (→ 動画:1080pのHD動画を見ることができます。)
① Tera Termを起動して通信条件を 以下のように設定します。 |
② PICの電源をONにするとPIC側から PC側(Tera Term)に "Hellow World !!"が 送信されてきます。 |
③ キーボードから "a"をキーインすると PC側から "data=a"が送信されて きます。 |
|
④ キーボードから "b"をキーインすると PC側から "data=b"が送信されて きます。 |
⑤ キーボードから "3"をキーインすると PC側から "data=3"が送信されて きます。 |
⑥ キーボードから "4"をキーインすると PC側から "data=4"が送信されて きます。 |
|
■ ステップ1: MHC作成
■ ステップ2
app.cに青地部を追加します。
① 送信データのバッファを定義します。 | |
char TransmitData[32]; //送信データ | |
② PIC立ち上がり時に PICからTeraTermに送信する文字列を定義します。 | |
static const char messageBuffer[] = "Hellow World !!\r\n"; //PIC32MZ立ち上がり時 TeraTermに送信される文字列 | |
③UART6のコールバック関数を定義します。 この関数は次の2つの場合 およびエラーが発生した場合に呼び出されます。。 1. 送信バッファU6TXREGのデータが全部送信されて 空になった場合 2. 受信バッファU6RXREGが受信を完了した場合 この2つの場合 appData.transferStatus = true; というイベントが出されます。 |
|
static void APP_USARTBufferEventHandler( //送受信バッファーのデータ処理完了に係るコールバック関数 DRV_USART_BUFFER_EVENT bufferEvent, DRV_USART_BUFFER_HANDLE bufferHandle, uintptr_t context ) { switch(bufferEvent) { case DRV_USART_BUFFER_EVENT_COMPLETE: //処理が完了すると呼ばれる(イベントが発生する)。 以下の2つの場合がある //1. 送信バッファにあるデータがすべて排出され送信バッファが空になった場合 //2. 受信バッファが受信を完了した場合 appData.transferStatus = true; break; case DRV_USART_BUFFER_EVENT_ERROR: appData.state = APP_STATE_ERROR; break; default: break; } } |
|
④ パラメータを初期化します。 | |
appData.state = APP_STATE_INIT; appData.transferStatus = false; appData.usartHandle = DRV_HANDLE_INVALID; appData.bufferHandle = DRV_USART_BUFFER_HANDLE_INVALID; |
|
⑤ プログラム起動後の最初のステートが APP_STATE_INIです。 DRV_USART_Open()関数で UARTのドライバーインスタンスを定義し、ハンドルを生成します。すでに生成されていたりしなければ ハンドルは生成されますので、DRV_USART_BufferEventHandlerSet()関数でコールバック関数を宣言します。 このコールバック 関数は③で中身を定義します。 |
|
switch ( appData.state ) { /* Application's initial state. */ case APP_STATE_INIT: //初期化ステート appData.usartHandle = DRV_USART_Open(DRV_USART_INDEX_0, DRV_IO_INTENT_READWRITE); // //UARTのドライバーインスタンスを定義し、ドライバーハンドルを生成 if (appData.usartHandle != DRV_HANDLE_INVALID) //ハンドルが正常に生成された場合 { DRV_USART_BufferEventHandlerSet(appData.usartHandle, APP_USARTBufferEventHandler, 0); //コールバック関数APP_USARTBufferEventHandlerを設定 appData.state = APP_STATE_TRANSMIT_MESSAGE; } else //ハンドルが正常に生成されなかった場合 { appData.state = APP_STATE_ERROR; } break; |
|
⑥ このAPP_STATE_TRANSMIT_MESSAGステートで 送信バッファU6TXREGへ起動直後にTeraTermに送信する文字列が書き こまれます。書き込みが正常に行われるとハンドルが生成され、 APP_STATE_WAIT_MESSAGE_TRANSFER_COMPLETEに移行します。 |
|
case APP_STATE_TRANSMIT_MESSAGE: //送信バッファへの書き込み DRV_USART_WriteBufferAdd(appData.usartHandle, (void*)messageBuffer, strlen(messageBuffer), &appData.bufferHandle); //送信モードへ、送信バッファーに書き込み if (appData.bufferHandle != DRV_USART_BUFFER_HANDLE_INVALID) //ハンドルの競合などがなくハンドルが正常に生成された場合 { appData.state = APP_STATE_WAIT_MESSAGE_TRANSFER_COMPLETE; } else { appData.state = APP_STATE_ERROR; } break; |
|
⑦ このAPP_STATE_WAIT_MESSAGE_TRANSFER_COMPLETEステートで 送信レジスタU6TXREGにある全データが送信され レジスタが空になるまで待ちます。 送信レジスタがからになると コールバック関数APP_USARTBufferEventHandler()が 呼ばれ appData.transferStatus = true;のイベントが発生します。 このイベントが発生したら appData.transferStatus = false;を 実行して 次のイベントが受けられるようにして、 次のAPP_STATE_RECEIVE_DATAステートに移行します。 |
|
case APP_STATE_WAIT_MESSAGE_TRANSFER_COMPLETE: //送信完了待ち if(appData.transferStatus == true) //送信完了(送信バッファが空になるの)を待つ { appData.transferStatus = false; //フラグをfalseにセット appData.state = APP_STATE_RECEIVE_DATA; } break; |
|
⑧ このAPP_STATE_RECEIVE_DATAステートでU6RXREGレジスタで受信を開始します。 DRV_USART_ReadBufferAdd()関数で 受信データのサイズ、変数などを定義します。 受信が問題なく開始されればハンドルが生成されるので APP_STATE_WAIT_RECEIVE_COMPLETEステートに移行します。 このステートは何も受信しなくとも次のステートに 移行します。 |
|
case APP_STATE_RECEIVE_DATA: //受信 DRV_USART_ReadBufferAdd(appData.usartHandle, appData.readBuffer, APP_DATA_SIZE, &appData.bufferHandle); //受信開始 //受信モードへ、受信バッファ受信待ち状態へ if (appData.bufferHandle != DRV_USART_BUFFER_HANDLE_INVALID) //ハンドルの競合などがなくハンドル生成成功の場合 { appData.state = APP_STATE_WAIT_RECEIVE_COMPLETE; } else { appData.state = APP_STATE_ERROR; } break; |
|
⑨ このAPP_STATE_WAIT_RECEIVE_COMPLETEステートで 受信バッファU6RXREGレジスタの受信が完了するまで待ちます。 受信が完了すると コールバック関数APP_USARTBufferEventHandler()が呼ばれappData.transferStatus = true; のイベントが 発生します。 イベントが発生したらこのイベントが発生したら appData.transferStatus = false;を 実行して 次のイベントが 受けられるようにして、 次のAPP_STATE_TRANSMIT_DATAステートに移行します。 |
|
case APP_STATE_WAIT_RECEIVE_COMPLETE: //受信完了待ちステート if(appData.transferStatus == true) //受信バッファへのデータ受信が完了するのを待つ { appData.transferStatus = false; //フラグをfalseにセット appData.state = APP_STATE_TRANSMIT_DATA; } break;
|
|
⑩ このAPP_STATE_TRANSMIT_DATAステートで 受信データに "data=" を追加したデータを sprintf(TransmitData,"data=%s\r\n", appData.readBuffer);で作成します。 そしてDRV_USART_WriteBufferAdd()関数で 送信レジスタU6TXREGに書き込みます。 書き込みが成功するとハンドルが生成されるので 次の APP_STATE_WAIT_TRANSMIT_COMPLETEに移行します。 |
|
case APP_STATE_TRANSMIT_DATA: //送信データ作成、データ送信ステート sprintf(TransmitData,"data=%s\r\n", appData.readBuffer); //送信データの作成 受信文字に"data="を追加 DRV_USART_WriteBufferAdd(appData.usartHandle, TransmitData, sizeof(TransmitData), &appData.bufferHandle); //送信バッファーにデータに書き込み if (appData.bufferHandle != DRV_USART_BUFFER_HANDLE_INVALID) //ハンドル生成成功の場合 { appData.state = APP_STATE_WAIT_TRANSMIT_COMPLETE; } else { appData.state = APP_STATE_ERROR; } break; |
|
⑪ このAPP_STATE_WAIT_TRANSMIT_COMPLETEステートで送信レジスタU6TXREGにある全データが送信され レジスタが空になるまで待ちます。 送信レジスタが空になると コールバック関数APP_USARTBufferEventHandler()が 呼ばれ appData.transferStatus = true;のイベントが発生します。 このイベントが発生したら appData.transferStatus = false;を 実行して 次のイベントが受けられるようにして、 次のAPP_STATE_RECEIVE_DATAステートに移行し、受信レジスタ U6TXREGレジスタの受信を待ちます。 |
|
case APP_STATE_WAIT_TRANSMIT_COMPLETE: // 送信完了待ち if(appData.transferStatus == true) //送信完了(送信バッファが空になるの)を待つ { appData.transferStatus = false; //フラグをfalseにセット LED1_Toggle(); //LEDの点灯/消灯を反転 appData.state = APP_STATE_RECEIVE_DATA; } break; |
|
⑫ 以下にある APP_STATE_ERRORステート、APP_STATE_IDLEステートには、正常動作の場合 制御はきまんせん |
|
case APP_STATE_ERROR: //正常動作の場合このステートは使用されない appData.state = APP_STATE_IDLE; break; case APP_STATE_IDLE: //正常動作の場合このステートは使用されない break; default: break; |
|
以下、app.c 全文 |