【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
7
1.73
76.8K
3
1.73
----
----
1
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