PIC18F46K22 EUSART1(RS232C)で受信割込みを使用してパリティ付き受信(アセンブラプログラム)

icon 項目のみ表示/展開表示の切り替え

概要

PIC18F46K22のEUSARTモジュールを使用しRS232Cを経由してパソコンと通信するプログラムである。
パソコンからターミナルで文字列を入力するとPICで受信してパリティーの結果をRed LEDに表示する。偶数パリティーでない場合はRed LEDが点灯する。文字を受信するたびにBlue LEDが点滅する。
パソコン側のターミナルソフトはTera Termを使用し、偶数・奇数それぞれのパリティを設定して動作確認をしました。本プログラムは偶数パリティーを対象としていますのでパソコン側を奇数に設定すると1文字送信するたびにRed Ledが点灯状態となります。
秋月電子 PIC18F46K22使用 マイコンボードをベースとし半田付けされている水晶20MHzをH8/3048ボードの16MHzと交換し64MHzで動作可能とした。このボードはICSP端子を備えておりPICKIT 3で書き込みができ、電源はミニUSBで供給可能である。またユニバーサル基板になっているので簡単に回路を追加することができる。
ちなみに水晶が20MHzの場合は、通信速度がかわるので設定を変更しなければならない。
EUSARTの設定値の計算はPIC18 EUSART ボーレート計算を参照してください。
使用メモリは以下のとおりです
プログラムメモリ 184byte使用
回路は次のとおりである。
cir.svg
回路図(PDF)
例えば9600bpsで割り込みを使用しない場合、1文字の受信に1ms近く受信が完了することを示すフラグをチェックし続けなければなりません。
割込みを使用すると受信後の割込みにより受信完了を知ることができますので、他の処理と同時に処理をすることができます。

通信設定

19200bps, ストップビット 1bit, パリティ 偶数, ストップ 1bit, フロー制御 無

プログラムの説明

初期化

EUSART1の初期化し通信仕様を設定します。
ボーレートの設定はBPS1という定数を設定することによりビルド時に自動的に計算して各種レジスタを設定するようにしてみました。
1byte分のデーターを受信するとRCREG1レジスタに受信データーが格納されます。その時、受信データがあることを知らせる割り込みをRC1IEビットで許可します。
上記の割り込みは周辺の割り込みですので有効にするためにPEIEビットをセットします。
割り込みは高位と低位の2種類使用できます。初期値は高位になっていますのでそのままとします。
高位割り込みを許可するためにGIEビットをセットします。
割り込み発生時のジャンプ先は、割込みベクターでROMアドレスに高位が0008h、低位が0018hにジャンプします。通常は、このアドレスにgoto命令を記述して割り込み処理ルーチンへジャンプさせます。
受信データが発生するまで無限ループで待機します。

高位割り込み処理ルーチン inth

受信データが1byte発生するとinthにジャンプします。
高位割り込みの場合、Wレジスタ、バンクレジスタ及びPCの値はPIC内の専用レジスタに保存されます。割り込みから復帰する場合は、retfie FAST命令を使用して保存された値によりWレジスタ、バンクレジスタ、PCを復帰します。
複数の割り込み要因を許可していないので、割り込み要因をボーリングする作業をしておりません。
サブルーチンusart1_readにより受信データーをWレジスタに取得し、サブルーチンusart1_writeにより送信します。

usart1p_read

受信データを1byte取得しWレジスタに格納します。
パリティーをチェックしRed Ledに結果を反映させます。
受信データーが発生するとRC1IFフラグがセットされますので、セットされるまでボーリングします。
受信データはRCREG1レジスタに格納されているのでWレジスタにコピーします。 スタック上に受信データをプッシュします。
サブルーチンparity2cで受信データのパリティーを計算します。結果はCフラグに反映されます。Cフラグがセット(1)されている場合は受信データの1のビット数が奇数、Cフラグがクリア(0)されている場合は偶数を示します。
キャリーフラグの値に応じてWレジスタを0x00または0xffをセットします。
RCSTA1のRX9Dビットが受信のパリティーの値を示します。
WレジスタとRCSTA1とで排他的論理和(xor)をとりWレジスタに保存します。
排他的論理和は2つの値の同じビット位置の値が同じ場合は0、異なる場合は1が同一ビット位置にセットされます。
RCSTA1の受信のパリティーの値を示すRX9Dの位置でWレジスタのビット値を検査し1の場合はパリティーが一致しないのでRed Ledを点灯させます。
スタックから受信データをポップしてWレジスタにコピーしサブルーチンを終了します。
本サブルーチンは偶数パリティーと見なしてチェックをしております。奇数パリティーにしたい場合は、btfsc STATUS,Cをbtfss STATUS,Cに置き換えると奇数パリティーでない場合にRed Ledを点灯させることができます。

parity2c

PIC18のステーラスレジスターにはパリティーを示すフラグがありません。ちなみにZ80等には存在します。
Wレジスタの1のビット数を数え偶数の場合はCフラグを0、奇数の場合は1をセットします。
ビット数を数えるには1ビットずつシフト命令を使用してシフトさせキャリーフラグのチェックを8回か繰り返す方法が一番簡単かと思います。
ここでは、先に上位4bitと下位4bitの排他的論理和をとります。 その後はその結果と右シフトした結果とを排他的論理和をとります。 もう一度、結果と右シフトした結果とを排他的論理和をとると全ビットのパリティーが0ビット目に反映されます。さらに右シフトすると0ビット目がCフラグに反映されます。
計算過程については、PIC18の標準命令セットを参照願います。

