USARTの使い方 


【USARTとは?】

USARTとは、Universal Synchronous Asynchronous Receiver Transmitter
略で、文字通り汎用の同期式と非同期式のシリアル送受信用の機能を持って
います。
ここでは、最も多い使い方である、非同期式(調歩同期式ともいう)での使い方
を説明します。

シリアル通信や調歩同期式の説明は、別ページを参照して下さい。

【USARTの構成】

USART機能の構成ブロックは簡単に示すと下図のようになっています。
この図のように送信と受信がそれぞれ独立しているので、全二重通信が可能
となっています。つまり、いつでも同時に送信と受信が出来るということです。
しかし、これには送受信のプログラム側も対応させなければ可能とはならず、
これを可能とするためには割込みを使う必要があります。

しかし、ここでの説明は割込みを使わず、プログラムでセンスする使い方です
ので、完全な全二重では無く、半二重通信となっています。正確にいうと、
受信は常時可能ですが、連続送信は全二重では出来ません。


【USARTの動作】

上図でUSARTの動作を説明します。

(1)送信動作
 送信の場合には、まずTRMTかTXIFのステータスでレディー状態を確認し
 送信ビジーでなければ、送信するデータをTXREGレジスタにプログラムで
 書き込みます。(MOV命令) 直後にTXIFがビジー状態にされます。
 後は自動的にデータがTXREGレジスタからTSRレジスタの転送され、
 TSRレジスタからシリアルに変換されてTXピンに順序良く出力されます。
 この転送直後にはTXIFがレディとなり、次のデータをTXREGレジスタに
 セットすることが可能となりますが、実際に出力されるのは、前に送った
 データが出力完了した後となります。
 ここで、シリアルで出力する際の出力パルス幅が、SPBRGにセットされた
 ボーレートを決める値に従って決定され制御されます。
 シリアル出力が完了するとTRMTがレディ状態に戻り、次のデータ送信が
 可能となります

(2)受信動作
 受信の場合には、RXピンに入力された信号を常時監視し、受信サンプル
 で、あらかじめSPBRGにセットされたボーレートに従って入力信号をサン
 プリングして、まずスタートビットを検出したら、その後に続くデータをRSR
 レジスタに順に詰め込んで行きます。そしてストップビットを検出したら、
 RSRレジスタからRXREGレジスタに転送します。
 この時点で、RCIFがレディとなり、受信データの準備が出来たことを知らせ
 ます。プログラムでは、このRCIFを監視して、レディになったら、RXREG
 レジスタからデータを読み込みます。
 このRXREGレジスタは2階層のダブルバッファとなっているので、次の次の
 データを受信完了するまでにデータを取り出せば正常に連続受信が出来る
 ことになります。このダブルバッファのお陰で、受信処理の時間を楽にする
 ことが出来ますが、連続受信の時には、1個のデータを受信する間に処理
 を完了させることが必要です。

【関連レジスタの設定】

USARTを調歩同期で使う場合の設定は下記のようにします。
まず関連するレジスタの一覧表は下記となります。このレジスタの存在する
バンクが分かれているので注意が必要です。特に送信のTRMTステータス
はバンク1側にあるので注意が必要です。

アドレス

バンク0

バンク1

機能概要

0CH

PIR1

  送受信完了フラグ
18H

RCSTA

TXSTA

ステータスとモード設定
19H

TXREG


SPBRG

送信レジスタ
ボーレート設定
20H

RCREG

  受信レジスタ

(1) TXSTAレジスタの詳細と設定
  送信の動作モードを指定するレジスタがTXSTAレジスタで、内部構造は
  下図のようになっています。下図のように普通の調歩同期式の場合には、
  8ビット ノンパリティ を使いますので下図のような指定とします。
  さらに、プログラムセンス方式で、レディチェックをするときには、TRMT
  ステータスを使うと、確実に前のデータの送信が完了してからレディと
  なるので、PIR1レジスタ中のTXIFステータスを使うよりは、確実な半二重
  通信とすることが出来ます。









