Renesas Synergy™

FAQ 1006965 : CTSなどの制御信号を用いた調歩同期通信を行ないたい。マイコン内蔵のUARTを用いた実現方法を知りたい。

ここでは、78K0S/KA1+に内蔵されたUART6を用いた例を考えてみます。UART6はシフト・レジスタとバッファ・レジスタの2段バッファ構成になっていますが、複数キャラクタを送受信する場合には別途、送信用と受信用にバッファ・メモリを準備する必要があります。また、通常の処理と送受信処理を並行して行なえるように割り込みを用いた制御を行なうものとします。
ここでは、受信バッファの状態を送信側に知らせるためにP40をRTS信号(送信要求信号)、P41(INTP3)をCTS信号(送信許可信号)として使用します。このときの接続例を下図に示します。この例のように、対応した信号同士をクロスで接続します。



バッファ・メモリとしては送受信共に16バイトの容量を確保し、リング・バッファとして使用します。16バイトのどれかを示すには4ビットオフセットを使用します。書き込み用と読み出し用のふたつのオフセットを比較することで、0バッファが空)から15バッファに15バイトデータ蓄積されている)までの状態を表すことができます。バッファの確実な制御のために、16バイト蓄積された状態はオーバフローとして扱い(そのような状態にしない)ます。

受信側でのリング・バッファの構成例を下図に示します。左側に受信処理を示し、右側が受信バッファからの読み出しを示します。受信データのバッファへの書き込みにより、受信バッファに13バイトのデータが埋まる(読み出し用オフセットから書き込み用オフセットを引いた値(空き)が3キャラクタになる)と、送信要求(RTS信号)をオフにします。バッファの空きが3キャラクタ以下になると送信要求をオンにします。RTS信号の出力は単純なポート出力として制御します。



送信側では送信要求を送信許可(CTS信号)として扱い、オフしたら新たな送信を中止します。CTS信号は立ち下がりエッジ検出による割り込みを送信許可(通信再開)のトリガで使用すると共に、次の送信データの書き込み時にポート入力として確認で使用する方法を組み合わせます。
この制御を行なう際の送信側の処理を以下に示します。送信処理では、送信するデータは送信用バッファに一旦蓄積します。その上で送信可能であれば送信処理を起動します。なお、起動処理は単に送信完了割り込み要求フラグをセットするだけです。また受信側からのCTS信号の立下り割り込みでも起動処理を行ないます。実際のデータ送信は送信完了割り込み(INTST6)処理の中で行ないます。INTST6処理では送信が可能で、送信するデータがあれば次のデータをUART6の送信バッファに書き込んで送信を行ないます。また、全てのデータの送信が完了すると送信中フラグ(これは起動処理の中でセット)をクリアして処理を終了します。



