概要
dsPIC33CHシリーズにはハードウェアでAD変換結果を平均化するADフィルター機能がマスターコアに4ch、スレーブコアに4ch搭載されております。
ADフィルターとは
アナログ変換結果をハードウェアで平均化する機能です。
前回の記事ではAD変換結果をソフトウェアにて平均化を行っていましたが、今回はハードウェアで自動で行います。このフィルタは2種類の変換モードが有り、以下の特徴を持ちます。
| 項目 | 平均化モード | オーバーサンプリングモード |
| レジスタ設定 | ADFLxCONbits.MODE = 1 | ADFLxCONbits.MODE = 0 |
| 出力分解能 | 12bit | 12~16bit |
| 平均化回数 | 2,4,8,16,32,64,128,256 から選択 | 2,4,8,16,32,64,128,256 から選択 |
平均化の回数は ADFLxCONbits.OVRSAM で指定し、回数が多くなるほど結果が出力されるまでの時間も増加します。

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

レジスタ
前回の記事で紹介したレジスタに加え、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 | フィルタ結果レジスタ |
ソースコード
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
}
}
}


コメント