2002/10/25 【ソフトウエア編TOPに戻る】
前回はPIC16F873のタイマー1で単純な16ビットタイマーの動作をさせてみました。そこではタイマーレジスタTMR1がオーバーフローすることによって発生する割り込み処理を利用しましたが、今回はカウント値があらかじめ設定した値と一致したことによって割り込みを発生させるコンペアマッチ動作についてご説明します。残念ながら、今回もPIC16F84Aではできません。
314−1.CCPの概要
ミッドレンジのPICにはCCPという機能が付いています。CCPとは(キャプチャ/コンペア/PWM)の頭文字を取ったもので、そのまんまキャプチャとコンペアとPWMの機能を行うためのものです。
CCPでは、機能の設定を行うためのCCPCONレジスタと、動作に関する値を保持するためのCCPRレジスタがあります。PIC16F873にはCCPが2チャンネルあり、それぞれCCP1、CCP2と称します。また、CCPCONレジスタやCCPRレジスタもそれに対応してCCP1CON、CCP2CONやCCPR1、CCPR2と呼びます。
CCPはCCPCONの設定によって以下の動作を行います。
■キャプチャ動作
PICのCCP端子(RC2/CCP1など)で立ち上がりエッジや立下りエッジといった入力信号の変化(イベント)があると、その時点でのタイマーレジスタTMRの16ビットの値をCCPRレジスタに保持(キャプチャ)します。イベントとしては立ち上がりごと/立下りごと/立ち上がり4回ごと/立ち上がり16回ごとの各種から選択することができます。
この機能は外部からのパルス幅を計測する場合などに用い、センサーからの応答を取り込んだりする場合に有効です。
■コンペア動作
タイマーレジスタTMRのカウント値が、あらかじめ設定しておいたCCPRレジスタの値と一致したときにコンペアマッチ割り込みが発生します。コンペアマッチ発生時にはCCP端子を1出力にしたり0出力にしたりする/TMRをゼロクリアする/AD変換を開始する(CCP2のみ)などの動作を行わせることができます。
■PWM動作
言わずと知れたパルス幅変調の波形を出力します。PWM動作ではPR2レジスタとTMR2タイマーレジスタのカウント速度で周期が決定され、パルス幅はCCPR1LレジスタとCCP1CONレジスタの設定で決定されて、CCP1端子から波形が出力されます。
今回は、これらの中からコンペアマッチによる割り込み処理についてご紹介します。キャプチャ動作とPWM動作については別の機会にご紹介します。
315−2.タイマー1を使ったプログラムその2 tmr1tes2.asm
それでは、タイマー1でCCP機能を使ったコンペアマッチ割り込み処理のプログラム例をご紹介します。内容的には314.タイマー1で16ビットタイマーのページでご紹介しているプログラムをベースに、コンペアマッチ動作に置き換えていますので、そちらも参照して下さい。
このプログラムでは、タイマー1のプリスケーラを8、タイマーカウンタTMR1の初期値を0000Hに設定してカウント動作をさせ、CCPR1にセットした8000Hの値と一致したことでコンペアマッチ割り込みを発生させます。発生した割り込み処理内で、RBの8BITから2進バイナリカウントを出力させます。コンペアマッチ割り込みが発生するとスペシャルイベントトリガと呼ばれる機能によってTMR1カウンタが0000Hに自動的にリセットされ、再びカウント動作が再開されます。
TMR1のオーバーフロー割り込みであれば104.856mSごとのカウント動作になりますが、今回はオーバーフローする前で割り込みが掛かるため、8000Hから計算すると約52.4mSごとの速さでカウントされるはずです。
プログラムはPIC16F873 用のみでtmr1tes2asm(ダウンロード)です。
| ;********************************************************************** ;TMR1 TIMER TEST2 RIKIYA 2002.10.21 ;DEVICE : PIC16F873 ;CLOCK : 20MHz ;CCP1の割り込みを使った、TMR1インターバルタイマー動作 ;PORTBからカウントアップ出力を行なう ;CCP1に設定した値とコンペアマッチするとTMR1のカウントをクリアして ;割り込み処理を行う。 ;内蔵のTMR1カウンタだけで最長105mSのインターバルを発生する。 ;********************************************************************** list p=16F873 #include <p16F873.inc> __CONFIG _CP_OFF & _WDT_OFF & _PWRTE_ON & _HS_OSC & _LVP_OFF CNT1 EQU 20H ;アドレス20Hを変数CNT1とする。 ;********************************************************************** ORG 0 ;リセット時の開始アドレスセット GOTO MAIN ;メインルーチンMAINにジャンプ ORG 4 ;割り込みアドレスセット GOTO INTR ;割り込みルーチンINTRにジャンプ MAIN BSF STATUS ,RP0 ;メモリーバンクを1にセット MOVLW 080H ;Wレジスタに80Hをセット MOVWF OPTION_REG ;OPTION_REGに80Hをセット PULL UPなし BCF PIE1,TMR1IE ;TMR1オーバーフロー割り込み禁止 BSF PIE1,CCP1IE ;CCP1コンペアマッチ割り込み許可 CLRF TRISB ;TRISBをクリア PORT-Bを出力にセット BCF STATUS,RP0 ;メモリーバンクを0にセット MOVLW 30H ;Wレジスタに30Hをセット MOVWF T1CON ;T1CONレジスタ プリスケーラ1:8 停止 MOVLW 00H ;Wレジスタに00Hをセット MOVWF TMR1L ;TMR1Lに下位8ビットデータをセット MOVLW 00H ;Wレジスタに00Hをセット MOVWF TMR1H ;TMR1Hに上位8ビットデータをセット CLRF CNT1 ;CNT1変数を00Hにクリア MOVLW 0BH ;Wレジスタに0BHをセット MOVWF CCP1CON ;CCP1CONレジスタ コンペアスペシャルイベント MOVLW 00H ;Wレジスタに00Hをセット MOVWF CCPR1L ;CCPR1Lに下位8ビットデータをセット MOVLW 80H ;Wレジスタに80Hをセット MOVWF CCPR1H ;CCPR1Hに下位8ビットデータをセット BSF INTCON,PEIE ;周辺割り込みの許可 BSF INTCON,GIE ;全体割り込みの許可 BSF T1CON,TMR1ON ;TMR1のTMR1ONビットをセット カウント開始 ;*********************************************************************** ;割り込みを待つループ ;*********************************************************************** LOOP NOP ;何もしない GOTO LOOP ;ラベルLOOPにジャンプ ;*********************************************************************** ;割り込み処理 ;*********************************************************************** INTR BCF PIR1,CCP1IF ;コンペアマッチフラグのクリア BSF STATUS,RP0 ;メモリーバンクを1にセット BSF PIE1,CCP1IE ;コンペアマッチ割り込み許可 BCF STATUS,RP0 ;メモリーバンクを0にセット INCF CNT1,F ;変数CNT1に+1する。 MOVF CNT1,W ;WレジスタにCNT1の値をセット MOVWF PORTB ;PORTBへCNT1の値を出力 RETFIE ;割り込みを許可してリターン END |
以下のプログラム説明に出てくる各種レジスタについては、302.PICの命令とレジスタ一覧のページを参照して下さい。また、314.タイマー1で16ビットタイマーのページでご紹介したプログラムとの相違点だけを以下にご説明します。相違点は上のソースコード上で青字で表示しています。
■イニシャル部(ラベルMAIN)
BCF PIE1,TMR1IE ;TMR1オーバーフロー割り込み禁止
BSF PIE1,CCP1IE ;CCP1コンペアマッチ割り込み許可
両方の割り込み設定ビットは、PIE1レジスタにあります。ここではTMR1のオーバーフロー割り込みを禁止し、CCP1コンペアマッチ割り込みを使用可能としています。オーバーフロー割り込みはここでわざわざ禁止にすることもないのですが、禁止状態を強調する意味で記載しています。つまり、CCP1のコンペアマッチが検知されないと割り込みは発生しません。
MOVLW 0BH ;Wレジスタに0BHをセット
MOVWF CCP1CON ;CCP1CONレジスタ コンペアスペシャルイベント
ここではCCP1CONレジスタによってコンペアマッチ割り込みでスペシャルイベントトリガが発生する設定にしています。具体的にはソフトウエア割り込みを発生させてTMR1タイマーレジスタを0000Hにクリアする動作に設定しています。
CCP1CONレジスタには以下の意味があります。
★CCP1CON(CCP1コントロール)レジスタの機能
CCP1の動作を設定します。
| 7 | 6 | 5 | 4 | 3 | 2 | 1 | 0 |
| - | - | CCP1X | CCP1Y | CCP1M3 | CCP1M2 | CCP1M1 | CCP1M0 |
CCP1XとCCP1Yは、CCPでPWM動作を行う場合のパルス幅を決定するために利用します。
CCP1M3〜CCP1M0の4ビット分でCCPの動作を以下のように設定することができます。
| CCP1M3,2,1,0 | モード | 説 明 |
| 0000 |
CCPオフ |
CCP1モジュールをリセットする。 |
| 0100 | キャプチャ | 立下りエッジごと |
| 0101 | キャプチャ | 立上がりエッジごと |
| 0110 | キャプチャ | 立上がりエッジ4回ごと |
| 0111 | キャプチャ | 立上がりエッジ16回ごと |
| 1000 | コンペア | 一致時にCCP1端子出力を1にセット(CCP1IFビットをセット) |
| 1001 | コンペア | 一致時にCCP1端子出力を0にセット(CCP1IFビットをセット) |
| 1010 | コンペア | 一致時に割り込み発生。(CCP1IFをセット、CCP1端子変化なし) |
| 1011 | コンペア | スペシャルイベントトリガ TMR1をクリア、CCP1IFをセット |
| 11xx | PWM | PWMモード |
そして、以下の命令でCCPR1レジスタを8000Hに初期化しています。
MOVLW 00H ;Wレジスタに00Hをセット
MOVWF CCPR1L ;CCPR1Lに下位8ビットデータをセット
MOVLW 80H ;Wレジスタに80Hをセット
MOVWF CCPR1H ;CCPR1Hに下位8ビットデータをセット
つまり、TMR1タイマーカウンタが8000HになってCCPR1と一致するとコンペアマッチ状態になります。
■割り込み処理部
割り込み処理部では、CCPIF(CCP1割り込みフラグ)のクリアと、CCP1IE(CCP1割り込みイネーブル)のセットを行い、次の割り込み発生に備えます。
BCF PIR1,CCP1IF ;コンペアマッチフラグのクリア
BSF STATUS,RP0 ;メモリーバンクを1にセット
BSF
PIE1,CCP1IE ;コンペアマッチ割り込み許可
BCF STATUS,RP0 ;メモリーバンクを0にセット
なお、TMR1オーバーフロー割り込みを使っていた前回のプログラムでは、
MOVLW 00H ;Wレジスタに00Hをセット
MOVWF TMR1L ;TMR1Lに下位8ビットデータをセット
MOVLW 00H ;Wレジスタに00Hをセット
MOVWF TMR1H ;TMR1Hに上位8ビットデータをセット
という命令を実行していましたが、今回は不要です。インターバルの周期を決定するのはCCPR1にセットする値なので、TMR1は0000Hのままでもいいのです。もちろん、TMR1にセットする値を変えてもインターバルの周期に影響を与えることができます。
314−3.実験風景
![]() |
左の写真が実験風景です。といっても前回と同じ写真を使わせてもらっていますが... 動作的には思惑通り、前回の倍の早さでカウント動作を行ってくれました。CCPR1に書き込む値を変化させれば、それに追従してカウント動作の速度も変化します。 |
今回は、タイマー1でCCPのコンペアマッチのスペシャルイベントトリガ動作を行ってみました。
CCPではコンペマッチでCCP1出力端子の状態を変化させたりもできますし、この他にもキャプチャ動作やPWM動作、AD変換開始動作など様々な動作が可能なので、アイデア次第で面白い使い方が可能になると思います。それぞれのプログラム例については別の機会にご紹介していきたいと思います。