8bitPICシリーズ③SMTモジュールの使い方

8BitPICシリーズ

概要

8BitPICシリーズには入力信号を計測するSMTモジュールが搭載されているマイコンがあります。
似たような機能を持つモジュールはインプットキャプチャがありますが、SMTはより高機能に信号を計測可能です。

今回は「PIC18F57Q43」のSMTモジュールを使用します。

SMTとは

SMTとはSignal Measurement Timerの略で信号を測定するモジュールの事。
外部信号の周期や幅、デューティー比やエッジ時間差などを11のモードによって計測します。

更新履歴

更公開/変更日更新内容
2022.08.16初版公開
2025.04.13タイトル修正、リンク追加、カテゴリ変更

関連リンク

記事リンク
第1回8bitPICシリーズ①
PRGモジュールの使い方
8bitPICシリーズ①PRGモジュールの使い方 – ぴくおの電子工作的な何かWP
第2回8bitPICシリーズ②
PWMモジュールの使い方
8bitPICシリーズ②PWMモジュールの使い方 – ぴくおの電子工作的な何かWP
第3回8bitPICシリーズ③
SMTモジュールの使い方
8bitPICシリーズ③SMTモジュールの使い方 – ぴくおの電子工作的な何かWP
第4回8bitPICシリーズ④
Timerモジュールの使い方
8bitPICシリーズ④Timerモジュールの使い方 – ぴくおの電子工作的な何かWP
第5回8bitPICシリーズ⑤
Angular Timer モジュールの使い方
8bitPICシリーズ⑤Angular Timer モジュールの使い方 – ぴくおの電子工作的な何かWP
第6回8bitPICシリーズ⑥
CLB(Configurable Logic Block)モジュールの使い方
8bitPICシリーズ⑥CLB(Configurable Logic Block)モジュールの使い方 – ぴくおの電子工作的な何かWP
第7回
第8回
第9回
第10回
内部リンク

ハードウェア構成と制御ブロック

SMTは下記のようにクロックソースをカウントするSMTxTMRとSMT_Window入力、SMT_Signal入力、コントロールロジックなどによって構成されます。

(fig.1)DS40002147F-page 423より抜粋 SMTブロックダイアグラム

タイマーモード

SMT_windowやSMT_signal入力は使用せず、SMTxENとSMTxGOがアクティブになった後にSMTxClockによりSMTxTMRがカウントアップしSMTxPRと一致した時に割り込み(SMTxIF)を発生させます。

(fig.2)DS40002147F-page 425より抜粋

ゲートタイマーモード

SMT_signalのHigh時間を測定します。

SMT_window入力は使用せずSMT_signal入力を使用します。SMT_signalがHighになった2クロックの立ち上がり信号でSMTx_signalsyncがアクティブになります。その1クロック後からSMTxClockによりSMTxTMRがカウントアップし、SMT_signalの立下りから3クロック後のSMTxTMR値がSMTxCPWにコピーされます。

(fig.3)DS40002147F-page 426より抜粋

周期&デューティ計測モード

SMT_signalの周期とDutyを測定します。

SMT_window入力は使用せずSMT_signal入力を使用します。SMT_signalがHighになった2クロックの立ち上がり信号でSMTx_signalsyncがアクティブになります。その1クロック後からSMTxClockによりSMTxTMRがカウントアップし、SMT_signalの立下りから3クロック後のSMTxTMRの値がSMTxCPWにコピーされます。また次のSMTx_signalsyncがアクティブになった時のSMTxTMR値をSMTxCPRにコピーされ、SMTxTMRの値は1にセットされます。

(fig.4)DS40002147F-page 427より抜粋

ハイ&ロー時間計測モード

SMT_signalのHigh時間Low時間を測定します。

SMT_window入力は使用せずSMT_signal入力を使用します。SMT_signalがHighになった2クロックの立ち上がり信号でSMTx_signalsyncがアクティブになります。その1クロック後からSMTxClockによりSMTxTMRがカウントアップし、SMT_signalの立下りから3クロック後のSMTxTMR値がSMTxCPWにコピーされ、SMTxTMRの値は1にセットされます。また次のSMTx_signalsyncがアクティブになった時のSMTxTMR値がSMTxCPRにコピーされ、SMTxTMRの値は再度1にセットされます。

(fig.5)DS40002147F-page 428より抜粋

ウィンドウ計測モード

SMT_windowの周期時間を測定します。

