シリアル通信制御方法

1.シリアル通信とは?

  「シリアル通信」とは、一般にコンピュータ機器を接続する方法の一つで、
 接続する線の本数を減らし、かつ遠距離まで信号が送れるようにした方式を
 呼びます。このとき信号が1ビットごとにシリアル(直列)に送られるため
 シリアル通信と呼ばれます。

2.パソコンとの接続

  ここでは通信接続相手がパソコンとします。しかし、このシリアル通信の接続
 は標準化されており、「RS232C」と呼ばれ、ほとんどのパソコンやモデム
 がこの規格に従っていますので同じように接続することができます。
 この接続には「25ピンDSUBコネクタ」か「9ピンミニDSUBコネクタ」
 と呼ばれるコネクタが一般的に使われており、それを前提に説明します。
 コネクタのピン番号と信号、および簡易的な使い方は下表となります。

ミニDSUB
コネクタ
25ピン
DSUB
 信 号 名 称 簡易な使い方
  1   8 CD(Data Carrier Detect) 入力、使わない
  2   3 RD(Receive Data) 入力、相手TDに接続
  3   2 TD(Transmit Data) 出力、相手RDに接続
  4  20 DTR(Data Terminal Ready) 出力、使わない
  5   7 SG(Signal Ground) グランド、相手SGに接続
  6   6 DSR(Data Set Ready) 入力、使わない
  7   4 RTS(Request to Send) 出力、相手CTSと接続
  8   5 CTS(Clear to Send) 入力、相手RTSと接続
  9  22 RI(Ring Indicate) 入力、使わない


3.シリアル通信制御プログラムの構成 

  今回の通信用プログラムはタイマー割込みを使っています。この割り込みを使う
 ことにより、各ビットの信号を待っている間、コンピュータには他のことをさせる
 ことができます。従って、通信をしながら何かをしたい時、例えば表示をしたり
 モータを動かしたりするようなことが可能となります。
 全体は3つのプログラムモジュールと1つの変数定義部分から出来ています。
   (1)変数定義部分
     通信プログラムで使う変数や定数を定義しています。ここで重要なのは、
     通信速度を変更するためのパラメータです。速度を変えるためには2個の
     パラメータの値を変更しアセンブルし直します。
   (2)割込み処理モジュール(INTERRUPT)
     これは割込みが入って来た時、その時のレジスタを保存したあと、
     各フラグを見てどの状態の割込みかを判定して必要な処理へジャンプ
     します。また各処理が終了したあと割込みが入った所へ戻るため、
     保存しておいたレジスタを元にもどしてリターンします。
   (3)送信プログラムモジュール(PUTCHAR)
     送信は比較的単純で、送信要求があったら、まずスタートビットを出力し
     一定時間のタイマーをスタートさせます。タイマーの割込みが入って
     きたら、順次データを1ビットづつシフトしながら出力します。最後に
     ストップビットを送信して完了します。
   (4)受信プログラムモジュール(GETCHAR)
     受信処理の部分で、まずスタートパルスを受信できるようにタイマーを
     フルカウントより一つ少ない状態に設定しておきます。そこでスタート
     ビットにより+1カウントすると割込みが発生し、スタートビットの検出
     が出来たことになります。あとは、一定時間毎のタイマー割込みが発生
     する様にしてその都度データを入力します。
     これを図で示すと下図の様になります。
     

     ここで少し工夫してあるのは、まずスタートビットの割込みが入って
     来たら、確かめるため10usec待ってもう一度入力を読み込んで見て
     同じ信号だったらスタートビットをみなします。違っていたらノイズで
     割込みが入ったものとして無視し次のスタートビットの割込みを待ちます。
     確かにスタートビットを受け取ったら次のタイマーは1.5ビット分の
     時間としてスタートします。そしてタイムアップの割込みが入って来たら
     データとして入力を読み込みます。これで、間違いなくデータの真ん中
     で読み込んだことになります。以下は1ビット分の時間のタイマとして
     続けます。

