概要
以前の記事でDMAを用い任意にアナログ波形が出力可能となったので、今回はその出力した電圧を別のDMAを用いCPU負荷ゼロでAD変換を行います。
ハードウェア構成と制御ブロック
周辺モジュールと全体構成は以下の通り
- SCCP2とDMA0、DAC1Hを使用しDACOUTピン(41pin)から波形出力
- SCCP3、DMA2を用い、DACOUTピンからAD変換

DMA関連のレジスタは以下の8種類
ソースコード
今回は特筆する事は有りません。
コンフィグレーション設定について
コンフィグレーション設定についてはコンフィグレーション設定に記載しております。
コピーして下記のソースコードの「 //ここにコンフィグレーション設定を挿入する// 」の位置に挿入してください。
クロック設定について
クロック設定用関数 vds_Main_Init_Clock_Register(); のソースコードはクロック設定のページに記載しております。
コピーして下記のソースコードの「 //ここにクロック設定ソースをコピペする// 」の位置に挿入してください。
/*------------------------------------------------------------------------------*/
/* @file DAC_DMA_AD.c */
/* @brief DACOUTから任意信号を出力しDMAでAD変換をする */
/*------------------------------------------------------------------------------*/
/*------------------------------------------------------------------------------*/
/* コンフィグレーション設定*/
/*------------------------------------------------------------------------------*/
//ここにコンフィグレーション設定を挿入する//
/*------------------------------------------------------------------------------*/
/* インクルードファイル*/
/*------------------------------------------------------------------------------*/
#include <stdio.h>
#include <stdlib.h>
#include <xc.h>
/*------------------------------------------------------------------------------*/
/* 定数定義*/
/*------------------------------------------------------------------------------*/
/*------------------------------------------------------------------------------*/
/*変数定義*/
/*------------------------------------------------------------------------------*/
/*波形ROM ([嵌り事]constを付けると上手く行かない)*/
unsigned int cu2l_Data[] =
{
2047 ,2212 ,2376 ,2538 ,2696 ,
2849 ,2997 ,3136 ,3268 ,3390 ,
3502 ,3603 ,3692 ,3768 ,3832 ,
3882 ,3918 ,3939 ,3947 ,3939 ,
3918 ,3882 ,3832 ,3768 ,3692 ,
3603 ,3502 ,3390 ,3268 ,3136 ,
2997 ,2849 ,2696 ,2538 ,2376 ,
2212 ,2047 ,1881 ,1717 ,1555 ,
1397 ,1244 ,1097 ,957 ,825 ,
703 ,591 ,490 ,401 ,325 ,
261 ,211 ,175 ,154 ,147 ,
154 ,175 ,211 ,261 ,325 ,
401 ,490 ,591 ,703 ,825 ,
957 ,1097 ,1244 ,1397 ,1555 ,
1717 ,1881
};
unsigned int u2g_ADCData[24];
/*------------------------------------------------------------------------------*/
/* クロック設定 */
/*------------------------------------------------------------------------------*/
//ここにクロック設定ソースを挿入する//
/*------------------------------------------------------------------------------*/
/* Main関数 */
/*------------------------------------------------------------------------------*/
int main(int argc, char** argv)
{
/*-------------------------------------------------------------------------*/
/* クロック初期化*/
/*-------------------------------------------------------------------------*/
vds_Main_Init_Clock_Register(); /* クロック初期化 */
/*-------------------------------------------------------------------------*/
/* GPIO初期化*/
/*-------------------------------------------------------------------------*/
TRISEbits.TRISE0 = 0u; /* LED1 */
ANSELAbits.ANSELA0 = 1u; /* RA0ピンはアナログピン*/
ANSELBbits.ANSELB2 = 1u; /* RB2ピンはアナログピン(DACOUT1) */
RPOR19bits.RP71R = 0x17u; /* RGB LED GREEN[OCM4] */
/*-------------------------------------------------------------------------*/
/* CMP初期化*/
/*-------------------------------------------------------------------------*/
DACCTRL1L = 0x0000u;
DACCTRL1Lbits.CLKSEL = 0u; /* DACクロック源( 0 = AFVCO/2 = 500MHz) */
DACCTRL1Lbits.CLKDIV = 0u; /* DACクロックディバイダ (0 = 1/1) */
DACCTRL1Lbits.FCLKDIV = 7u; /* コンパレータフィルタクロックディバイダ*/
DACCTRL1Lbits.DACON = 1u; /* モジュール有効化(0 = 無効,1 = 有効) */
DACCTRL2H = 0x001Au; /* 移行開始からの時間 */
DACCTRL2L = 0x0055u; /* 遷移モードの継続時間 */
DAC1CONH = 0x0000u;
DAC1CONL = 0x0000u;
DAC1CONLbits.INSEL = 0u; /* コンパレータ入力ソース */
DAC1CONLbits.HYSSEL = 1u; /* コンパレータヒステリシス (1 = 15mV) */
DAC1CONLbits.DACOEN = 1u; /* DAC外部出力 (0 = 無効,1 = 有効) */
DAC1DATH = 0x0000u; /* コンパレータ比較値上限 */
DAC1DATL = 0x0000u; /* コンパレータ比較値下限 */
/*-------------------------------------------------------------------------*/
/* DAC1の有効化*/
/*-------------------------------------------------------------------------*/
DAC1CONLbits.DACEN = 1u; /* DAC1の有効化 */
/*-------------------------------------------------------------------------*/
/* SCCP2初期化(DAC出力)*/
/* [嵌り事]TimerモードではDAC出力タイミングの周期はPRHで設定*/
/* [嵌り事]OCモードではDAC出力タイミングの周期はPRL,RAL!=RABで設定*/
/*-------------------------------------------------------------------------*/
CCP2CON1L = 0x0000u;
CCP2CON1H = 0x0000u;
CCP2CON2H = 0x0000u;
CCP2CON2Hbits.AUXOUT = 1u; /* イベント時補助出力信号選択ビット*/
CCP2PRL = 240u; /* 周期(PWMモード) */
CCP2PRH = 240u; /* 周期(タイマーモード) */
CCP2RAL = 130u; /* 立ち上がりタイミング(PWMモード) */
CCP2RBL = 0u; /* 立ち下がりタイミング(PWMモード) */
CCP2CON1Lbits.CCPON = 1u;
/*-------------------------------------------------------------------------*/
/* SCCP3初期化(ADトリガ間隔)*/
/*-------------------------------------------------------------------------*/
CCP3CON1L = 0x0000u;
CCP3CON1Lbits.CLKSEL = 0; /* クロック源選択(0 = FP) */
CCP3CON1Lbits.TMRPS = 0u; /* クロックプリスケーラ選択(0 = 1:1) */
CCP3CON1Lbits.CCSEL = 0u; /* Capモード選択(0 = OC,Timerモード) */
CCP3CON1Lbits.MOD = 5u; /* 動作モード(5 = PWMモード(必須)) */
CCP3CON1Lbits.T32 = 0u; /* 32ビットモード(0 = 16bit / 1 = 32Bit) */
CCP3CON1H = 0x0000u;
// CCP2PRL > CCP2RAL > CCP2RBL ...トリガ可能
// CCP2PRL > CCP2RBL > CCP2RAL ...トリガ可能
// CCP2PRL > CCP2RAL = CCP2RBL ...トリガ不可
CCP3PRL = 1000; /* 周期 */
CCP3RAL = 0; /* 立ち上がりタイミング */
CCP3RBL = 100; /* 立ち下がりタイミング */
/*-------------------------------------------------------------------------*/
/* DMA1初期化 */
/*-------------------------------------------------------------------------*/
DMAH = 0xC000u; /* DMA転送最大アドレス */
DMAL = 0x080u; /* DMA転送最小アドレス */
DMACON = 0x0000u;
DMACONbits.DMAEN = 1u; /* DMAモジュール有効化 */
DMACONbits.PRSSEL = 1u; /* ラウンドロビン方式 */
DMACH0 = 0x0000u;
DMACH0bits.SAMODE = 1u; /* 送信元アドレスをインクリメントする */
DMACH0bits.DAMODE = 0u; /* 受信元アドレスは固定 */
DMACH0bits.TRMODE = 1u; /* 繰り返し、ワンショットモード */
DMACH0bits.RELOAD = 1u; /* 自動でリロードする */
DMACH0bits.SIZE = 0u; /* 16bit転送モード */
DMAINT0 = 0x0000u;
DMAINT0bits.CHSEL = 0x0C; /* トリガイベント = SCCP2 */
DMASRC0 = (unsigned int)&cu2l_Data; /* 送信元データは cu2l_Data[] */
DMADST0 = (unsigned int)&DAC1DATH; /* 送信先はDAC1DATHレジスタ */
DMACNT0 = 71u; /* 送信カウントは72(71 + 1)回 */
/*-------------------------------------------------------------------------*/
/* DMA2初期化 */
/*-------------------------------------------------------------------------*/
DMACH2 = 0x0000u;
DMACH2bits.SAMODE = 0u; /* 送信元アドレスは固定 */
DMACH2bits.DAMODE = 1u; /* 受信元アドレスをインクリメントする */
DMACH2bits.TRMODE = 1u; /* 繰り返し、ワンショットモード */
DMACH2bits.RELOAD = 1u; /* 自動でリロードする */
DMACH2bits.SIZE = 0u; /* 16bit転送モード */
DMAINT2 = 0x0000u;
DMAINT2bits.CHSEL = 0x2F; /* トリガイベント = ADCdone AN7 */
DMASRC2 = (unsigned int)&ADCBUF7; /* 送信元データは cu2l_Data[] */
DMADST2 = (unsigned short int)&u2g_ADCData; /* 送信先はDAC1DATHレジスタ */
DMACNT2 = 18u; /* 送信カウントは18(17 + 1)回 */
DMACH0bits.CHEN = 1u; /* DMA0チャンネルを有効にする */
IFS0bits.DMA0IF = 0u;
DMACH2bits.CHEN = 1u; /* DMA1チャンネルを有効にする */
IFS1bits.DMA2IF = 0u;
/*-------------------------------------------------------------------------*/
/* ADモジュール初期化*/
/*-----------------------------------------------------------------------------*/
ADCON1L = 0x0000u;
ADCON1H = 0x0000u;
ADCON2L = 0x0000u;
ADCON2H = 0x0000u;
ADCON3L = 0x0000u;
ADCON3H = 0x0000u;
ADCON5H = 0x0000u;
ADTRIG0L = 0x0000u;
ADTRIG0H = 0x0000u;
ADTRIG1L = 0x0000u;
ADTRIG1H = 0x0000u;
ADTRIG2L = 0x0000u;
ADTRIG2H = 0x0000u;
ADTRIG3L = 0x0000u;
ADTRIG3H = 0x0000u;
ADTRIG4L = 0x0000u;
ADTRIG4H = 0x0000u;
ADTRIG5L = 0x0000u;
ADLVLTRGL = 0x0000u;
ADLVLTRGH = 0x0000u;
ADCMP0CON = 0x0000u;
ADCMP0ENL = 0x0000u;
ADCMP0ENH = 0x0000u;
/***** AD制御レジスタの設定 ******/
ADCON1Hbits.SHRRES = 3u; /* シェアADC分解能 (3 = 12bit) */
ADCON2Lbits.SHRADCS = 2u; /* シェアADCClockディバイダ(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トリガ―の設定 ******/
ADTRIG1Hbits.TRGSRC7 = 0x16; /* AN7入力のトリガ設定(SCCP3) */
/***** AD割り込みの設定(重要) ******/
ADIELbits.IE7 = 1u;
IEC6bits.ADCAN7IE = 0u;
/***** ADFilter ******/
ADFL0CONbits.FLCHSEL = 7u; /* 入力チャンネル設定(AN7)*/
ADFL0CONbits.MODE = 3u; /* フィルタモード */
ADFL0CONbits.OVRSAM = 0u; /* オーバーサンプリング比 */
ADFL0CONbits.FLEN = 1u; /* フィルタの有効化 */
/***** ADの有効化 ******/
ADCON1Lbits.ADON = 1u; /* ADC全体のパワーON */
ADCON5Lbits.SHRPWR = 1u; /* シェアADCのパワーON */
while(ADCON5Lbits.SHRRDY == 0u){;}
ADCON3Hbits.SHREN = 1u; /* シェアADCの有効化 */
/*-----------------------------------------------------------------------------*/
/* CCPモジュール有効化*/
/*-----------------------------------------------------------------------------*/
CCP3CON1Lbits.CCPON = 1u;
/*-----------------------------------------------------------------------------*/
/* メインルーチン*/
/*-----------------------------------------------------------------------------*/
while(1)
{
}
}
結果
取得したu2g_ADCData[]の中身をCSVにて書き出し、グラフ化してみるとサイン波が格納されている事が確認できます。サンプルの6番目と7番目が不連続なのは入出力のサンプリング周波数が異なる為です。



コメント