(2) RCSTAレジスタの詳細と設定
  受信の動作モードを指定するレジスタがRCSTAレジスタで、内部構成は
  下図のようになっています。この設定も送信と同じように、調歩同期式の
  場合には下図のような設定とします。
  受信の場合のレディーチェックはPIR1レジスタ中のRCIFステータスで行い
  ます。












(3) SPBRGの設定方法
  通信速度を決めるのは、SPBRGレジスタによるボーレートジェネレータが
  制御しています。このSPBRGレジスタへに設定する数値とボーレートの
  関係は下表のようになります。但し、下表は調歩同期式の場合だけです。
  同期式の場合には別の値となりますので、PICのマニュアルを参照して
  下さい。

  クロック

ボーレート

20MHz

16MHz

10MHz

SPBRG
設定値

エラー
レイト

SPBRG
設定値

エラー
レイト

SPBRG
設定値

エラー
レイト

1200

255

1.73

207

0.16

129

0.16

2400

129

0.16

103

0.16

64

0.16

9600

32

-1.36

25

0.16

15

1.73

19.2K

15

1.73

12

0.16

1.73

76.8K

1.73

----

----

1.73

  (注)エラーレイトとは、ボーレート周波数のズレの多さを%であらわしたもので
     1フレーム内でのズレになりますが、10ビット(スタートストップ合わせて)
     のフレームでのエラーマージンは、1/2ビット幅までのズレを許容すると
     すれば、50%/10=5%となります。

【USARTの使用例】

実際にUSARTを使った例を説明します。ここでは、パソコンのRS232Cのシリアル
インターフェースとの接続を例にして具体的な使い方を説明します。
まず、このためのPIC側の回路図は下図のようにします。ここでは、必要な部分
のみ示しています。使ったPICはPIC16C73/JPです。
RS232Cのインターフェースに合わせるためのレベル変換には、有名なMAX232
というICを使っています。これには最近は各社から同様な機能のICが発売されて
いるので、どれでもOKです。 パソコン側はDOS/V機であれば、COM2ポートに接続
します。



 

【プログラム例】

上記回路図で実際の通信をテストするためのプログラム例を説明します。
今回テストに使用したプログラムは、下記のような機能をもっています。

・通信速度は19.2Kbpsとし、8ビット ノンパリティの調歩同期式とする。

・パソコンからのデータ受信を常時監視し、データを受信したらデータメモリ
 のバンク1側の96バイトの領域に格納する。
・受信したデータがCRコード(0D)であったら、その時点でデータメモリに格納
 していたデータを順次パソコン側に送信する。
・受信データを格納する時点で96バイトを超えたときには、その時点での
 データメモリの96バイトの内容を全てパソコンへ送信する。
・データ送信の最後には、常に”End of TX”という固定メッセージを付加して
 送信する。

★USARTテストプログラムソースファイル


本プログラム例では、通信処理を行うときのバッファの処理の扱い方も例と
して入れてあります。
 ・データメモリエリアに格納していく方法
 ・固定フォーマットのデータを送信する方法
の2種類を例としてあります。


;*********************************************
;
; USART test program using USART module.
; Test condition is below
;  Mode : Asyncronous transfer mode only
;  Speed: 1200,2400,9600,19Kbps switchable
;  Bit : startx1 datax8 stopx1
;  Not use interrupt
;
;*********************************************
;
   LIST    P=PIC16C73A
   INCLUDE  "P16C73A.INC"

;***********************************
; 変数定義
; バンク1の全部(96バイト)を送受信
; バッファとして使います。
;***********************************
TEMP   EQU  020H    ;work area
POINT  EQU  021H    ;pointer of table

BUFFER  EQU  020H    ;buffer


     ORG  0
;***********************************
; 送受信モードの初期化
; バンクの位置に注意
; Baud rate setting is below
;    Clock 10MHz   20MHz     
;    Baud  SPBRG   SPBRG
;    1200  81H    FFH
;    2400  40H    81H
;    9600  0FH    20H
;    19K   07H    0FH  
;***********************************
INIT
    BSF   STATUS,RP0  ;バンク1に切替
    MOVLW  081H     ;set portc
    MOVWF  TRISC     ;PORTC
