こんにちは、ENGかぴです。
PIC16F1827はキャプチャー機能を持っているため外部機器からの取得したパルス信号の周波数を測定することができます。MPLAB X IDEのプラグインであるMCCでCCP(Capture)を実装して動作確認を行いました。
DOで50Hz(500Hz)の模擬パルス波形を生成しキャプチャーの動作確認を行います。PIC16F1827で動作確認したことについてリンクをまとめています。
PICマイコン(PIC16F1827)で実現できる機能と解説リンクまとめ
キャプチャー(Capture)機能
キャプチャー機能はパルスの立ち上り/立ち下りエッジを検出して次の立ち上り/立ち下りエッジまでの間隔(周波数)を測定する機能です。
PIC16F1827はCCPにキャプチャー機能が含まれており、TMR1と連動してキャプチャーの間隔(周波数)が測定できます。キャプチャー割り込みが発生するとTMR1のカウント値をCCPRに格納する仕様になっています。
立ち上がりエッジで検出する場合は、パルス波形がLOWからHIGHに変化した場合に割り込みを発生します。逆に立ち下がりエッジで検出する場合はパルス波形がHIGHからLOWに変化した場合に割り込みを発生します。
キャプチャーは周期的なパルス波形の周波数を測定する用途で使用されることが多い機能です。TMR1の分解能によって測定する周波数を調整することができます。
INTピン(外部割込み)とタイマを使って周波数を測定する方法については下記記事にまとめています。
MCCで各種機能を実装する
PIC16F1827の各種設定はMCCを使っています。MCCの使い方については下記記事にまとめています。
MPLAB Code Configurator(MCC)の追加と使い方
今回はキャプチャー機能にCCP3、TMR1、50Hz(500Hz)の模擬パルス波形の生成にTMR0の設定を行います。
System Moduleの設定
最初に共通事項であるSystem Moduleの設定を行います。MPLAB X IDEを起動しMCCのアイコンをクリックしてMCCを有効にします。
内部クロックを使用するためINTOSCを選択しています。TMR1の分解能を上げるためクロック周波数は16MHz_HFを選択しています。他にも設定項目はありますがクロックの設定のみとしています。
CCP3(Capture)及びTMR1の設定
キャプチャー機能はCCP3(CCP4)に含まれています。 Resources内のPeripherals欄のCCP3を選択して追加します。 またキャプチャーはTMR1と連動するためTMR1の設定を行います。
CCP ModeでCaptureを選択します。Capture Modeでキャプチャーするパルス波形のエッジを選択します。エッジを検出した場合に割り込みを発生させる場合はEnable CCP Interruptにチェックを入れます。
コールバック関数を指定すると割り込み発生時にユーザーの関数を呼び出すことができます。
void Capture_CallBack(uint16_t capturedValue); //CCP割り込みのコールバック関数
//コールバック関数の指定例
CCP3_SetCallBack(Capture_CallBack); //コールバック関数を指定
/* キャプチャー割り込み */
void Capture_CallBack(uint16_t capturedValue){
TMR1_WriteTimer(0); //TMR1のカウント値をクリア
capbuf.data[capbuf.wp] = capturedValue; //キャプチャー値の格納
}
CCP3_SetCallBack()関数はコールバックするユーザーの関数を指定します。例では自作のCapture_CallBack()関数を指定しています。MCCでキャプチャー時点のCCPR値(キャプチャー間隔のカウント数)が引数で渡されるため引数からCCPRの値を取得します。
Capture_CallBack()関数では次のエッジ検出に備えてTMR1のカウント値をクリアしています。次のエッジを検出までの時間の測定を開始します。
TMR1の設定でキャプチャーの分解能を設定します。分解能を細かくするほど周波数の測定の精度を上げることができますがキャプチャーできる間隔が短くなります。Timer Periodが1usになるようにClock Source及びPrescalerを設定しています。
TMR1はキャプチャーでカウントスタートするため初期値を0スタートにする必要があります。そのため初期値のPeriod countを0x00にしています。
キャプチャー割り込みが発生するとTMR1がスタートします。次のキャプチャー割り込みでTMR1の値がCCPRに格納されるためCCPRを確認することで周波数を測定することができます。
TMR0を設定する
TMR0はDevice Resources内のPeripherals欄のTimerを選択しTMR0をクリックして追加します。
Timer Clock内でクロックに関する設定を行います。Clock Sourceは内部クロックを使用しているためFOSC(FOSC/4)を指定します。PrescalerはClock Sourceに対してTMR0のカウントアップする分周比を指定します。
Timer PeriodはTMR0がオーバーフローするタイミングを設定します。1ms毎にオーバーフロー割り込みが発生します。
void mainTimer(void); //タイマー0割り込みのコールバック関数
//コールバック関数の指定例
TMR0_SetInterruptHandler(mainTimer); //コールバック関数を指定
TMR0_SetInterruptHandler()関数でコールバックするユーザーの関数を指定します。例ではmainTimer()が1ms毎にコールされます。
MCCが生成した関数の使用例
IO_RB3_SetLow(); //PORTBの3番(RA3)をLOW
IO_RB3_SetHigh(); //PORTBの3番(RA3)をHigh
IO_RB0_Toggle(); //PORTBの0番(RB0)の出力を反転
IO_RBX_SetLow()関数はRORTBのX番のポートをLOWにします。IO_RBX_SetHigh()関数はRORTBのX番のポートをHIGHにします。Xはポートの番号で0~7が入ります。
IO_RBX_Toggle()関数はRORTBのX番のポートの出力を反転します。Xはポートの番号で0~7が入ります。
ピンの設定
MCCのピン設定は以下の通りです。
PA3をキャプチャー(CCP3)で使用します。PB5はウィークプルアップ付きのINPUTで50Hz/500Hzの模擬パルス波形の切替に使用します。
ウィークプルアップ(WPU)を使用する場合はRegistersタブのnWPUENをenabledにする必要があります。
Easy SetupでWPUにチェックするのみでは有効にならないので注意が必要です。Notificationsにワーニングで通知されます。
動作確認
CCP3にRB0で生成した模擬パルス波形を入力してキャプチャー機能の動作確認を行います。RB5をGNDに接続しない場合は50Hzの模擬パルス波形を生成します。GNDに接続した場合は500Hzの模擬パルス波形を生成します。
50Hz相当の波形がキャプチャーできているとLED1を点灯して通知します。また500Hz相当の波形がキャプチャーできているとLED2を点灯して通知します。
PB0の模擬パルス波形をオシロスコープで確認し、PICkit4を使ったデバッグによるCCPR値を確認して周波数を測定します。
PB0の波形を確認すると50Hzの波形が生成できていることが確認できました。デバッグでCCP3でキャプチャーしたCCPR値の平均値(capbuf.avr)を確認すると20090になっています。TMR1は1カウント当たり1usになるため20.09msになります。オシロスコープの結果と一致してキャプチャーできていることが分かります。
同様に500Hzの模擬パルス波形についても確認します。
PB5をGNDに接続して波形を切り替えて測定を行います。PB0の波形を確認すると500Hzの波形が生成できていることが確認できました。デバッグでCCP3でキャプチャーしたCCPR値の平均値(capbuf.avr)を確認すると1981になっています。TMR1は1カウント当たり1usになるため1.98msになります。オシロスコープの結果と一致してキャプチャーできていることが分かります。
模擬パルス波形が50Hzの時はLED1、500Hzの時はLED2が点灯することが確認できました。
広告
マイベスト3年連続1位を獲得した実績を持つ実践型のプログラミングスクール
ソースコード全体
以下のソースコードはコンパイルして動作確認をしております。コメントなど細かな部分で間違っていたりやライブラリの更新などにより動作しなくなったりする可能性があります。参考としてお使いいただければと思います。
#include "mcc_generated_files/mcc.h"
#define PLS_MAX 10
#define PLS_MAX2 1
#define CAP_MAX 4
#define TIME_OFF -1
#define TIME_UP 0
typedef struct{
uint8_t wp;
uint16_t data[CAP_MAX];
uint16_t avr;
}CAP_FILT;
CAP_FILT capbuf;
int16_t timpls;
void Capture_CallBack(uint16_t capturedValue);
void mainTimer(void);
void mainApp(void);
/* Main application */
void main(void)
{
SYSTEM_Initialize();
INTERRUPT_GlobalInterruptEnable();
INTERRUPT_PeripheralInterruptEnable();
TMR0_SetInterruptHandler(mainTimer);
CCP3_SetCallBack(Capture_CallBack);
while (1)
{
mainApp();
}
}
/* メイン処理 */
void mainApp(void){
if( capbuf.avr > 19600 && capbuf.avr < 20400 ){
IO_RB3_SetHigh();
}
else{
IO_RB3_SetLow();
}
if( capbuf.avr > 1900 && capbuf.avr < 2100 ){
IO_RB4_SetHigh();
}
else{
IO_RB4_SetLow();
}
if( timpls == TIME_UP){
if(IO_RB5_GetValue()){
timpls = PLS_MAX;
}
else{
timpls = PLS_MAX2;
}
IO_RB0_Toggle();
}
}
/* キャプチャー割り込み */
void Capture_CallBack(uint16_t capturedValue){
uint8_t i;
uint32_t sum=0;
TMR1_WriteTimer(0);
capbuf.data[capbuf.wp] = capturedValue;
if( ++capbuf.wp >= CAP_MAX){
capbuf.wp = 0;
}
for(i=0; i < CAP_MAX; i++){
sum += capbuf.data[i];
}
capbuf.avr = (uint16_t)(sum / CAP_MAX);
}
/* TMR0割り込み */
void mainTimer(void){
if( timpls > TIME_UP ){
--timpls;
}
}
/* End of File */
本ソースコードはMPLAB X IDEにMCCのプラグインをインストールしていることが前提となります。MCCをインストールする方法は下記記事を参考にしてください。
MPLAB Code Configurator(MCC)の追加と使い方
関連リンク
PICマイコンを使ってマイコンのレジスタの設定やMPLAB X IDEのプラグインであるMCCを使用して動作確認したことについてまとめています。
PICマイコン(PIC12F675)で実現できる機能と解説リンクまとめ
PICマイコン(PIC16F1827)で実現できる機能と解説リンクまとめ
PR:スキマ時間を有効に!スマホで学べる人気のオンライン資格講座【スタディング】まずは気になる講座を無料で体験しよう!
最後まで、読んでいただきありがとうございました。