割り込み処理って便利だ!

マイコンの割り込みの便利さに今更気付きました(;^ω^)なんだか面倒だし処理を途中で止めるのってなんか嫌だし・・・と今まで食わず嫌いしてましたw

今回はシリアル通信で信号を受信した時に割り込みがかかるというようなプログラムを作ってみました
プログラム中のポイントは、シリアル受信しか使わなくても送信用のTXSTAレジスタに通信関係のビットがあるからちゃんと設定すること、割り込みがかかったら必ず割り込み要因である受信フラグをクリアすること。

一番下にサンプルを載せてみました。


まずは必要な初期設定。バンク0では

   ;割り込みの許可を行う:INTCON
   ;bit7:割り込み全体の許可
   ;bit6:周辺機器からの割り込み許可
   ;その他のタイマやピン変化などの割り込みは許可しないため他は0
   movlw b'11000000'
   movwf INTCON

   ;シリアルの受信設定を行う:RCSTA
   ;bit7:シリアル通信自体の許可
   ;bit6:9ビット受信ではなく8ビット受信のため0
   ;bit5;非同期モードのため0/1どちらでも関係ない
   ;bit4:連続受信許可
   ;bit3:アドレス検出を許可しないため0
   ;bit2:ユーザーから書き込みはできないため適当に0を置いておく
   ;bit1:ユーザーから書き込みはできないため適当に0を置いておく
   ;bit0:ユーザーから書き込みはできないため適当に0を置いておく
   movlw b'10010000'
   movwf RCSTA

バンク1では

   ;周辺機器の割り込みの許可を行う:PIE1
   ;bit5:シリアル受信の割り込みを許可
   ;その他の周辺機器の割り込みは許可しない
   movlw b'00100000'
   movwf PIE1

   ;シリアルの送信設定を行う:TXSTA
   ;bit7:非同期モードのため0/1どちらでも関係ない
   ;bit6:9ビット受信ではなく8ビット受信のため0
   ;bit5:送信を使う場合は1。今回は使わないため0
   ;bit4:非同期モードを選択するため0
   ;bit3:使用されていないビットのため適当に0を置いておく
   ;bit2:ボーレートを高速モードに設定
   ;bit1:ユーザーから書き込みはできないため適当に0を置いておく
   ;bit0:通信で第9ビットは使わないため0
   movlw b'00000100'
   movwf TXSTA

   ;ボーレートの決定:SPBRG
   ;今回は9600bpsに設定。クロック20[Mhz]でシリアル通信の設定で高速モードを指定したためこのレジスタには129を入れておく。計算または表から求められる
   movlw d'129'
   movwf SPBRG

   ;シリアル受信用のポートを入力に指定
   clrf TRISB
   bsf TRISB,2

そして割り込みルーチン内では

   ;受信したデータが入るRCREGは読み出しに行くと自動的に受信フラグがクリアされる=割り込み要因が解除される
   movfw RCREG

割り込みを使うには各種レジスタの退避処理も必要ですが、それは全て予めテンプレートに書いてあるので省略。
※テンプレート:C:\Program Files\Microchip\MPASM Suite\Template\Code以下に全PIC用のテンプレートが用意してあります。
このテンプレートの

   MOVF    PCLATH,W          ; move pclath register into W register
   MOVWF   PCLATH_TEMP       ; save off contents of PCLATH register

   ;ここに割り込み処理を記述

   Restore context before returning from interrupt
   MOVF    PCLATH_TEMP,W     ; retrieve copy of PCLATH register

・使用PIC:PIC16F88
・20[Mhz]セラロック
・LEDはそれぞれPORTAの1と3に接続
・通常はPORTA,3のLEDが点滅
・シリアルで受信すると割り込みがかかってPORTA,1のLEDが点灯
・受信するごとにPORTA,1のLEDは付いたり消えたり
・実際に受信した値は使っていない。受信時に割り込みがかかってるか確認するためだけのプログラムです
・たぶんちょっくら変更するだけでUART積んでる他のPICでも動くかもしれません


※全角スペースを使っているためもしコピーするような場合はエディタ等で「全角スペース3つ」を「タブ1つ」に置き換えてください

     LIST      p=16F88       ; list directive to define processor
     #INCLUDE <P16F88.INC>   ; processor specific variable definitions

     __CONFIG    _CONFIG1, _CP_OFF & _CCP1_RB0 & _DEBUG_OFF & _WRT_PROTECT_OFF & _CPD_OFF & _LVP_OFF & _BODEN_OFF & _MCLR_OFF & _PWRTE_ON & _WDT_OFF & _HS_OSC
     __CONFIG    _CONFIG2, _IESO_OFF & _FCMEN_OFF

    CBLOCK 0x20 ; Sample GPR variable registers allocated contiguously
    MYVAR1  ; User variable
    MYVAR2  ; User variable
    MYVAR3  ; User variable
    ENDC

W_TEMP     EQU    0x7D  ; w register for context saving (ACCESS)
STATUS_TEMP    EQU    0x7E  ; status used for context saving (ACCESS)
PCLATH_TEMP    EQU    0x7F  ; variable used for context saving
CNT1 equ 0x20
CNT2 equ 0x21

DATAEE    ORG  0x2100
    DE    "MCHP"  ; Place 'M' 'C' 'H' 'P' at address 0,1,2,3

RESET     ORG     0x0000     ; processor reset vector
   PAGESEL START
   GOTO    START      ; go to beginning of program

ISR   ORG     0x0004     ; interrupt vector location

;     Context saving for ISR
   MOVWF   W_TEMP     ; save off current W register contents
   MOVF    STATUS,W   ; move status register into W register
   MOVWF   STATUS_TEMP   ; save off contents of STATUS register
   MOVF    PCLATH,W   ; move pclath register into W register
   MOVWF   PCLATH_TEMP   ; save off contents of PCLATH register

   movfw RCREG

intmain
   btfss PORTA,1
   goto on
   goto off

on
   bsf PORTA,1
   goto modoru

off bcf PORTA,1

modoru
;     Restore context before returning from interrupt
   MOVF    PCLATH_TEMP,W     ; retrieve copy of PCLATH register
   MOVWF   PCLATH     ; restore pre-isr PCLATH register contents
   MOVF    STATUS_TEMP,W     ; retrieve copy of STATUS register
   MOVWF   STATUS     ; restore pre-isr STATUS register contents
   SWAPF   W_TEMP,F
   SWAPF   W_TEMP,W   ; restore pre-isr W register contents
   RETFIE      ; return from interrupt

;以下初期化処理
START
   ;bank0
   bcf   STATUS,RP0
   bcf   STATUS,RP1

   movlw b'11000000'
   movwf INTCON
   movlw b'10010000'
   movwf RCSTA

   ;bank1
   bsf   STATUS,RP0
   bcf   STATUS,RP1

   movlw b'00100000'
   movwf PIE1

   movlw b'00000100'
   movwf TXSTA
   movlw d'129'
   movwf SPBRG
   clrf TRISA
   clrf TRISB
   bsf TRISB,2
   clrf ANSEL

   ;bank0
   bcf   STATUS,RP0
   bcf   STATUS,RP1

   clrf PORTA
   clrf PORTB

main_loop
   bsf PORTA,3
   call delay
   bcf PORTA,3
   call delay
   goto main_loop

delay
   movlw   0xfa
   movwf   delay1
delay1   ;1mS
   movlw   0xf0
   movwf   delay2
delay2
   nop
   nop
   decfsz   delay2,f
   goto delay2
   decfsz   delay1,f
   goto delay1
   return

    END