USARTのアセンブラによる使い方 


【USARTとは?】

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

【USARTの構成】

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

しかし、ここでの例は割込みを使わず、プログラムでセンスする使い方ですので、全二重
では無く、半二重通信となっています。


【USARTの動作】

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

(1)送信動作
 送信の場合には、まずTRMTかTXIFのステータスでレディー状態を確認し、送信ビジー
でなければ、送信するデータをTXREGレジスタにプログラムで書き込みます。
直後にTXIFがビジー状態にされます。後は自動的にデータがTXREGレジスタからTSR
レジスタの転送され、TSRレジスタからシリアルに変換されてTXピンに順序良く出力され
ます。
このTSRへの転送直後には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レジスタへに設定する数値とボーレートの関係は下表のようになります。
但し、下表は調歩同期式の場合だけです。 

  クロック

ボーレート

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のインターフェースに合わせるための
レベル変換には、有名なMAX232AというICを使っています。これには最近は各社から同様
な機能のICが発売されているので、どれでもOKです。PICのピンはUSARTを使うときには
TX,RXとして固定のピンになっているので変更はできません。

パソコン側はDOS/V機であれば、COM2ポートに接続します。そしてパソコン側はハイ
パーターミナルなどの通信ソフトを起動しておき、通信パラメータをPIC側と合わせて起きます。
(通信速度、データ長、パリティ、スタートストップビット長、転送制御なし)



    

【プログラム例】

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

・通信速度は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




      目次ページへ