4.変数、定数の定義

 (1)通信速度用パラメータ
   通信速度を可変にするため2個のパラメータを使っています。その値の求め方
   下記のようにします。
    まず通信速度から1ビットのパルス幅を求める。次にマイコンのクロックで
    それを割ってカウンタの値を求める。(1カウントは4クロック分)
    さらにそのカウント値を実現するプリスケーラとTMR0の値を求める。
    下表は実際の例で、クロックは10MHzの場合です。

     
BaudRate PulseWidth

Counter

prescale

TMR0(BITTMR)

width
300bps 3333.33usec

8333

64(5)

130(7E)

3328usec
1200 833.33

2083

16(3)

130(7E)

832
2400 416.67

1041

8(2)

128(80)

409
4800 208.33

521

4(1)

124(84)

198
9600 104.17

260

2(0)

122(86)

99
 ここで4800、9600bpsの場合には、プログラムの実行時間による遅れの分
 を差し引いた値となっています。(約6usec分)
 また上記のprescaleの括弧内の値がプリスケーラ設定用の値となり、これ
 をBAUDRATEの値として設定します。


プログラムリスト上は下記となっています。
;
;BAUDRATE:boud rate 300 to 9600 at 10MHz clock.
; 5=300bps 3=1200bps 2=2400bps 1=4800bps 0=9600bps 
;
BAUDRATE  SET  0   ;ここにプリスケーラ値を指定する
BITTMR   SET  086H  ;TMR0に設定する値で上表の値を指定する
BITTMR1  SET  050H  ;スタートビットの時の約1.5ビット分の値

 (2)その他の変数
   その他汎用に使う変数と、フラグ類は下記で定義されています。

;*************************************
; Define constant module
;*************************************
#DEFINE  TXBUSY  RESULT,0  ;sending
#DEFINE  RXBUSY  RESULT,2  ;receiving
#DEFINE  RECV   RESULT,3  ;receive end
#DEFINE  ERROR  RESULT,4  ;error bit

;**** Define Variables *****
RESULT  EQU    0CH     ;current status
WREG   EQU   0DH     ;wreg save area
SREG   EQU    0EH     ;status reg save area
BITCNT  EQU    0FH     ;send bit counter
EXTRA  EQU    10H     ;stop bit flag
TXREG  EQU    11H     ;send data buffer 
RXREG  EQU    12H     ;receive data buffer
CNT2   EQU    13H     ;counter for delay

5.割込み処理プログラム

  割込みが入った時にまず実行する処理です。ここではレジスタの待避、復旧と
  各種フラグを見てどの割り込みかを判定しそれぞれの処理に分岐します。
  この処理のリストは下記です。

 
;****************************************
; Interrupt process module
;****************************************
INTERRUPT            ;4番地からここにジャンプする
     BTFSS  INTCON,T0IF  ;TMR0の割込みか確認
     RETFIE         ;違っていたら何もしないで戻る
     BCF   INTCON,T0IF  ;TMR0の割込みフラグクリア

;**** W register & status registerを待避 
     MOVWF  WREG     ;W regを待避
     SWAPF  STATUS,W   ;statusをwregに移動
     MOVWF  SREG     ;statusを待避
     BTFSC  TXBUSY    ;送信中か?
     GOTO   TXNEXT    ;送信中なら次のビット送信へ
     BTFSC  RXBUSY    ;受信中か?
     GOTO   RXNEXT    ;受信中なら次のビット受信へ
     GOTO   STARTBIT   ;スタートビット割込み処理へ

;**** registerを復帰させ割込みの入った場所へ戻る
RESTORE
     SWAPF  SREG,W    ;status取り出し
     MOVWF  STATUS    ;status復帰
     SWAPF  WREG,F    ;wreg取り出し
     SWAPF  WREG,W    ;wreg復帰
     RETFIE         ;次の割込み許可リターン


