AD変換モジュールの使い方2(ADフィルター機能)

AD変換モジュールの使い方

概要

dsPIC33CHシリーズにはハードウェアでAD変換結果を平均化するADフィルター機能がマスターコアに4ch、スレーブコアに4ch搭載されております。

ADフィルターとは

アナログ変換結果をハードウェアで平均化する機能です。

前回の記事ではAD変換結果をソフトウェアにて平均化を行っていましたが、今回はハードウェアで自動で行います。このフィルタは2種類の変換モードが有り、以下の特徴を持ちます。

項目平均化モードオーバーサンプリングモード
レジスタ設定ADFLxCONbits.MODE = 1ADFLxCONbits.MODE = 0
出力分解能12bit12~16bit
平均化回数2,4,8,16,32,64,128,256
から選択
2,4,8,16,32,64,128,256
から選択
(Fig.1)フィルタモード

平均化の回数は ADFLxCONbits.OVRSAM で指定し、回数が多くなるほど結果が出力されるまでの時間も増加します。

(fig.2)共有ADCコアによる4倍オーバーサンプリング(DS70005213C_JP – p.50より抜粋)

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

前回の記事とハードウェアはほぼ同じですが、ADの変換トリガをSCCPで定期的に行う、もしくはレベルソフトトリガにて発生させます。

(fig.3)全体構成

レジスタ

前回の記事で紹介したレジスタに加え、ADフィルタを実現するADCモジュールのレジスタは以下の4種類です。

レジスタ名機能説明
ADTRIGnL
ADTRIGnH
ADC Channel Trigger n
Selection Register Low
ADC チャンネルトリガn 選択レジスタ
ADLVLTRGL
ADLVLTRGH
ADC Level-Sensitive Trigger
Control Register
ADC入力チャンネルをレベルセンシティブかエッジセンシティブにするかを設定
ADFLxCON
(x = 1~4)
ADC Digital Filter x
Control Register
ADフィルタ制御レジスタ
ADFLxDAT
(x = 1~4)
Oversampling Filter x
Output Register
フィルタ結果レジスタ
(fig.4)ADフィルタ関連レジスタ

ソースコード

AD変換開始の方法は下記の2種類のマクロを下記のように書き換えて下さい。

①ADの変換トリガをSCCPで定期的に行う。

#define TRG_MODE        TRG_MODE_SCCP2

② ADの変換トリガをソフトウェアで行う。

#define TRG_MODE        TRG_MODE_LVSOFT
コンフィグレーション設定について

コンフィグレーション設定についてはコンフィグレーション設定に記載しております。

コピーして下記のソースコードの「 //ここにコンフィグレーション設定を挿入する// 」の位置に挿入してください。

クロック設定について

クロック設定用関数 vds_Main_Init_Clock_Register(); のソースコードはクロック設定のページに記載しております。

コピーして下記のソースコードの「 //ここにクロック設定ソースをコピペする// 」の位置に挿入してください。

/*--------------------------------------------------------------------------------*/
/* @file      ADFIL_POTANTION.c */
/* @brief     ポテンションの値をハードで平均化、結果によってLEDの点灯・消灯 */
/* @details   GPIO(TRIS,LAT) */
/*            AD(ADCON1H,ADCON2L,ADCON2H,ADCON3L,ADCON3H,ADCON5H) */
/*            AD(ANSELA,ADSTATL,ADCBUF) */
/*--------------------------------------------------------------------------------*/
/*--------------------------------------------------------------------------------*/
/* コンフィグレーション設定*/
/*--------------------------------------------------------------------------------*/
//ここにコンフィグレーション設定を挿入する//
/*--------------------------------------------------------------------------------*/
/* インクルードファイル*/
/*--------------------------------------------------------------------------------*/
#include <stdio.h>
#include <stdlib.h>
#include <xc.h>
/*--------------------------------------------------------------------------------*/
/*【CONST】定数定義*/
/*--------------------------------------------------------------------------------*/
#define ADSIZE       8u

#define TRG_MODE_CMNSOFT 0x01
#define TRG_MODE_LVLSOFT 0x02
#define TRG_MODE_SCCP2   0x15

#define TRG_MODE        TRG_MODE_SCCP2
/*--------------------------------------------------------------------------------*/
/*【VARI】変数定義*/
/*--------------------------------------------------------------------------------*/
struct
{
    unsigned int u2_FilAve;
    unsigned int u2_Ave;
}Pot;