プログラムは大きく分けて、以下に示す5つの部分から構成されます。
①送信バッファへの送信データの追加(putTxDATA
②受信バッファから受信データの読み出し(getRxDATA
CTS立下り割り込み処理(CTSONINT
④受信完了割り込み処理(RXRDYINT
⑤送信完了割り込み処理(TXRDYINT

これ以外に受信エラー割り込み処理とバッファの状態をチェックするサブルーチンがあります。

①送信バッファへの送信データの追加(putTxDATA)
Aレジスタに送信したいデータをセットしてサブルーチン・コールすることで使用します。バッファ内のデータが15キャラクタになるとそれ以降はキャリーをセットしてエラーを示します。
15キャラクタ未満の場合には、書き込むためのオフセット(下位4ビットのみ使用)から書き込むアドレスを計算してそこに送信データを格納します。オフセットを更新(+1)してバッファ処理は完了し、UART6の制御を行ないます。その際に割り込みが入ると余分な送信完了割込みが生じる可能性があるので、以降は排他制御のために割り込み禁止で処理します。CTS信号がハイ・レベルであれば、新たな送信は起動しません。そうでないときには、起動中フラグをセットし、送信完了割り込み要求フラグをセットして処理を終了します。

;
;  送信バッファへのデータの書き込み
;
putTxDATA:
PUSH    HL
PUSH    AX
CALL    !CHKTXDATA      ; バッファをチェック
ADD     A,#0F1H         ; バッファ・フルでキャリー
BC      $TXEXIT         ; エラーで終了
MOV     A,#0FH
AND     A,TXWTPT        ; 下位4ビットを抽出
ADD     A,#LOW TXBUFF   ; オフセットを加算
MOV     L,A
MOV     H,#HIGH TXBUFF
POP     AX              ; データを復帰
PUSH    AX
MOV     [HL],A          ; データをバッファにセット
INC     TXWTPT          ; 書き込みオフセット更新
DI                      ; フラグ操作の排他処理のため
;
;  送信が止まっているので、送信可能なら再開する
;
BT      P4.1,$TXEXIT    ; CTSがハイなら再開しない
SET1    TXFLAG.0        ; 送信中フラグをON
SET1    STIF6           ; 起動のための割り込み要求セット
TXEXIT:
EI
POP     AX
POP     HL
RET

オフセットは下位の4ビットだけが有効なデータですが、更新は8ビットまで行ないます。オフセットから実際のバッファのアドレスを計算するときに下位の4ビットだけを使用するようにしています。


②受信バッファから受信データの読み出し(getRxDATA)
バッファを調べ、バッファが空ならゼロ・フラグをセットしてもどります。データがあれば、残りデータが規定値(BUFFEMP)以下ならRTS信号ロウ・レベルにして受信可能であることを示します。読み出し用のオフセット(下位ビット)から読み出すデータのアドレスを計算して、バッファからデータを読み出します。その後に、読み出しオフセットを更新して処理を終了します。

;
;  受信バッファからデータの読み出し
;
;出力
;データがあるとき
;  Aレジスタ   :読み出しデータ
;  ZERO         :0
;データが無いとき
;  Aレジスタ   :0
;  ZERO         :1
;
getRxDATA:
CALL    !CHKRXDATA      ; データ数チェック
BZ      $GETEXIT        ; 空なら分岐
PUSH    PSW             ; フラグをセーブ
CMP     A,#BUFFEMP      ; 残りをチェック
BNC     $GETNEXT        ; 指定値以下なら
CLR1    P4.0            ; RTSを立ち下げる
GETNEXT:
PUSH    HL
MOV     A,#0FH
AND     A,RXPOINTER     ; オフセット計算
ADD     A,#LOW RXBUFF   ; 下位アドレスの計算
MOV     L,A
MOV     H,#HIGH RXBUFF
MOV     A,[HL]          ; データの読み出し
INC     RXPOINTER       ; 読み出しポインタ更新
POP     HL
POP     PSW             ; フラグを復帰
GETEXIT:
RET

CTS立下り割り込み処理(CTSONINT)
CTS信号の立下り受信側のバッファに空きができたことを示す)エッジで発生した割り込みの処理です。CTS信号を入力ポートP41から読み、ロウ・レベルである(ノイズ入力でない)ことを確認します。ロウ・レベルなら、送信許可の処理を行ないます。既に、送信が起動されている(送信中フラグがセットされている)か、送信するデータがなければ、何もせず終了します。送信するデータが残っていれば送信中フラグをセットして、送信完了割り込みを起動します。

;
;  INTP3(立下り検出)割り込み処理
;
;  CTSが立ち下がり、送信可能になったときの処理
;
CTSONINT:
BT      P4.1,$CTSONEXIT ; ノイズ対策
BT      TXFLAG.0,$CTSONEXIT
;
;  送信中ではないときの処理
;
PUSH    AX
CALL    !CHKTXDATA      ; バッファをチェック
POP     AX
BZ      $CTSONEXIT
SET1    TXFLAG.0        ; 送信中フラグをON
SET1    STIF6           ; 起動のための割り込み要求セット
CTSONEXIT:
RETI

④受信完了割り込み処理(RXRDYINT)
受信完了割り込みにより起動され、受信バッファへの書き込み用オフセットから書き込むアドレスを計算し、受信したデータを保存します。オフセットを更新後、バッファ内のデータ数をチェックして、規定値(BUFFFULL)以上ならRTS信号をハイ・レベルに立ち上げます。

;
;  UART6データ受信処理
;
RXRDYINT:
PUSH    AX
PUSH    HL
MOV     A,RXWTPT        ; 受信データ書き込みオフセット
AND     A,#0FH
ADD     A,#LOW RXBUFF
MOV     L,A
MOV     H,#HIGH RXBUFF  ; ポインターをセット
MOV     A,RXB6          ; 受信データ読み出し
MOV     [HL],A          ; データをバッファに保存
INC     RXWTPT          ; オフセットを更新
POP     HL
CALL    !CHKRXDATA      ; バッファの状態をチェック
CMP     A,#BUFFFULL
BC      $RXRDYEXIT      ; 13バイト以下なら戻る
SET1    P4.0            ; RTSを立ち上げる
RXRDYEXIT:
POP     AX
RETI

⑤送信完了割り込み処理(TXRDYINT)
実際のデータ送信処理を行なう部分です。データ送信は必ずこの送信完了割り込み処理の中で行われます。処理を開始するとTXB6が空かを確認(空のはずであるが念のために確認)します。次にCTS信号を確認してハイ・レベルになっているか、リング・バッファが空になっていれば、新たなデータの送信は行ないません。さらに、TXS6が空になっているかを確認し、空なら送信中フラグクリアします(このときにはUART6からこれ以上は送信完了の割り込みが発生することはありません。次の起動はputTxDATAでの新しい送信データの書き込みでのプログラムによるセットか、その後のINTP3割り込み処理の中でのプログラムでのセットによるものです)。
送信可能状態で、次に送信すべきデータがリング・バッファに残っていれば、そのデータをUART6に書き込んで読み出し用のオフセットを更新します。

;
;  UART6データ送信完了処理
;
TXRDYINT:
PUSH    AX
PUSH    HL
MOV     A,ASIF6
BT      A.1,$TXRDYEXIT  ; 送信中で抜ける
;
; TXB6が空ならば、次データ送信のためにCTSをチェックする。
;CTSがオンなら残りデータの送信を継続し、オフならば現在の
;データの送信完了で送信中ステータスをクリアする。
;

BT      P4.1,$CTSOFF
CALL    !CHKTXDATA      ; 残りデータをチェック
BZ      $NODATA
MOV     A,TXPOINTER     ; 出力データ用オフセット読み出し
AND     A,#0FH
ADD     A,#LOW TXBUFF
MOV     L,A
MOV     H,#HIGH TXBUFF
MOV     A,[HL]          ; データ読み出し
MOV     TXB6,A          ; 送信
INC     TXPOINTER       ; 読み出しオフセット更新
POP     HL
POP     AX
RETI
CTSOFF:
NODATA:
BT      A.0,$TXRDYEXIT
; 送信動作を完了
CLR1    TXFLAG.0
TXRDYEXIT:
POP     HL
POP     AX

⑥その他の処理
UART6の受信でエラーが発生した場合の処理や送受信のリング・バッファの状態をチェックする処理です。
受信でエラーが発生した場合にはそのときのASIS6の内容をエラー・ステータスとしてセットし、受信したデータは読み飛ばします。
リング・バッファの状態のチェックは書き込みと読み出しの2つのオフセットを比較(書き込み用から読み出し用を引く)、結果の下位4ビットに書き込まれたデータ数を得ています。

;
;  UART6受信エラーの処理
;ASIS6レジスタの内容をフラグにコピーするのみ
;
RXERRORINT:
PUSH    AX
MOV     A,ASIS6         ; ステータスの読み出し
MOV     RXSTATUS,A
MOV     A,RXB6          ; データのダミー読み出し
POP     AX
RETI

;
;  受信データ数確認
;
;出力
;  Aレジスタ   :バッファされたデータ数
;  ZERO         :空なら1
;
CHKRXDATA:
MOV     A,RXWTPT        ; 書き込みオフセットの読み出し
SUB     A,RXPOINTER     ; 書き込み-読み出し
AND     A,#0FH          ; 有効ビットのみ抽出
RET

;
;  送信待ちデータ数確認
;
;出力
;  Aレジスタ   :送信待ちデータ数
;  ZERO         :空なら1
;
CHKTXDATA:
MOV     A,TXWTPT        ; 書き込みオフセットの読み出し
SUB     A,TXPOINTER     ; 書き込み-読み出し
AND     A,#0FH          ; 有効ビットのみ抽出
RET

リング・バッファ関係のメモリの定義は以下のようになります。初期化の段階でこれらの内容は全て0にクリアしておきます。

;
;  送受信用16バイトのリング・バッファ領域
;
;
DSEG    SADDRP
RXBUFF:
DS      16              ; 受信バッファ

TXBUFF:
DS      16              ; 送信バッファ
;
;  リング・バッファのアクセス用オフセットは各バッファで読み出しと
;書き込みを1バイトづつ準備し、その下位4ビットを有効とする
;
RXPOINTER:
DS      1               ; 受信データ読み出しオフセット
RXWTPT:
DS      1               ; 受信データ書き込みオフセット
TXPOINTER:
DS      1               ; 送信データ読み出しオフセット
TXWTPT:
DS      1               ; 送信データ書き込みオフセット

RXSTATUS:
DS      1               ; 受信エラー・ステータス
TXFLAG:
DS      1               ; 送信動作モードフラグ
;  ビット0が1なら送信動作中、0なら送信していない

また、ベクタ・テーブル関係とプログラムの起動処理関係の例は以下のようになります。使用していない割り込みのベクタにはダミーのアドレスを設定しています。

DSEG    IHRAM
DS      20H             ; スタック領域確保
STACKTOP:

RSTVECT CSEG    AT      0
DW      START           ;00:リセットスタート処理のベクタ
INTVECT CSEG    AT      18H     ; ここでは以下の割り込みを定義
DW      CTSONINT        ;18:INTP3
DW      DUMMY           ;1A:INTTM80
DW      RXERRORINT      ;1C:INTSRE6
DW      RXRDYINT        ;1E:INTSR6
DW      TXRDYINT        ;20:INTST6

@@OPTB  CSEG    AT      0080H
DB      10011100b
DB      11111111b

START:
MOVW    AX,#STACKTOP
MOVW    SP,AX           ; RAMの先頭部分にスタックを設定

この後にUART6を使用するための初期設定が以下の例のように続きます。

;
;  メモリの初期化
;
MOVW    HL,#RXBUFF
MOV     A,#0
MEMLOOP:
MOV     [HL],A
INC     L
BNZ     $MEMLOOP

MOV     CKSR6,#1                ; プリスケーラで1/2分周
MOV     BRGC6,#218              ; 1/218分周する
MOV     ASIM6,#10010000b        ; 受信エラーでINTSRE6発生
MOV     ASICL6,#00000010b
SET1    TXE6                    ; 送信許可に設定
SET1    RXE6                    ; 必要なら受信許可も設定
MOV     P4,#00001000b           ; 兼用のポートをハイに設定
CLR1    PM4.3                   ; TxD6端子を出力モードに設定
;
;  ハンドシェイク関係の初期化
;
CLR1    PM4.0                   ; RTS端子を出力モードに設定
MOV     INTM1,#00               ; 立下りエッジに設定
;
;  割り込み関係の初期化
;
MOV     IF0,#00                 ; 割り込み要求クリア
MOV     IF1,#00
MOV     MK0,#0FFH
MOV     MK1,#10001011b          ; シリアルとINTP3のマスク解除
EI                              ; 割り込み許可

⑦使い方
送信する場合にはAレジスタに送信データをセットしてputTxDATAをコールします。バッファがいっぱいなら、キャリーをみてループさせています。同様に受信ではgetRxDATAをコールします。データがなければゼロ・フラグで確認します。

;
;  送信の例
;
MOV     A,#41H
TX15LOOP:
CALL    !putTxDATA              ; データ送信
BC      $TX15LOOP               ; エラーなら繰り返し

;
;  受信の例
;
RXCHARLOOP:
CALL    !getRxDATA              ; データ読み出し
BZ      $RXCHARLOOP             ; データがなければループ

 

適用製品

RL78 ファミリ
78K ファミリ
他にご質問がございましたら、リクエストを送信してください