USARTの使い方 


【USARTとは】

 USART(Enhanced Universal Synchronous Asynchronous Receiver Transmitter)
または、UART(Universal Asynchronous Receiver Transmitter)は、古くから使われている
基本のシリアル通信方式をサポートするモジュールです。

 汎用のシリアル通信機能で、パーソナルコンピュータや、ほかの機器とRS232C(EIA232-D/E)
という規格のシリアル通信でデータ通信を行うことができます。

 USARTの場合は、名前の通り全二重の非同期式通信(調歩同期式とも呼ばれる)と、
半二重の同期式通信に対応しており、UARTの場合は全二重の非同期通信のみに対応
しています。

 しかし同期式通信は、比較的簡単な周辺デバイスとのデータ通信用として設計されているので、
伝送制御手順を含むようなハイレベルの同期式通信に使うには無理があります。
このためほとんど使われませんのでここでは非同期通信方式に限定して説明します。


《通信データフォーマット》
 調歩同期方式の基本のデータ転送はバイト単位で行われ、下図のフォーマットで1ビットずつ
が順番に送信されます。



 TTL接続の信号ラインの常時状態はHighレベルになっていて、送信を開始する側が任意の
時点でLowとします。このLowになったエッジで通信の開始を示し、ボーレートで決まる1ビット分
だけLowを継続します。これが「スタートビット」と呼ばれる通信開始を示すビットです。

 この後は、ボーレートで決まるパルス幅で8ビットのデータを下位ビット側から出力します。
最後に1ビット分のHighのパルスを出力して終了となります。このHighのビットは「ストップビット」と
呼ばれます。ストップビットの役割は、次のスタートビットが判別できるようにすることです。

 このデータを受信する側は、常時受信ラインをチェックしていて、Lowになるのを検出します。
これでスタートビットを検出したら、そこからボーレットで決まるビット幅ごとにデータとして取り込みます。
8ビットのデータを取り込んだ後、次のビットがストップビットであることを確認して受信終了となります。

 このように、常にスタートビットから送信側と受信側が同じ時間間隔で互いに送信と受信を
行いますから、スタートビットごとに毎回時間合わせが行われることになり、時間誤差が積算
されることがありません。
 したがって、10ビット分の時間の誤差が許容範囲内であれば正常に通信ができることになります。
この誤差の許容範囲はどれほどでしょうか。

 1ビットの取り込みは通常はビットの中央で行われまので、この取り込み位置が1/3ビット
つまり30%程度ずれても正常に取り込みが可能と考えられます。
 10ビットの最後のビットで30%のずれを許容するとすれば、時間誤差は3%の許容差ということに
なります。送信側と受信側で逆方向にずれている可能性がありますから、許容差は±1.5%という
ことになります。

【USARTの内部構成】

 USARTモジュールの内部構成は調歩同期式の場合には下図のようになっています。
図のように送信と受信がそれぞれ独立しているので、全二重通信が可能となっています。
つまり、いつでも同時に送信と受信ができるということです。
 EUSARTとなっている場合は、従来のUSARTのEnhanced版で、ブレーク信号の送受信と
ボーレートの自動検出が可能となっています。



(1) 送信動作
 送信の場合には、まずTRMTTXIFのステータスでレディ状態を確認し、送信ビジー
でなければ送信するデータをTXREGレジスタにプログラムで書き込みます。
直後にTXIFがビジー状態になります。
このあとは自動的にデータがTXREGレジスタからTSRレジスタに転送され、TSRレジスタから、
ボーレートジェネレータからのビットクロック信号に同期してシリアルデータに変換されて
TXピンに順序良く出力されます。

 このレジスタ間の転送直後にTXIFがレディとなり、次のデータをTXREGレジスタにセット
することが可能となりますが、実際に出力されるのは、前に送ったデータがTSRレジスタから
出力完了した後となります。
 シリアルデータで出力する際の出力パルス幅は、ボーレートジェネレータにセットされた値
に従って制御されます。
 シリアル出力が完了しTSRレジスタが空になるとTRMTがレディ状態に戻り、次のデータ送信
が可能となります


(2) 受信動作
 受信の場合には、RXピンに入力される信号を常時監視してLowになるスタートビットを待ちます。
スタートビットを検出したら、1ビット幅の周期で、その後に続くデータを受信シフトレジスタの
RSRレジスタに順に詰め込んで行きます。
 この時の受信サンプリング周期は、あらかじめボーレートジェネレータにセットされたボーレート
に従った周期となります。
 最後のストップビットを検出したら、RSRレジスタからRCREGレジスタに転送します。
この時点で、RCIFフラグが1となり、受信データの準備ができたことをプログラムに通信します。
プログラムでは、割り込みか、またはこのRCIFを監視して、1になったらRCREGレジスタから
データを読み込みます。
 このRCREGレジスタは2階層のダブルバッファとなっているので、データを受信直後でも連続
して次のデータを受信することが可能です。
つまり、3つ目のデータの受信を完了するまでにデータを取り出せば、正常に連続受信が
できることになります。このダブルバッファのお陰で、受信処理の時間をかせぐことができますが、
3バイト以上の連続受信の時には、ダブルバッファであっても次のデータを受信する間に
処理を完了させることが必要です。
そうしないと次のデータの受信に間に合わないのでデータ抜けが発生することになってしまいます。
 このような場合に、オーバーランエラーやフレミングエラーという受信エラーが発生します。
エラーが発生した場合には、いったんRCSTAレジスタをクリアしてUSARTモジュールを
ディスエーブルにしたあと、再度RCSATレジスタを設定しなおす必要があります。