SMT_signal入力は使用せずSMT_window入力を使用します。SMT_windowがHighになった2クロックの立ち上がり信号でSMTx_WINsyncがアクティブになります。その1クロック後からSMTxClockによりSMTxTMRがカウントアップし、次のSMTx_syncがアクティブになった時のSMTxTMR値がSMTxCPRにコピーされ、SMTxTMRの値は再度1にセットされます。

(fig.6)DS40002147F-page 429より抜粋

ゲートウィンドウ計測モード

SMT_windowの周期期間中のSMT_signalのHigh時間を測定します。

SMT_signal入力とSMT_window入力を使用します。SMT_windowがHighになった2クロックの立ち上がり信号でSMTx_WINsyncがアクティブになります。その後SMT_signalがHighになった2クロックの立ち上がり信号でSMTx_signalsyncがアクティブになります。その1クロック後からSMTx_signalsyncがアクティブの期間SMTxClockによりSMTxTMRがカウントアップします。次のSSMTx_WINsyncがアクティブになった時のSMTxTMR値がSMTxCPRにコピーされ、SMTxTMRの値は再度0にセットされます。

(fig.7)DS40002147F-page 430より抜粋

タイムオブフライト計測モード

SMT_windowの立ち上がりからSMT_signalの立ち上がりの時間を計測します。

SMT_signal入力とSMT_window入力を使用します。SMTx_WINsyncがアクティブになった後にSMTxTMRの値が1にセットされます。またSMTxClockによりSMTxTMRがカウントアップし、SMTx_signalsyncがアクティブになった時の値がSMTxCPRにコピーされます。その後SMTx_WINsyncがアクティブになるまでのSMTx_signalsyncは無視されます。

SMTx_WINsyncがアクティブになった後にSMTx_signalsyncがアクティブにならなかった場合、SMTxTMRの値(=SMTx_WINsyncの周期値)がSMTxCPWにコピーされます。

(fig.8)DS40002147F-page 431より抜粋

キャプチャーモード

SMT_windowの立ち上がりとSMT_windowの立ち下がり時間をキャプチャします。

SMT_signal入力は使用せずSMT_window入力を使用します。SMTxGO_syncがアクティブになった後からSMTxClockによりSMTxTMRがカウントアップします。SMT_windowがHighになった2クロック後にSMTx_WINsyncがアクティブになり、その時のSMTxTMRの値がSMTxCPRにコピーされます。またSMTx_WINsyncがインアクティブになったタイミングSMTxTMRの値がSMTxCPWにコピーされます。

(fig.9)DS40002147F-page 432より抜粋

カウンターモード

SMT_windowの周期期間中のSMT_signalの立ち上がりエッジ数をカウントします。

SMT_signal入力とSMT_window入力を使用します。SMTxGOがアクティブになった後からSMT_signalの立ち上がりエッジによりSMTxTMRがカウントアップします。その後SMT_WINの立ち上がりエッジから2クロック後のSMTxTMRの値がSMTxCPWにコピーされます。

(fig.10)DS40002147F-page 433より抜粋

ゲートカウンターモード

SMT_windowがアクティブ期間中に入力されたのSMT_signalの立ち上がりエッジ数をカウントします。

SMT_signal入力とSMT_window入力を使用します。SMTxGOがアクティブになった後からSMT_windowがアクティブ期間中にSMT_signalの立ち上がりエッジが入力されるとSMTxTMRがカウントアップします。その後SMT_WINの立ち上がりエッジから2クロック後のSMTxTMRの値がSMTxCPWにコピーされます。

(fig.11)DS40002147F-page 433より抜粋

ウィンドウカウンターモード

SMT_windowがアクティブ期間中に入力されたのSMT_signalの立ち上がりエッジ数とSMT_windowの周期期間中のSMT_signalの立ち上がりエッジ数をカウントします。

SMT_signal入力とSMT_window入力を使用します。SMTxGOがアクティブになった後にSMT_windowの立ち上がりエッジでSMTxTMRの値がSMTxCPWにコピーされ、SMTxTMRの値が1にセットされます。その後SMT_signalの立ち上がりエッジが入力されるとSMTxTMRがカウントアップされ、SMT_WINの立下りによってSMTxTMRの値がSMTxCPRにコピーされます。

(fig.12)DS40002147F-page 434より抜粋

ハードウェア構成

SMTの動作確認としてPWM1のP1とP2出力の立ち上がり位相差をTOFモードで計測します。

(fig.13)SMT動作確認用ブロックダイアグラム

PWMの開始からP1は 0x27F – 0x140 のタイミングで立ち上がり、P2 は0x27F – 0x020 のタイミングで立ち上がります。つまり位相差は0x140 – 0x020 = 288となります。

(fig.14)SMT動作確認用PWM出力タイミング

ソースコード

