シリアル通信の初期化が完了しました。これでいつでも送信/受信が可能ですので、まずは1文字(1バイト)を送信するための関数を作りましょう。例によって、データシートに示されている手順通りに実装します。
このレジスタは、シリアル通信の動作状態を格納しているレジスタです。ここでチェックするのは、送信データを格納するトランスミットデータレジスタ(SCTDR)が空になっているかどうかです。すなわち、前回送信したデータがきちんと送信されるまで待つという制御になります。SCTDRが空になると、SCSSRのTDREビットが「1」になるので、TDREビットが「0」の間ループさせます。
while(!SCI1.SCSSR.BIT.TDRE); // SCSSRのTDREビットが1になるまで待機
SCTDRが空になったので、SCTDRに送信するデータを書き込みます。データを書き込んだら、SCSSRのTDREビットに「0」をセットします。この後、データは一度トランスミットシフトレジスタ(SCTSR)に送られ、LSBから順番にTXD端子に出力されます。SCTDRのデータがSCTSRに送られ、SCTDRが空になると、SCSSRのTDREビットに「1」がセットされます。
SCI1.SCTDR = c; // 送信データの書き込み SCI1.SCSSR.BIT.TDRE = 0; // SCSSRのTDREビットを0にクリア
続けてデータを送信する場合は(1)に戻りますが、今回は1文字送信するだけですので、このまま終了処理をします。送信が完全に終了したことを知るには、SCSSRのTENDビットをチェックします。TENDビットは、SCTSRのデータが完全に送信された後、SCTDRが空になっている場合に「1」がセットされます。すなわち、TENDビットが「1」になるまで待機します。
while(!SCI1.SCSSR.BIT.TEND); // SCSSRのTENDビットが1になるまで待機
以上で送信は完了です。送信する1バイトのデータを引数とする関数にしておきましょう(プログラム3)。
void sendByteSCI1(char c) { while(!SCI1.SCSSR.BIT.TDRE); // SCSSRのTDREビットが1になるまで待機 SCI1.SCTDR = c; // 送信データの書き込み SCI1.SCSSR.BIT.TDRE = 0; // SCSSRのTDREビットを0にクリア while(!SCI1.SCSSR.BIT.TEND); // SCSSRのTENDビットが1になるまで待機 }
送信ができたので、今度は受信する関数を作りましょう。この手順もデータシートに書いてあります。受信時にはエラー処理がありますが、今回は無視することにします。余裕がある人は、エラー処理の手順もデータシートに書いてありますので、実装してみてください。
SCSSRは送信時にも出てきましたが、受信時にも利用します。ここでチェックするのは、受信したデータがレシーブデータレジスタ(SCRDR)に格納されているかどうかです。すなわち、受信したデータがSCRDRに格納されるまで待つという制御になります。SCRDRにデータが格納されると、SCSSRのRDRFビットに「1」がセットされるので、RDRFビットが「0」の間ループさせます。
while(!SCI1.SCSSR.BIT.RDRF); // SCSSRのRDRFビットが1になるまで待機
SCRDRに受信データが格納されたので、データを読み出します。データを読み出したら、SCSSRのRDRFビットに「0」をセットします。その後、データシートにはSCSCRのREビットに「0」をセットすると書かれていますが、以後受信ができなくなってしまうので、ここは無視します。最後に、関数の呼び出し元に受信データを返します。
receivedByte = SCI1.SCRDR; // 受信データの読み出し SCI1.SCSSR.BIT.RDRF = 0; // RDRFフラグを0にクリア return receivedByte; // 受信したデータを返す
以上で受信は完了です。受信した1バイトのデータを戻り値とする関数にしておきましょう(プログラム4)。
char recvByteSCI1(void) { char receivedByte; // 受信データ while(!SCI1.SCSSR.BIT.RDRF); // RDRFフラグのチェック receivedByte = SCI1.SCRDR; // 受信データの読み出し SCI1.SCSSR.BIT.RDRF = 0; // RDRFフラグを0にクリア return receivedByte; // 受信したデータを返す }
ここまでの内容で、マイコン側はシリアル通信の初期化、送信、受信ができるようになりました。これが正しく動作するかどうか、PCと通信してチェックしてみましょう。
まずは簡単に、受信した文字をそのまま送信するプログラムを書いてみましょう。例えば、プログラム5のようになります(これまでに作った関数は省略します)。
void main(void) { char recv; initSCI1(); // シリアル通信の初期化 while(1) { recv = recvByteSCI1(); // 1文字受信 sendByteSCI1(recv); // 受信した文字をそのまま送信 } }
シリアル通信の動作チェック程度であれば、PC側で新たなプログラムを組む必要はありません。フリーのターミナルエミュレータ「Tera Term」を使いましょう。以下のサイトからダウンロードしてインストールしてください。
関連リンク: | |
---|---|
⇒ | Tera Term |
Tera Termを起動すると、図2のような接続先を選択するダイアログが表示されます。[シリアルポート]を選択し、マイコンが接続されているポートを選択して[OK]ボタンを押下します。
次に、シリアルポートの設定を行います。表示されたウィンドウから、[設定]―[シリアルポート(E)]を選択します。すると、シリアルポート設定のダイアログが表示されますので、図3のように設定して[OK]ボタンを押下してください。
この設定を見てみると、マイコン側のシリアル通信初期化関数で設定した内容とよく似ていることが分かりますね。どのような通信プロトコルでもそうですが、お互いの設定を同じにしておかないと通信はできません。
これで準備完了です。マイコンの電源を入れてみてください。初めは何も出てきませんが、キーボードで文字を入力すると、画面に入力した文字が表示されます。ここで表示される文字は、キーボードから入力された文字がマイコンに送信され、マイコンが同じ文字を送信してきた結果です。その証拠に、マイコンのスイッチを切った状態でキーボードを打っても何も表示されません。
いかがでしたか? 今回は前回に比べてかなり難しくなったと思います。しかし、今回の実装も結局は“レジスタ操作”です。しかも、ほとんどの手順はデータシートに書いてあることをそのまま実装しただけです。各レジスタ操作の意味まではきちんと理解できなかったかも知れませんが、やっていること自体は実にシンプルです。今回作った関数をベースに、自分でいろいろなシリアル通信のプログラムを作ってみてください。文字列を送受信したり、送られてきた文字に応じてLEDを光らせたりすると面白いかも知れませんね。
次回は、いよいよ「Windows Embedded CEとSHマイコンでシリアル通信するアプリケーション」を開発します。お楽しみに! (次回に続く)
Copyright © ITmedia, Inc. All Rights Reserved.