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