ソースコードは以下の通りです。

#include "xc.h"

#pragma config FEXTOSC = ECH
#pragma config RSTOSC = EXTOSC 

//CONFIG2
#pragma config CLKOUTEN = OFF
#pragma config FCMEN = ON
#pragma config CSWEN = ON
#pragma config PR1WAY = ON 

//CONFIG3
#pragma config MVECEN = OFF 
#pragma config MCLRE = EXTMCLR
#pragma config BOREN = SBORDIS 
#pragma config PWRTS = PWRT_OFF 
#pragma config IVT1WAY = ON    
#pragma config LPBOREN = OFF    

//CONFIG4
#pragma config XINST = OFF  
#pragma config LVP = ON    
#pragma config ZCD = OFF    
#pragma config STVREN = ON    
#pragma config BORV = VBOR_1P9  
#pragma config PPS1WAY = ON     

//CONFIG5
#pragma config WDTCPS = WDTCPS_31   
#pragma config WDTE = OFF  

//CONFIG6
#pragma config WDTCWS = WDTCWS_7 
#pragma config WDTCCS = SC 

//CONFIG7
#pragma config SAFEN = OFF    
#pragma config BBEN = OFF     
#pragma config BBSIZE = BBSIZE_512     
#pragma config DEBUG = OFF     

//CONFIG8
#pragma config WRTB = OFF     
#pragma config WRTC = OFF     
#pragma config WRTD = OFF     
#pragma config WRTAPP = OFF    
#pragma config WRTSAF = OFF     

//CONFIG10
#pragma config CP = OFF  // Background Debugger->Background Debugger disabled

int main(void)
{
    volatile long Phase;
    /*----------------------------------------------------------------------------*/
    /* オシレータ設定 */
    /*----------------------------------------------------------------------------*/
        OSCCON1 = 0x60;
        OSCCON3 = 0x0;
        OSCEN = 0x0;
        OSCFRQ = 0x8;
        OSCTUNE = 0x0;
        ACTCON = 0x0;
    /*----------------------------------------------------------------------------*/
    /* ピン設定*/
    /*----------------------------------------------------------------------------*/
        TRISF = 0x3C;

        RF0PPS = 0x18;      //RF0->PWM1_16BIT:PWM11;
        RF1PPS = 0x19;      //RF1->PWM1_16BIT:PWM12;
    /*----------------------------------------------------------------------------*/
    /* SMT設定 */
    /*----------------------------------------------------------------------------*/
      SMT1CON0 = 0x80;
        SMT1CON1 = 0x46; 
            SMT1CON1bits.MODE = 6;
            SMT1CON1bits.REPEAT = 1;
        SMT1CLK = 0x1;     
        SMT1STAT = 0x0; 
        SMT1WIN = 0x12; 
        SMT1SIG = 0x11; 
        SMT1PRU = 0x0; 
        SMT1PRH = 0x0; 
        SMT1PRL = 0x0; 

    /*----------------------------------------------------------------------------*/
    /* PWM設定 */
    /*----------------------------------------------------------------------------*/
        PWM1ERS = 0x0;
        PWM1CLK = 0x2;      //CLOCK = FOC
        PWM1LDS = 0x0;
        PWM1PRL = 0x7F;     //周期下位8Bit
        PWM1PRH = 0x2;      //周期上位8Bit
        PWM1CPRE = 0x0;
        PWM1PIPOS = 0x0;
        PWM1GIR = 0x0;
        PWM1GIE = 0x0;
        PWM1S1CFG = 0x1;
        PWM1S1P1L = 0x40;   //P1下位8Bit
        PWM1S1P1H = 0x1;    //P1上位8Bit
        PWM1S1P2L = 0x20;   //P2下位8Bit
        PWM1S1P2H = 0x0;    //P2上位8Bit

        PIR4bits.PWM1PIF = 0;
        PIR4bits.PWM1IF = 0;
        PWM1GIRbits.S1P1IF = 0;
        PWM1GIRbits.S1P2IF = 0;
        PIE4bits.PWM1IE = 0;
        PIE4bits.PWM1PIE = 0;
        PWM1CON = 0x80;
    
        SMT1CON1bits.SMT1GO = 1u;
        

    while(1)
    {
        while(PIR1bits.SMT1PRAIF == 0){;}
        PIR1bits.SMT1PRAIF = 0;
        Phase= SMT1CPR;
        Nop();
    }    
}

結果

PIR1bits.SMT1PRAIFがセットされた後にSMT1CPRの値をPhaseにコピーし確認すると、想定通り288の値が取得できています。

コメント

タイトルとURLをコピーしました