ソースファイル

以下のファイルで構成されている
eusart4a.asm ・・・ メインプログラム

ソースファイルのダウンロード eusart4ap.zip

; EUSART1受信割り込みによるパリティ付き受信テスト(高位レベル割り込み使用)  2017/08/23 21:00 動作確認
; 慈渓博瑞テクノロジー株式会社 PIC18F46K22 マイコンキット Ver2013.12.08用
;   http://akizukidenshi.com/catalog/g/gK-07231/
;   水晶は16MHzに交換してPICを64MHzで駆動
;   19200bps
;   ストップビット 1bit
;   パリティ 偶数
;   ストップ 1bit
;   フロー制御 無
; MPLAB X IDE v3.45 Microchip MPASM(v5.70)
; PicKit 3

; RC6:TX1  RS232C
; RC7:RX1  RS232C
; RC2:Blue LED 1文字受信するたびにLEDの点灯状態が反転
; RE2:Red  LED パリティエラーが発生すると点灯(初期時は点灯 文字受信後動作)
        #INCLUDE <p18f46k22.inc>
        ; 水晶発振(16MHz) クロック分周無 PLL有効(*4) プライマリクロック有効  ウォッチドッグタイマ無効 低電圧プログラム書き込みモード無効
        CONFIG FOSC = HSHP,PLLCFG=ON,PRICLKEN=ON,WDTEN=OFF,LVP=OFF

STACK_MAX   EQU d'32'
 
bank1   IDATA 060h
stack1  RES     STACK_MAX ; スタックエリア      
        
        CODE
        ORG 0
        goto   start    ;   リセット時
        org 08h
        goto   inth     ;   高位レベル割り込み

start
        BANKSEL ANSELC
        lfsr    2,stack1+(STACK_MAX-1)  
;       USART初期化 300bps?115.2kbps (Xtal 16MHz PLL *4)
FOSC1   EQU     d'64000000' ;   クロック周波数 Hz
BPS1    EQU     d'19200'        ;   ボーレート設定
SPBRGW1    EQU  (FOSC1/(d'16'*BPS1)-1)
        bsf     BAUDCON1,BRG16  ;   BRH16=1
;       movlw   b'10010000' ; シリアル 8bit
        movlw   b'11010000' ;TX9=1:9bit
        movwf   RCSTA1
        movlw   LOW SPBRGW1
        movwf   SPBRG1
        movlw   HIGH SPBRGW1
        movwf   SPBRGH1
        
        movlw   b'00111111'
        movwf   ANSELC,BANKED
        movlw   b'11111011' ;   RC2をOUT
        movwf   TRISC
        movlw   b'00000000' ;   RC2=offを出力
        movwf   PORTC

        movlw   b'11111011'
        movwf   ANSELE,BANKED
        movlw   b'11111011' ;   RE2をOUT
        movwf   TRISE
        movlw   b'00000000' ;   RE2=offを出力
        movwf   PORTE   
        bsf     LATC,2
        bsf     LATE,2
        bsf     PIE1,RC1IE  ;   受信割り込み許可
        bsf     INTCON,PEIE
        bsf     INTCON,GIE  ;   高位レベル割り込み許可

        goto $

inth    ;   高位割り込み
        call    usart1p_read
        retfie  FAST

usart1p_read  ;   USART1から読み取り
        btfss   PIR1,RC1IF   ; 受信完了
        bra     usart1p_read
        btfsc   RCSTA1,FERR ; フレミングエラーがない場合次の命令をスキップ
        bra     usart1p_ferr
        btfsc   RCSTA1,OERR ; オーバーランエラーがない場合次の命令をスキップ
        bra     usart1p_oerr
        movf    RCREG1,W

        movwf   POSTDEC2
        btg     LATC,2
        call    parity2c    ; WREGのパリティチェック キャリーに反映
        clrf    WREG
        btfsc   STATUS,C    ; 偶数:btfsc   STATUS,C   奇数:btfss   STATUS,C
        comf    WREG
        xorwf   RCSTA1,WREG
        bcf     LATE,2  
        btfsc   WREG,RX9D
        bsf     LATE,2  ; パリティが一致しない場合実行(Red LED点灯)
        movf    PREINC2,w
        return
usart1p_ferr  ;   フレミングエラーが発生
usart1p_oerr  ;   オーバーフローエラーが発生
        return

;   パリティ計算をし結果をcに保存 偶数パリティ
;   WREG:引数
;   FSR2:スタック 最大1byte消費
parity2c
        movwf   POSTDEC2
        swapf   WREG
        xorwf   PREINC2,W
        movwf   POSTDEC2
        rrcf    WREG
        xorwf   PREINC2,W
        movwf   POSTDEC2
        rrcf    WREG
        rrcf    WREG
        xorwf   PREINC2,W
        rrcf    WREG
        return          
       
        END