unsigned int u2_SamplingTime;
/*--------------------------------------------------------------------------------*/
/* クロック設定 */
/*--------------------------------------------------------------------------------*/
//ここにクロック設定ソースを挿入する//
/*--------------------------------------------------------------------------------*/
/* Main関数 */
/*--------------------------------------------------------------------------------*/
int main(int argc, char** argv) 
{
    /*----------------------------------------------------------------------------*/
    /* クロック初期化*/
    /*----------------------------------------------------------------------------*/
        vds_Main_Init_Clock_Register();     /* クロック初期化 */
    /*----------------------------------------------------------------------------*/
    /* GPIO初期化*/
    /*----------------------------------------------------------------------------*/
        TRISEbits.TRISE0 = 0u;              /* LED1ピンはデジタル出力ピン */
        ANSELAbits.ANSELA0 = 1u;            /* RA0ピンはアナログピン*/
    /*----------------------------------------------------------------------------*/
    /* AD初期化*/
    /*----------------------------------------------------------------------------*/
        ADCON1L = 0x0000u;
        ADCON1H = 0x0000u;
        ADCON2L = 0x0000u;
        ADCON2H = 0x0000u;
        ADCON3L = 0x0000u;
        ADCON3H = 0x0000u;
        ADCON5H = 0x0000u;
        ADTRIG0L = 0x0000u;
        ADTRIG5L = 0x0000u;
        
        /***** AD制御レジスタの設定 ******/
        ADCON1Hbits.SHRRES = 3u;        /* シェアADC分解能 (3 = 12bit) */
        ADCON2Lbits.SHRADCS = 2u;       /* シェアADCクロックディバイダ (2 = 4Clock) */
        ADCON2Hbits.SHRSAMC = 4u;       /* シェアADCサンプル時間 (3 = 4TAD) */
        ADCON3Lbits.CNVCHSEL = 0u;      /* ソフトウェアAD入力(0 =AN0入力) */
        ADCON3Hbits.CLKSEL = 2u;        /* ADCクロックソース (2 = AFVCODIV ) */
        ADCON3Hbits.CLKDIV = 2u;        /* ADCクロックディバイダ(2 = 3Clock)*/
        ADCON5Hbits.WARMTIME = 15u;     /* ウォームアップ時間(15 = 32768Clock) */

        /***** ADトリガ―の設定 ******/
        ADTRIG0Lbits.TRGSRC0 = TRG_MODE;
        ADTRIG5Lbits.TRGSRC20 = TRG_MODE;
        ADLVLTRGLbits.LVLEN0 = 0u;
        ADLVLTRGHbits.LVLEN20 = 0u;
        
        /***** ADFilter ******/
        ADFL0CONbits.FLCHSEL = 0u;          /* 入力チャンネル設定*/
        ADFL0CONbits.MODE = 0u;             /* フィルタモード */
        ADFL0CONbits.OVRSAM = 2u;           /* オーバーサンプリング比 */
        ADFL0CONbits.FLEN = 1u;             /* フィルタの有効化 */
        
        /***** ADの有効化 ******/
        ADCON1Lbits.ADON = 1u;              /* ADC全体のパワーON */
        ADCON5Lbits.SHRPWR = 1u;            /* シェアADCのパワーON */
        while(ADCON5Lbits.SHRRDY == 0u){;}
        ADCON3Hbits.SHREN = 1u;             /* シェアADCの有効化 */
        
    /*----------------------------------------------------------------------------*/
    /* SCCPでトリガ*/
    /* タイマーモードではADのトリガが発生しない*/
    /*----------------------------------------------------------------------------*/ 
#if (TRG_MODE == TRG_MODE_SCCP2)    
        CCP2CON1L = 0x0000u;
            CCP2CON1Lbits.CLKSEL = 0;       /* クロック源選択(0 = FP) */
            CCP2CON1Lbits.TMRPS = 1u;       /* クロックプリスケーラ選択(1 = 1:4) */
            CCP2CON1Lbits.CCSEL = 0u;       /* キャプチャモード選択*/
            CCP2CON1Lbits.MOD = 5u;         /* 動作モード(5 = PWMモード(必須)) */
            CCP2CON1Lbits.T32 = 0u;         /* 32ビットモード */
        
        CCP2CON1H = 0x0000u;
            CCP2CON1Hbits.TRIGEN = 0u;
            CCP2CON1Hbits.ALTSYNC = 0u;
            CCP2CON1Hbits.SYNC = 0u;
            CCP2CON2H = 0x0000u;
            CCP2CON2Hbits.AUXOUT = 0u;      /* イベント時補助出力信号選択ビット*/
        CCP2PRL = 22500;                /* 周期 */
        CCP2RAL = 0;                    /* 立ち上がりタイミング */
        CCP2RBL = 8000;                 /* 立ち下がりタイミング */
    /*----------------------------------------------------------------------------*/
    /* CCP2の有効化*/
    /*----------------------------------------------------------------------------*/
        CCP2CON1Lbits.CCPON = 1u;
#endif

#if (TRG_MODE == TRG_MODE_LVLSOFT)
        ADCON3Lbits.SWLCTRG = 0;
        ADCON3Lbits.SWLCTRG = 1;
#endif
    /*----------------------------------------------------------------------------*/
    /* メインルーチン*/
    /*----------------------------------------------------------------------------*/
        while(1)
        {
            if(ADFL0CONbits.RDY == 1)
            {
                Pot.u2_FilAve = ADFL0DAT;
                /*----------------------------------------------------------------*/
                /* LED点灯判定*/
                /*----------------------------------------------------------------*/  
                    if (Pot.u2_Ave > 2048u ){ PIN_MASTER_LED1 = 1u;}
                    else { PIN_MASTER_LED1 = 0u;}
                #if (TRG_MODE == TRG_MODE_LVLSOFT)
                    ADCON3Lbits.SWLCTRG = 0;
                    ADCON3Lbits.SWLCTRG = 1;
                #endif
            }
        }
}

コメント

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