18F26J50には、ECCP (Enhanced Capture/Compare/PWM)が2セット組み込まれています。なお、2つのECCPは同じ構造をしているため、両方に該当する場合はECCPxと表記しています。関連レジスターも同様に「x」には、1または2の番号が入ります。ECCPのCompareモードは、タイマー1またはタイマー3を常時モニターしています。どちらのタイマーを使用するかは、表に示すように TCLKCON、<1:0>で指定します。タイマーがCCPRxH / CCPRxLで定められたカウントに達すると、以下の5種類のいずれかの動作を行います。
ECCPのCompareモードは、タイマー1またはタイマー3を常時モニターしています。どちらのタイマーを使用するかは、表に示すように TCLKCON、<1:0>で指定します。タイマーがCCPRxH / CCPRxLで定められたカウントに達すると、以下の5種類のいずれかの動作を行います。
| TCLKCON < T3CCP2:T3CCP1 > | |||
|---|---|---|---|
| 1:0 | 0:1 | 0:0 | |
| ECCP1 | Timer3 | Timer1 | Timer3 |
| ECCP2 | Timer3 | Timer3 | Timer1 |
Special Eventを利用すると連携するタイマーカウンターを16ビットまでの任意の分周カウンターにすることができます。なお、CCP1(RC5)をCCPの出力に使用する場合には、TRISCのビットを"0"出力に設定する必要があります。 この機能を活用することで、精度の高いクロックを分周し時計や、周波数カウンターの基準時間を定期的に発生させることが可能です。注意点として、Special Event が発生しタイマーをゼロにリセットするので、CCPR1H / CCPR1Lにプリセットする値は(必要分周数ー1)となります。
*注意*
出力ピンのCCPxはPeripheral Pin Select (PPS)機能で任意のRPnピンに指定することができます。CCPx出力に使用する場合には、該当のTRISCのビットを"0"出力に設定し、ANCONxビットも”1”デジタルにする必要があります
関連するレジスター一覧を下表に示します。
| レジスタ | bit7 | bit6 | bit5 | bit4 | bit3 | bit2 | bit1 | bit0 |
|---|---|---|---|---|---|---|---|---|
| RCON | IPEN | — | CM | RI | TO | PD | POR | BOR |
| INTCON | GIEH | GIEL | TMR0IE | INT0IE | RBIE | TMR0IF | INT0IF | RBIF |
| PIR1 | — | ADIF | RC1IF | TX1IF | SSP1IF | CCP1IF | TMR2IF | TMR1IF |
| PIE1 | — | ADIE | RC1IE | TX1IE | SSP1IE | CCP1IE | TMR2IE | TMR1IE |
| IPR1 | — | ADIP | RC1IP | TX1IP | SSPIP | CCP1IP | TMR2IP | TMR1IP |
| PIR2 | OSCFIF | CM2IF | CM1IF | USBIF | BCL1IF | HLVDIF | TMR3IF | CCP2IF |
| PIE2 | OSCFIE | CM2IE | CM1IE | USBIE | BCL1IE | HLVDIE | TMR3IE | CCP2IE |
| IPR2 | OSCFIP | CM2IP | CM1IP | USBIP | BCL1IP | HLVDIP | TMR3IP | CCP2IP |
| CCPxCON | PxM < 1 - 0 > | DCxB < 1 - 0 > | CCPxM < 3 - 0 > | |||||
| TCLKCON | T1RUN | T3CCP2 | T3CCP1 | |||||
| ODCON1 | — | — | — | — | — | — | ECCP2OD | ECCP1OD |
| CCPRxL | CCP Register x, Low Byte | |||||||
| CCPRxH | CCP Register x, High Byte | |||||||
| レジスタ | BIT | 名 | 説明 | 1 | 0 |
|---|---|---|---|---|---|
| RCON | 7 | IPEN | 2レベルのインタラプト優先度 | 使用 | 不 |
| INTCON | 7 | GIEH | 高優先度インタラプトを使用許可 | 許可 | 不 |
| 6 | GIEL | 低優先度インタラプトを使用許可 | 許可 | 不 | |
| PIR1 | 1 | CCP1IF | CCP1 発生フラグ | 発生 | |
| PIE1 | 1 | CCP1IE | CCP1 インタラプトを使用許可 | 許可 | 不 |
| IPR1 | 1 | CCP1IP | CCP1 インタラプト優先度 | 高 | 低 |
| PIR2 | 0 | CCP2IF | CCP2 発生フラグ | 発生 | |
| PIE2 | 0 | CCP2IE | CCP2 インタラプトを使用許可 | 許可 | 不 |
| IPR2 | 0 | CCP2IP | CCP2 インタラプト優先度 | 高 | 低 |
| CCPxCON | 3 | CCPxM3 | 0000 =モジュール全体をOFF (初期値) 0010 =CCPxをトグル, 1000 =CCPxLOW, 1001 =CCPxをLOW 1010 =CCPxは変化せず、CCPxIFセット 1011 =Special Event を発生 |
||
| 2 | CCPxM2 | ||||
| 1 | CCPxM1 | ||||
| 0 | CCPxM0 | ||||
| TCLKCON | 1 | T3CCP2 | 10 =CCP1,CCP2 両方ともタイマー3を使用する 01 =CCP1はタイマー1、CCP2はタイマー3を使用する 00 =CCP1はタイマー3、CCP2はタイマー1を使用する(初期値) |
||
| 0 | T3CCP1 | ||||
| ODCON1 | 1 | ECCP2OD | CCP1出力のオープンドレイン機能 | 有効 | 無効 |
| 0 | ECCP1OD | CCP2出力のオープンドレイン機能 | 有効 | 無効 | |
タイマー1でシステムクロックをカウントし、CCPRxH / CCPRxLで定められたカウントに達すると、Special Eventを発生させるプログラムを作成しました。Special Eventの発生でタイマー1をリセットし同時にンタラプトを発生させ出力を反転(LEDを点滅)させています。比較する値を可変するためにVRの値をAD変換し、CCPRxH にセットしています。
<回路図>
<プログラム>
// File name: CCP Comp
// Description:
// VRの値で出力する周波数が変化する 約 240Hz-1Hz
// Timer1で内部クロックをカウントし、CCP1で比較する
// AN0のAD変換値と一致で割込みが発生する
// 高優先割込み処理ルーチンで、LED0を反転し点滅させる。
// Timer3で内部クロックをカウントし、CCP2で比較する
// AN1のAD変換値と一致で割込みが発生する
// 低優先割込み処理ルーチンで、LED2を反転し点滅させる。
// Notes: 4MHz内部クロック
// LED0 RB0 LED2 RB2
// LED1 RB1 LED3 RB3
// Pot0 AN0(RA0)
// Pot1 AN1(RA1)
// Language: MPLAB xc8
// Target: PIC18F26J50
#include <xc.h>
#define _XTAL_FREQ 4000000 // delay_ms(x) のための定義
#define LED0 LATBbits.LATB0
#define LED1 LATBbits.LATB1
#define LED2 LATBbits.LATB2
#define LED3 LATBbits.LATB3
//
#pragma config WDTEN = OFF, PLLDIV = 2, STVREN = ON, XINST = OFF
#pragma config CPUDIV = OSC1, CP0 = OFF
#pragma config OSC = INTOSC, T1DIG = OFF
#pragma config LPT1OSC = OFF, FCMEN = OFF, IESO = OFF
#pragma config WDTPS = 32768
#pragma config DSWDTOSC = INTOSCREF, RTCOSC = T1OSCREF
#pragma config DSBOREN = OFF, DSWDTEN = OFF, DSWDTPS = 8192
#pragma config IOL1WAY = OFF, MSSP7B_EN = MSK7
#pragma config WPFP = PAGE_1, WPEND = PAGE_0, WPCFG = OFF
#pragma config WPDIS = OFF
//----------------------高優先割込み------------------------
void interrupt Hi_Isr(void){
if(PIR1bits.CCP1IF){ // CCP1からの割込みを確認
PIR1bits.CCP1IF = 0; // 割込みフラッグをクリア
LED0 = !LED0; // LED0を反転
LED1 = !LED0; // LED1を反転
}
}
//-----------------低優先割込みの処理------------------------
void interrupt low_priority Lo_Isr(void){
if(PIR2bits.CCP2IF){ //CCP2からの割込みを確認
PIR2bits.CCP2IF = 0; // 割込みフラッグをクリア
LED2 = !LED2; // LED2を反転
LED3 = !LED2; // LED3を反転
}
}
//----------------------メインプログラム-------------------------
void main(void){
OSCCON = 0b01100010; // 内部クロック4Mhz
LATB = 0; // PortCのすべてのビットを「0」
TRISB = 0b11110000; // LEDのポートを出力に設定
// ---------------- CCPの使用するタイマーを設定 ---------------
TCLKCON = 0x01; // CCP1はT1と、CCP2はT3と連携
// ---------------- CCP1の 設定 ------------------------
CCP1CON = 0b00001011; // スペシャルイベント
CCPR1H = 0x0F; // 繰返し周期の暫定設定
CCPR1L = 0xFF; //
IPR1bits.CCP1IP = 1; // 高優先割り込み
PIE1bits.CCP1IE = 1; // 割り込みを使用する。
PIR1bits.CCP1IF = 0;
T1CON = 0b00110001; // T1は Fosc/4をPSで1/8してカウント
// ---------------- CCP2の 設定 ------------------------
CCP2CON = 0b00001011; // スペシャルイベント
CCPR2H = 0xFF; // 繰返し周期の暫定設定
CCPR2L = 0xFF; //
IPR2bits.CCP2IP = 0; // 低優先割り込み
PIE2bits.CCP2IE = 1; // 割り込みを使用する。
PIR2bits.CCP2IF = 0;
T3CON = 0b00110001; // T3は Fosc/4をPSで1/8してカウント
// ---------------- ADC初期化 ------------------------
ADCON1 = 0b00101100; // 左詰 クロックFosc/4 12_TAD
ADCON0 = 0b00000001; // Vdd-Vss AN0(RA0) ADC_ON
ANCON0 = 0b00011100; // CH0,1をアナログ入力にする
ANCON1 = 0b00011111;
// ---------------- 割込みの有効化 ------------------------
RCONbits.IPEN=1; // 2段階の割込みに設定
INTCONbits.GIEH=1; // 高優先割込みを許可
INTCONbits.GIEL=1; // 低優先割込みを許可
while(1){
ADCON0 = 0b00000001; // AN0に接続
ADCON0bits.GO = 1; // AD変換開始
while(ADCON0bits.GO); // AD変換終了待ち
CCPR1H = ADRESH; // AD変換結果をCCP1繰返周期に
ADCON0 = 0b00000101; // AN1に接続
ADCON0bits.GO = 1; // AD変換開始
while(ADCON0bits.GO); // AD変換終了待ち
CCPR2H = ADRESH; // AD変換結果をCC2P繰返周期に
__delay_ms(100); // 更新間隔
}
}