概要
外部のPWMパルスの周期やDutyを計測したい場合、インプットキャプチャを使用すると簡単に計測できます。
パルスの立ち上がりや立下りを起点としてそのタイミングのカウンタ値を読み取る機能です。

ハードウェア構成と制御ブロック
今回はダミーとしてSCCP1をPWM出力させ、その信号を他のSCCPモジュールでインプットキャプチャ動作させます。通常のインプットキャプチャの動作ですと、(fig.1)のSCCP2の様にエッジイベントごとにフリーランタイマ値を取得することになります。この時に周期を得る為には、今回の値と前回の値の差分をCPUで演算する必要が発生します。またオーバーフロー処理(0xFFFFを跨いだ場合)は更に面倒です。
そこでSCCP3のインプットキャプチャイベントを同期出力トリガにしてSCCP3、SCCP4の同期入力に入力させます。(fig.2)

この様な設定にする事で、(fig.1)のSCCP3のように立ち上がりイベントでタイマがクリアされるので、周期やDuty(幅)を直接取得可能となります。ただしMicrochipのリファレンスマニュアルには以下のように、推奨される使い方ではない模様です。
規定値では、入力キャプチャモード中のMCCPモジュールは、フリーランニングタイマを使って動作します。入力キャプチャモードでは、CCPxPRH/Lレジスタを使ってタイマ周期を設定する事はできません。SYNC<4:0>を「11111」に固定する事で、タイマのフリーランニング動作を維持する事を推奨します
DS33035A_JP -p64-56より引用
ソースコード
今回のように自己のキャプチャトリガでタイマをクリアするために、重要なレジスタビットは以下の3点です。これ以外の設定ではキャプチャ動作はするものの、クリア動作はされない模様です。
CCP3CON1Hbits.SYNC = 4u; /* [重要]SCCP3に同期 */
CCP3CON1Hbits.ALTSYNC = 1u; /* [重要]代替同期出力有効 */
CCP3CON1Lbits.TMRPS = 0; /* [重要]プリスケーラ0以外では自己同期しない */
コンフィグレーション設定についてはコンフィグレーション設定に記載しております。
コピーして下記のソースコードの「 //ここにコンフィグレーション設定を挿入する// 」の位置に挿入してください。
クロック設定用関数 vds_Main_Init_Clock_Register(); のソースコードはクロック設定のページに記載しております。
コピーして下記のソースコードの「 //ここにクロック設定ソースをコピペする// 」の位置に挿入してください。
/*--------------------------------------------------------------------------------*/
/* @file SCCP_InputCapture.c */
/* @brief SCCPモジュールの使い方4 */
/* @details SCCP(CCPxCON1L,CCPxCON2H,CCPxPRL,CCPxRB) */
/* リマッパブルピン(RPOR) */
/*--------------------------------------------------------------------------------*/
/*--------------------------------------------------------------------------------*/
/* コンフィグレーション設定*/
/*--------------------------------------------------------------------------------*/
//ここにコンフィグレーション設定を挿入する//
/*--------------------------------------------------------------------------------*/
/* インクルードファイル*/
/*--------------------------------------------------------------------------------*/
#include <stdio.h>
#include <stdlib.h>
#include <xc.h>
/*--------------------------------------------------------------------------------*/
/* 変数定義*/
/*--------------------------------------------------------------------------------*/
unsigned int u2g_Cap2[256];
unsigned int u2g_Cap3[256];
unsigned int u2g_Cap4[256];
unsigned int u2g_CapCnt2;
unsigned int u2g_CapCnt3;
unsigned int u2g_CapCnt4;
/*--------------------------------------------------------------------------------*/
/* クロック設定 */
/*--------------------------------------------------------------------------------*/
//ここにクロック設定ソースを挿入する//
/*--------------------------------------------------------------------------------*/
/* Main関数 */
/*--------------------------------------------------------------------------------*/
int main(int argc, char** argv)
{
/*------------------------------------------------------------------------------*/
/* クロック初期化*/
/*------------------------------------------------------------------------------*/
vds_Main_Init_Clock_Register(); /* クロック初期化 */
/*----------------------------------------------------------------------------*/
/* リマッパブルピン初期化*/
/*----------------------------------------------------------------------------*/
RPOR18bits.RP69R = 15u; /* RGB LED RED [SCCP1] */
RPINR4bits.ICM2R = 69u; /* IC[SCCP2] */
RPINR5bits.ICM3R = 69u; /* IC[SCCP3] */
RPINR6bits.ICM4R = 69u; /* IC[SCCP4] */
/*---------------------------------------------------------------------------*/
/* CCP1初期化*/
/*---------------------------------------------------------------------------*/
CCP1CON1L = 0x0000u;
CCP1CON1Lbits.MOD = 4u; /* PWMモード*/
CCP1CON1Lbits.CCSEL = 0u; /* コンペアモード */
CCP1CON1H = 0x0000u;
CCP1CON1Hbits.SYNC = 0u; /* 同期無し */
CCP1CON2H = 0x0000u;
CCP1CON2Hbits.OCAEN = 1u; /* 出力イネーブル / ステアリング制御ビット*/
CCP1CON3H = 0x0000u;
CCP1CON3Hbits.POLACE = 1u; /* CCPx 出力ピン極性制御ビット */
CCP1PRL = 6250;
CCP1RB = 400u;
/*---------------------------------------------------------------------------*/
/* CCP2初期化*/
/*---------------------------------------------------------------------------*/
CCP2CON1L = 0x0000u;
CCP2CON1Lbits.MOD = 1u; /* 立ち上がり間 */
CCP2CON1Lbits.CCSEL = 1u; /* キャプチャモード*/
CCP2CON1H = 0x0000u;
CCP2CON1Hbits.SYNC = 0u; /* 同期無し */
CCP2CON2H = 0x0000u;
CCP2CON2Hbits.ICS = 0u; /* ICxPIN(PPS) */
CCP2CON3H = 0x0000u;
CCP2PRL = 0x0000u;
CCP2RA = 0x0000u;
CCP2RB = 0x0000u;
/*---------------------------------------------------------------------------*/
/* CCP3初期化*/
/*---------------------------------------------------------------------------*/
CCP3CON1L = 0x0000u;
CCP3CON1Lbits.MOD = 1u; /* 立ち上がり間 */
CCP3CON1Lbits.CCSEL = 1u; /* キャプチャモード */
CCP3CON1Lbits.TMRPS = 0; /* [重要]プリスケーラ0以外では自己同期しない */
CCP3CON1H = 0x0000u;
CCP3CON1Hbits.SYNC = 4u; /* [重要]SCCP3に同期 */
CCP3CON1Hbits.ALTSYNC = 1u; /* [重要]代替同期出力有効 */
CCP3CON2H = 0x0000u;
CCP3CON2Hbits.ICS = 0u; /* ICxPIN(PPS) */
CCP3CON3H = 0x0000u;
CCP3PRL = 0x0000u;
CCP3RA = 0x0000u;
CCP3RB = 0x0000u;
/*---------------------------------------------------------------------------*/
/* CCP4初期化*/
/*---------------------------------------------------------------------------*/
CCP4CON1L = 0x0000u;
CCP4CON1Lbits.MOD = 2u; /* 立下り間 */
CCP4CON1Lbits.CCSEL = 1u; /* キャプチャモード */
CCP4CON1Lbits.TMRPS = 0; /* [重要]プリスケーラ0以外では自己同期しない */
CCP4CON1H = 0x0000u;
CCP4CON1Hbits.SYNC = 4u; /* SCCP3に同期 */
CCP4CON1Hbits.ALTSYNC = 1u; /* [重要]代替同期出力有効 */
CCP4CON2H = 0x0000u;
CCP4CON2Hbits.ICS = 0u; /* ICxPIN(PPS) */
CCP4CON3H = 0x0000u;
CCP4PRL = 0x0000u;
CCP4RA = 0x0000u;
CCP4RB = 0x0000u;
/*---------------------------------------------------------------------------*/
/* CCP2,3,4の有効化*/
/*---------------------------------------------------------------------------*/
CCP4CON1Lbits.CCPON = 1u ;
CCP2CON1Lbits.CCPON = 1u ;
CCP3CON1Lbits.CCPON = 1u ;
CCP1CON1Lbits.CCPON = 1u ;
while(1)
{
if (CCP2STATLbits.ICBNE == 1u)
{
u2g_Cap2[u2g_CapCnt2 ++] = CCP2BUFL;
u2g_CapCnt2 &= 0xFF;
}
if (CCP3STATLbits.ICBNE == 1u)
{
u2g_Cap3[u2g_CapCnt3 ++] = CCP3BUFL;
u2g_CapCnt3 &= 0xFF;
}
if (CCP4STATLbits.ICBNE == 1u)
{
u2g_Cap4[u2g_CapCnt4 ++] = CCP4BUFL;
u2g_CapCnt4 &= 0xFF;
}
}
}
結果
各SCCPモジュールのICxBUF値です。
- u2g_Cap2[](SCCP2)はフリーランタイマの値
- u2g_Cap3[](SCCP3)は周期
- u2g_Cap4[](SCCP4)はDuty
の値が取得できています。

32bitでキャプチャする場合
32bitでキャプチャする場合は、TMR32をセットし
CCP3CON1Lbits.TMR32 = 1u;
読み込み時に下記のようにレジスタにアクセスすれば取得可能です。(u4g_Cap[*]はunsigned long)
if (CCP3STATLbits.ICBNE == 1u)
{
u4g_Cap3[u2g_CapCnt3 ++] = ((unsigned long)CCP3BUFH ) << 16u | CCP3BUFL;
u2g_CapCnt3 &= 0xFF;
}

コメント