(3) 9ビットモードとアドレス有効化
 9ビットモードというのはUSARTで送受信するデータを9ビットにする方法です。
RS422RS485と呼ばれる方式で、ひとつの伝送線にひとつの親機と複数の子機を接続し、
アドレスで区別して送受信する場合に使います。

 この場合、子機側でADDENをセットしてアドレス検出を有効としておくと、親機側から
送れられてくるデータで9ビット目に1がセットされているデータがアドレスとして扱われ、
この場合のみ子機側で割り込みを生成します。
 子機ではこの割り込みが発生したら受信データと自分に与えられたアドレスとを比較して、
一致した場合のみADDENをクリアして通常データ受信を有効として以降のデータを受信しますが、
一致しない場合にはそのままとしてデータ受信割り込みを生成しないようにします。
これで指定したアドレスの子機と親機間だけで通信ができるようになります。


【USART関連レジスタ】

 USARTを非同期式通信で使う場合の制御レジスタの使い方を説明します。
関係するレジスタは次のようになります。

 ・TXSTA    :送信動作設定
 ・TXREG    :送信データレジスタ
 ・RCSAT    :受信動作設定
 ・RCREG    :受信データレジスタ
 ・BAUDCON   :ボーレート制御
 ・SPBRG     :ボーレート設定下位レジスタ
 ・SPBRGH    :ボーレート設定上位レジスタ


 動作モードを設定するレジスタの詳細は下図となります。



(1) TXSTAレジスタの詳細と設定
 送信の動作モードを指定するレジスタがTXSTAレジスタで、通常は8ビットデータ、
ノンパリティを使うので、図のように“0010 0000”か“0010 0100”と指定します。

 さらに、プログラムセンス方式でレディーチェックをするときには、こちらの
TRMTステータスを使うと、前のデータの送信が確実に完了してからレディとなるので、
途中で通信が打ち切れることなく通信することができます。

 後で説明するPIR1レジスタ中のTXIFステータスを使うときは、送信中にUARTを
ディスエーブルにすることが無いように注意する必要があります。
またTXIFビットを使うときには、割り込みフラグビットですから1を検出したら命令で
クリアする必要があります。


(2) RCSTAレジスタの詳細と設定
 受信の動作モードを指定するレジスタがRCSTAレジスタで、調歩同期式の場合には
図のように“1001 0000”という設定とします。
 受信の場合のレディーチェックはPIR1レジスタ中のRCIFステータスで行います。
このRCIFは割り込みフラグですが、読み出ししかできないビットとなっていて、RCREGを
全部読み出して空にすれば自動的にクリアされます。


(3) SPBRGの設定方法
 通信速度を決めるボーレートは、SPBRGレジスタによるボーレートジェネレータが
制御しています。
 F1ファミリでは機能強化され、BAUDCONレジスタのBRG16ビットをセットすると、
SPBRGレジスタを16ビットとすることができますので、より広範囲で正確なボーレート値が
設定可能となりました。
 このSPBRGレジスタに設定する値XとボーレートBaudは下記の計算式で求められます。
ただし Baud:通信速度、Fosc:クロック周波数となっています。

 このXで設定される通信速度は、クロック周波数とSPBRG設定値で決まりますので、
標準通信速度とぴったり一致しない場合があります。
この誤差が表の中のエラーレイトとして計算されています。
前述のように±
1.5%以下のずれであれば正常通信可能ということになります。

 ① BRGH=0かつBRG16=0の場合
    X = Fosc/(64×Baud) - 1 
 ②BRGH=1かつBRG16=0の場合、またはBRGH=0かつBRG16=1の場合
    X=Fosc/(16×Baud) - 1
 ③ BRGH=1かつBRG16=1の場合
    X = Fosc/(4×Baud) - 1

代表的なボーレートとXの値は下表のようになります。



 割り込みを使う場合に関連するレジスタは下図のようになっています。
送信と受信が独立になっていますから、それぞれを指定して制御する必要があります。




【プログラム例】

《例1》 初期設定例
 実際にUSARTを使ったプログラム例です。
下記はUSARTの初期設定のプログラム例で、Foscが8MHzの場合で19.2kbpsの
通信速度に設定しています。



《例②》 送信と受信のサブ関数例
 次が実際の送信と受信のサブ関数例です。
送信は簡単でビジーチェックをしてからTXREGレジスタに送信データをセットすれば、
後は自動的に行われます。
 注意が必要なのは、TXREGに書き込んだあと、実際の送信がシリアル通信で
行われますから、この関数を実行した直後にスリープにしたり停止したりすると、
通信が途中で止まってしまうことになります。
このような場合には、TRMTビットで終了を確認してからスリープにする必要があります。

 受信はいつ発生するかわかりませんので、ポーリング方式で受信を待つ関数でも
関数内でブロックして永久待ちとならないようにする必要があります。
さらに、受信ができたときには受信エラーチェックが必要です。

そこで、関数では戻り値でこの状態を区別するようにしています。
未受信の場合には0を返し、受信エラーの場合は0xFFを返していて、
正常受信の場合は受信データを返します。
したがって関数を呼ぶ側で戻り値をチェックする必要があります。


 オーバーランエラーの場合は、USARTモジュールをいったん無効化しないとクリア
されず次の受信動作ができません。したがって、いずれのエラーがあった場合にも
RCSTAレジスタをクリア後再設定してから、エラーフラグを返すようにしています。

 このようにポーリング方式で受信を待つのは無駄時間も多くなりますし、応答が
ポーリング周期となってしまいます。これを避ける場合には、割り込みを使います。
通常は受信側のみを割り込みとすれば問題ないですが、送信完了を待つ時間も
有効に使いたい場合には、送信側も割り込みを使います。