6.送信処理プログラム

  送信はタイマーで一定時間毎に割込みを出し、その都度送信データのビットを
  順次送り出す。送り出す先は常にRA3のポートである。
  下記リストで説明する。
 (1)まず送信要求がCALLされると、PUTCHAR処理ででTXBUSYフラグをセットして
  送信中とし、続いてスタートビットを送信してタイマーを1ビット分の時間に
  セットしてスタートさせてから割込み待ちとする。(TXSTART)
 (2)タイマーがカウントアップして割込むとTXNEXT処理に分岐してデータの送信
  を1ビット毎に行う。そのビット毎にタイマーをセットして割込みを待つ。
 (3)最後のデータ送信後にはストップビットの送信(STOPBIT)に分岐し1ビット分
  のストップビットを出力する。
 (4)次の割込みですべて終了しDONEに分岐して割込みを禁止にして終了する。

;************************************
; Transmission process module
;************************************
;送信開始処理
PUTCHAR
     BSF   TXBUSY    ;送信中フラグをセット
     MOVLW  8       ;送信データビット数を8にして
     MOVWF  BITCNT    ;ビットカウンタにセット
     MOVLW  1       ;ストップビット数を1にして
     MOVWF  EXTRA     ;カウンタにセット
     CALL   TXSTART    ;スタートビット送信
     BCF   INTCON,T0IF  ;割込みフラグクリア
     BSF   INTCON,T0IE  ;タイマ割込み許可
     RETFIE
;**** スタートビット送信処理 ****
TXSTART
     CLRF   TMR0     ;タイマセット
     BSF   STATUS,RP0  ;page 1
     CLRWDT
     MOVLW  BAUDRATE   ;プリスケーラセット
     MOVWF  OPTION_REG
     BCF   STATUS,RP0  ;page 0
     BCF   PORTA,3    ;スタートビットセット
     MOVLW  BITTMR    ;タイマ値取り出し
     MOVWF  TMR0     ;タイマスタート
     RETURN
;****** データビットの送信処理 *****
TXNEXT
     MOVLW  BITTMR    ;タイマ再スタート
     MOVWF  TMR0
     MOVF   BITCNT    ;全ビット終了か?
     BTFSC  STATUS,Z
     GOTO   STOPBIT    ;終了時ストップビット送信へ
NEXTTXBIT
     DECF   BITCNT,F   ;ビットカウンタ−1
     BSF   STATUS,C   ;データビットをシフト
     RRF   TXREG     ;
     BTFSS  STATUS,C   ;データビットの0,1により
                 ;RA3に0,1を出力
     BCF   PORTA,3    ;0 out
     BTFSC  STATUS,C
     BSF   PORTA,3    ;1 out
     GOTO   RESTORE    ;return                
;**** ストップビット送信処理 ****
STOPBIT
     MOVF   EXTRA,W    ;ストップビット送信済みか?
     BTFSC  STATUS,Z   ;
     GOTO   DONE     ;送信済み終了へ
     DECF   EXTRA,F    ;ストップビットカウンタ−1
     BSF   PORTA,3    ;ストップビット出力
     GOTO   RESTORE    ;return
;*** 全データ送信完了、終了処理 ****
DONE
     BCF   INTCON,T0IE  ;タイマ割込み禁止
     BCF   TXBUSY    ;送信中フラグクリア
     GOTO   RESTORE    ;return 

7.受信処理プログラム

  受信は少し処理内容が複雑ですが、流れは単純です。
 (1)まず最初に受信要求があると、GETCHARでスタートビットの受信準備処理
  を実行します。これにはタイマをフルカウント一つ手前として割込み待ち
  とします。
 (2)スタートビット入力によりタイマの割込みが入ったら、STARTBITに分岐し
  10usec待ってもう一度データを入力しスタートビットである事を確認します。
  もしそうで無かったら、ノイズによる誤割込みとして何もせず次のスタート
  ビット待ちとして戻ります。(NOISE) 確かにスタートビットだったら、
  受信中フラグ(RXBUSY)をセットし、タイマに1.5ビット幅分のタイマ値を
  セットして割込み待ちとします。
 (3)次からの割込みはデータビットとしてデータ受信(RXNEXT)に分岐します。
  ここからは1ビット分の幅の時間にタイマを戻して順次データビットの受信
  としてRXREGに格納していきます。(NEXTRXBIT)
  最後のデータビットの次はストップビットの受信のはずなのでそれを確認
  します。もしストップビットでなかったらエラーとしてERRORフラグをセット
  して終了します。終了時には受信中フラグ(RXBUY)をクリアします。また
  正常にデータが受信できた時にはデータ受信フラグ(RECV)をセットします。