;
    MOVLW  020H     ;Set Async mode 
    MOVWF  TXSTA     ;Set TX mode
    MOVLW  07H      ;Set Baud Rate 19Kbps
    MOVWF  SPBRG     ;Set BRG
    BCF   STATUS,RP0  ;バンク0に戻す
    MOVLW  090H     ;Set Async mode 
    MOVWF  RCSTA     ;Set RX mode

;****************************************
; Main routine
; データを受信しバッファに格納する。
; もしデータがCRだったらそれまでのデータを
; 送信出力する。
; またバッファが一杯になった時も送信する。
;****************************************
MAIN
;****** Wait Receive data ******
    MOVLW  0A0H     ;set buffer top address
    MOVWF  FSR      ;間接アドレスポインタ初期化
LPRCV
    BCF   PORTC,5    ;LED on
;
    BTFSS  PIR1,RCIF   ;check receive end flag
    GOTO  LPRCV
;
    BSF   PORTC,5    ;LED off
;**** error check ****
    BTFSC  RCSTA,FERR  ;framing error check
    GOTO  FRAME
    BTFSC  RCSTA,OERR  ;overrun error
    GOTO  OVER
;***** get data and save *****
;** 間接アドレッシングでバッファに格納する ***
    MOVF  RCREG,W    ;get received data
    MOVWF  INDF     ;save in buffer
    SUBLW  0DH      ;CR code?
    BTFSC  STATUS,Z   ;data=CR?
    GOTO  SEND     ;to transfer
;**** if buffer full then end *****
CHKBF
    INCF  FSR,F     ;pointer+1
    BTFSS  STATUS,Z   ;buffer full?
    GOTO  LPRCV
    GOTO  SEND     ;full then end 


;******** ERROR PROCES ******
;**** framing error
FRAME
    MOVF  RCREG,W    ;dumy input & reset FERR
    MOVLW  '?'
    MOVWF  INDF     ;save ?
    BTFSS  RCSTA,OERR  ;check more error?
    GOTO  CHKBF     ;to next
;***** overrun error
OVER
    BCF   RCSTA,CREN  ;reset OERR
    BSF   RCSTA,CREN
    MOVLW  '?'
    MOVWF  INDF     ;save ?
    GOTO  CHKBF     ;to next

;*************************
;****** Send answer ******
SEND
    MOVLW  0A0H     ;reset pointer
    MOVWF  FSR
LPSD
    BCF   PORTC,5   ;LED on 
    MOVF   INDF,W    ;get data
    CALL   TX      ;send execute
    BSF   PORTC,5   ;LED off
    MOVF   INDF,W    ;re-get data
    SUBLW  0DH     ;CR?
    BTFSC  STATUS,Z   ;end check
    GOTO   TEXT     ;end text send
;**** if buffer end then end *****
    INCF   FSR,F    ;pointer+1
    BTFSS  STATUS,Z   ;buffer end?
    GOTO   LPSD     ;loop
    GOTO   TEXT     ;end

;************ text send process  *****
;** 固定データの送信例 ****
TEXT
    CLRF   POINT    ;reset table pointer
LPTEX
    MOVF   POINT,W   ;get pointer offset
    ANDLW  0FH     ;limit upper
    CALL   TABLE    ;get text data
    ADDLW  0      ;test zero?
    BTFSC  STATUS,Z   ;end zero?
    GOTO   MAIN
    CALL   TX      ;send
    INCF   POINT,F   ;pointer+1
    GOTO   LPTEX
;***** text data table *****
;** RETLW命令でテーブルを作成 ****
TABLE
    ADDWF  PCL,F    ;PC+offset
    DT    "End of TX",0,0,0,0,0,0,0,0


;**************************************
; Transmit subroutine
; レディチェックは送信レジスタ空で確認
; つまり、TRMT=1でレディと判定
; TXSTAのあるバンクに注意
;**************************************
TX
    MOVWF  TEMP     ;data save
    BSF   STATUS,RP0  ;switch to Bank1
LPTX
    BTFSS  TXSTA,TRMT  ;ready check
    GOTO   LPTX
;
    BCF   STATUS,RP0  ;return to Bank0
    MOVF   TEMP,W    ;get data
    MOVWF  TXREG     ;start send
    RETURN

    END




      目次ページへ