;*************************************
; Receiving process module
;*************************************
GETCHAR
     BSF   RECV      ;データ受信フラグクリア
     MOVLW  9       ;データビット数を8として
     MOVWF  BITCNT     ;ビットカウンタにセット
     CLRF   RXREG     ;データバッファクリア
     BCF   ERROR     ;エラーフラグクリア
;**** スタートビット受信準備処理 ****
     CLRF   TMR0      ;タイマを初期セット
     BSF   STATUS,RP0   ;page 1
     CLRWDT          ;clear WDT
     MOVLW  038H      ;ウォッチドッグタイマモード
     MOVWF  OPTION_REG   ;でプリスケーラを1にセット
     BCF   STATUS,RP0   ;page 0
     MOVLW  0FFH      ;タイマをFFにセット
     MOVWF  TMR0      ;タイマスタート
     BCF   INTCON,T0IF  ;タイマ割込みフラグクリア
     BSF   INTCON,T0IE  ;タイマ割込み許可
     RETFIE         ;割込み待ちへ

;**** スタートビット割込み処理 ****
STARTBIT
     CLRWDT         ;
     CALL   TIME10    ;10usec待ち
     BTFSC   PORTA,4    ;再読込みスタートビットか?
     GOTO   NOISE     ;違う時
     BSF    RXBUSY    ;受信中フラグON
;データ受信準備
     CLRF   TMR0     ;タイマ再セット
     BSF    STATUS,RP0  ;page 1
     MOVLW   BAUDRATE   ;プリスケーラセット
     MOVWF   OPTION_REG
     BCF    STATUS,RP0  ;page 0
     MOVLW   BITTMR1    ;1.5ビット幅の時間にセット
     MOVWF   TMR0     ;タイマスタート
     GOTO   RESTORE    ;return
;*** スタートビットでない時の処理 ****
NOISE    
     MOVLW   0FFH     ;タイマ再セット
     MOVWF   TMR0
     GOTO   RESTORE    ;return
;**** データビット受信処理 ****
RXNEXT
     BSF    STATUS,RP0  ;page 1
     CLRWDT          ;タイマ再セット
     MOVLW   BAUDRATE     
     MOVWF   OPTION_REG
     BCF    STATUS,RP0  ;page 0
     MOVLW   BITTMR    ;1ビット幅の時間にセット
     MOVWF   TMR0     ;タイマ再スタート
     DECFSZ  BITCNT,F   ;ビットカウンタ−1、終了か?
     GOTO   NEXTRXBIT   ;次のデータ受信へ
;*** ストップビット受信処理 ***
     BTFSS   PORTA,4    ;
データ入力しストップビット確認?
     BSF    ERROR     ;ストップビットでない時エラ
     BCF    INTCON,T0IE  ;割込み禁止
     BCF    RXBUSY     ;受信中フラグリセット
     BCF    RECV      ;データ受信フラグセット
;
;**** 割込み並列処理を実行する時は、ここに受信完了時の処理を***
;   追加し、処理実行後割込み処理から戻る。
;     CALL   RECEIVEPROCESS
     GOTO   RESTORE

;**** データビット受信処理 ***
NEXTRXBIT
     BCF    STATUS,C    ;データの0,1によりRXREG
     BTFSC   PORTA,4    ;に0,1をセットする
     BSF    STATUS,C    ;1 case
     RRF    RXREG,F    ;set data to RXREG
     GOTO   RESTORE
;***** 10usec遅延タイマ *****
TIME10               ;10usec
     MOVLW   7H     
     MOVWF   CNT2    
T_LP2   DECFSZ  CNT2,F     ;2+3*7-1=22    
     GOTO   T_LP2    
     RETURN          ;22+1=23


  次のページへ    目次ページへ