dsPIC33AKシリーズ⑩DMAモジュールの使い方

DMAの使い方

概要

今回は、強化されたDMAモジュールの使い方をご紹介します。
DMAとはDirect Memory Accessの略でCPUのリソースを使用せずに、RAMやペリフェラル間のデータ転送を実行するモジュールです。

以前の記事( DACとDMAモジュールの使い方(任意波形出力編) – ぴくおの電子工作的な何かWP (electricpico.com) )で紹介したように、従来のdsPICシリーズにもDMAモジュールは搭載されていました。しかし、dsPIC33AKシリーズでは、さらに強化されたDMA機能が搭載されています。

以下にその特徴を示します。

特徴

・6つの独立したチャンネル
・CPUとの同時動作(DMAによる待機状態なし)
・固定優先順位とラウンドロビン方式によるDMAバス調停
・4つのアドレスモード
・4つの転送モード
・ピンポン・モード(各ブロック転送完了後に2つのチャネルを自動切り替え)
・データ転送のための8ビット、16ビットまたは32ビットワード・サポート
・各チャンネルに24ビットの送信元および宛先アドレス・レジスタを搭載。
・32ビット・トランザクション・カウント・レジスタ。
・上下限アドレス・レジスタ
・カウンタ・ハーフ/フル・レベル割り込み
・ソフトウェア・トリガー転送
・対称バッファ・オペレーションのためのヌル・ライト・モード
・各チャネルのDMAリクエストは、サポートされた割り込みソースから選択可能
・チャネル・チェイニングと呼ばれるチャネルのデイジー・チェイニングのサポート
・セット/クリア/反転ビット操作機能
・パターン・マッチ
・バス・リード/ライト・エラー障害表示

今回は基本的な使い方から実践的な使い方まで紹介します。

記事変更履歴

公開/
変更日
特記
24/08/11初版公開。
25/11/15Ping-Pongモードについて注記追加

関連記事

記事リンク
第1回dsPIC33AKシリーズについてdsPIC33Aシリーズに関して – ぴくおの電子工作的な何かWP (electricpico.com)
第2回開発ボード、コンフィグレーション設定、クロック設定についてdsPIC33AKシリーズ②開発ボード,コンフィグレーション設定,クロック設定について – ぴくおの電子工作的な何かWP (electricpico.com)
第3回CPU性能についてdsPIC33AKシリーズ③CPU性能について – ぴくおの電子工作的な何かWP (electricpico.com)
第4回FPU性能についてdsPIC33AKシリーズ④FPU性能について – ぴくおの電子工作的な何かWP (electricpico.com)
第5回DSPについてdsPIC33AKシリーズ⑤DSPについて – ぴくおの電子工作的な何かWP (electricpico.com)
第6回タイマー1割り込みの使い方dsPIC33AKシリーズ⑥Timer1割り込みの使い方 – ぴくおの電子工作的な何かWP (electricpico.com)
第7回PMUの使い方dsPIC33AKシリーズ⑦PMUの使い方 – ぴくおの電子工作的な何かWP (electricpico.com)
第8回高速ADCの使い方dsPIC33AKシリーズ⑧高速ADCの使い方 – ぴくおの電子工作的な何かWP (electricpico.com)
第9回高速OPAMPの使い方dsPIC33AKシリーズ⑨高速OPAMPの使い方 – ぴくおの電子工作的な何かWP (electricpico.com)
第10回(本記事)DMAモジュールの使い方dsPIC33AKシリーズ⑩DMAモジュールの使い方 – ぴくおの電子工作的な何かWP
(fig.1-1)各関連記事リンク

開発環境

開発環境を以下に示します。
今回はどちらのCPUボードでも動作いたします。

項目リンク
ベースボードdsPIC33A CURIOSITY PLATFORM
DEVELOPMENT BOARD
dsPIC33A Curiosity Platform Development Board User’s Guide (microchip.com)
CPUボード(EV68M17A)EV68M17A – dsPIC33AK128MC106 Motor Control DIMdsPIC33AK128MC106 Motor Control Dual In-Line Module (DIM) Information Sheet (microchip.com)
CPUボード(EV02G02A)dsPIC33AK128MC106 General Purpose Dual In-Line Module (DIM)dsPIC33AK128MC106 General Purpose Dual In-Line Module (DIM) | Microchip Technology
統合開発環境MPLAB X IDE v6.20MPLAB® X IDE | Microchip Technology
コンパイラMPLAB XC DSC v3.10MPLAB® XC DSC Compiler | Microchip Technology
(fig.2-1)本記事の動作確認環境
(fig.2-2)動作環境

DMAレジスタ

以下にDMAレジスタとその説明を示します。

レジスタ名(xは1~6)機能説明
DMACONDMAモジュール制御レジスタDMAモジュール全体の設定を行う
DMABUFDMAデータバッファレジスタDMA転送時の一時バッファ
DMALOWDMAアドレス低リミットレジスタDMA転送のためのアドレスリミットを設定する
DMAHIGHDMAアドレス高リミットレジスタDMA転送のためのアドレスリミットを設定する
DMAxCHDMAチャンネルx制御レジスタDMAチャンネルxの各種設定を行う
DMAxSELDMAチャンネルxトリガレジスタDMAチャンネルxの転送トリガを設定する
DMAxSTATDMAチャンネルxステータスレジスタDMAチャンネルxの動作ステータスを取得する
DMAxSRCDMAチャンネルx転送元レジスタDMAチャンネルxの転送元アドレスを設定する
DMAxDSTDMAチャンネルx転送先レジスタDMAチャンネルxの転送先アドレスを設定する
DMAxCNTDMAチャンネルxカウントレジスタDMAチャンネルxの転送回数を設定する
DMAxCLRDMAチャンネルxクリアレジスタDMABUF レジスタの対応ビットをクリアする
DMAxSETDMAチャンネルxセットレジスタDMABUF レジスタの対応ビットをセットする
DMAxINVDMAチャンネルx反転レジスタDMABUF レジスタの対応ビットを反転する
DMAxMSKDMAチャンネルxマスクレジスタパターンマッチ用マスクビットを設定する
DMAxPATDMAチャンネルxパターンマッチレジスタパターンマッチ用データ
(fig.3-1)DMAレジスタ

DMA基本動作

転送タイプ

DMAの転送は、Peripheralアドレス(SFR Area)とRAMアドレス(Data Space)間で自由にデータを転送できます。

(fig.4-1)転送タイプ(dsPIC33AK128MC106-Family-Data-Sheet-DS70005539.pdf p.659より抜粋)

転送モード

転送モードは以下の4つを備えています。

モード転送バイト転送終了後
ワンショットDMAxCHbits.SIZEモジュール停止
繰り返しワンショットDMAxCHbits.SIZEリロードとリピート
連続DMAxCHbits.SIZE × DMAxCNTモジュール停止
繰り返し連続DMAxCHbits.SIZE × DMAxCNTリロードとリピート
(fig.4-2)転送モード

ワンショット転送モード (RAM → RAM)

動作説明

ワンショット転送モードは1回の転送トリガに対し1回の転送を行います。
DMAxCNTで設定した回数の転送トリガを受信するとチャンネルの動作が無効になります。

(fig.5-1)ワンショットモード

ソースコード

インクルードファイル

コンフィグレーションファイル、クロック設定ファイルは以下のファイルをインクルードしてください。

■コンフィグレーションファイル (config.h)

■クロック設定ソースファイル(Clock_Driver.c)

■クロックヘッダーファイル(clock_driver.h)

ソースコード全体

下記のコードは1回の転送トリガしか発生させていないため、u4g_SrcData[0]のみがu4g_DstData[0]に転送されます。

#include <stdio.h>
#include <stdlib.h>
#include <xc.h>
#include "config.h"
#include "clock_driver.h"

uint32_t u4g_SrcData[8];
uint32_t u4g_DstData[8];

int main() 
{
    /*-----------------------------------------------------------------------*/
    /*初期化*/
    /*-----------------------------------------------------------------------*/
        vdg_Clock_Set_Register();
		
	for (int i=0 ; i< 8 ;i++)
	{
	  u4g_SrcData[i] =i * 10 + 20;
	  u4g_DstData[i] = 0x00000000U;
	}
		
    /*-----------------------------------------------------------------------*/
    /* DMA設定 */
    /*-----------------------------------------------------------------------*/
	DMACONbits.ON = 1U;        //DMA有効
	DMACONbits.PRIORITY = 0U;  //Fixed
	DMACONbits.SIDL = 0UL;

	DMABUF = 0x00000000u;

	DMALOW = 0x4000U;
	DMAHIGH = 0x7FFFU;

	DMA0CH = 0x00000000U;
	DMA0CHbits.SIZE = 2U;	 //32Bit
	DMA0CHbits.TRMODE = 0U;  //One-Shot
	DMA0CHbits.DAMODE = 1U; //Increment
	DMA0CHbits.SAMODE = 1U; //Increment

	DMA0SEL = 0x00000000U;
	DMA0STAT = 0x00000000U;
	DMA0SRC = (unsigned int)& u4g_SrcData;  //転送元
	DMA0DST = (unsigned int)& u4g_DstData; //転送先
	DMA0CNT = 8u;                           //転送回数
	DMA0CLR = 0x00000000U;
	DMA0SET = 0x00000000U;
	DMA0INV = 0x00000000U;
	DMA0MSK = 0x00000000U;
	DMA0PAT = 0x00000000U;
		
	DMA0CHbits.CHEN = 1U;  //DMA0チャネル有効化

	DMA0CHbits.CHREQ = 1U; //DMA0ソフトウェア転送開始
	while(DMA0CHbits.CHREQ){;}  //DMA0ソフトウェア転送完了確認
		
	while(1)
	{
		;	
	}	
}   

もし全部の転送を行う場合は、下記のコードを8回繰り返す必要が有ります。

	DMA0CHbits.CHREQ = 1U; //DMA0ソフトウェア転送開始
	while(DMA0CHbits.CHREQ){;}  //DMA0ソフトウェア転送完了確認

連続転送モード (RAM → RAM)

動作説明

連続転送モードは1回の転送トリガに対し複数回の転送を行います。回数はDMA0CNTで設定します。
転送トリガを受信し8回の転送が完了するとチャンネルの動作が無効になります。

(fig.5-2)連続転送モード

ソースコード

ワンショット転送モードとの違い

ワンショット転送モードとの違いは以下の行のみです。

	DMA0CHbits.TRMODE = 2U;  //連続転送

ソースコード全体

下記のコードを実行すると、u4g_SrcData[0]~[7]の値がu4g_DstData[0]~[7]に転送されます。

#include <stdio.h>
#include <stdlib.h>
#include <xc.h>
#include "config.h"
#include "clock_driver.h"
#include <dsp.h>

uint32_t u4g_SrcData[8];
uint32_t u4g_DstData[8];

int main() 
{
    /*-----------------------------------------------------------------------*/
    /*初期化*/
    /*-----------------------------------------------------------------------*/
        vdg_Clock_Set_Register();
		
	for (int i=0 ; i< 8 ;i++)
	{
	  u4g_SrcData[i] =i * 10 + 20;
	  u4g_DstData[i] = 0x00000000U;
	}
		
    /*-----------------------------------------------------------------------*/
    /* DMA設定 */
    /*-----------------------------------------------------------------------*/
	DMACONbits.ON = 1U;        //DMA有効
	DMACONbits.PRIORITY = 0U;  //Fixed
	DMACONbits.SIDL = 0UL;

	DMABUF = 0x00000000u;

	DMALOW = 0x4000U;
	DMAHIGH = 0x7FFFU;

	DMA0CH = 0x00000000U;
	DMA0CHbits.SIZE = 2U;	 //32Bit
	DMA0CHbits.TRMODE = 2U;  //連続転送
	DMA0CHbits.DAMODE = 1U; //Increment
	DMA0CHbits.SAMODE = 1U; //Increment

	DMA0SEL = 0x00000000U;
	DMA0STAT = 0x00000000U;
	DMA0SRC = (unsigned int)& u4g_SrcData;  //転送元
	DMA0DST = (unsigned int)& u4g_DstData; //転送先
	DMA0CNT = 8u;                           //転送回数
	DMA0CLR = 0x00000000U;
	DMA0SET = 0x00000000U;
	DMA0INV = 0x00000000U;
	DMA0MSK = 0x00000000U;
	DMA0PAT = 0x00000000U;
		
	DMA0CHbits.CHEN = 1U;  //DMA0チャネル有効化

	DMA0CHbits.CHREQ = 1U; //DMA0ソフトウェア転送開始
	while(DMA0CHbits.CHREQ){;}  //DMA0ソフトウェア転送完了確認
		
	while(1)
	{
		;	
	}	
}   

ワンショットリピートモード(RAM → RAM)

動作説明

ワンショットリピートモードは1回の転送トリガに対し1回の転送を行います。
DMAxCNTで設定した回数の転送トリガを受信してもチャンネルの動作が無効になりません。

ここで重要なのが、以下のリロード設定を有効にすることです。これを転送元、転送先の両方に設定しておくことで、アドレスがリロードされます。

	DMA0CHbits.DAMODE = 1U;  //リロード
	DMA0CHbits.SAMODE = 1U;  //リロード
(fig.5-3)ワンショットリピートモード

ソースコード

ソースコード全体

以下を実行するとwhileループでトリガを発生させていますので、データ転送が永遠と実行されます。

#include <stdio.h>
#include <stdlib.h>
#include <xc.h>
#include "config.h"
#include "clcok_driver.h"
#include <dsp.h>

uint32_t u4g_SrcData[8];
uint32_t u4g_DstData[8];

int main() 
{
    /*-----------------------------------------------------------------------*/
    /*初期化*/
    /*-----------------------------------------------------------------------*/
        vdg_Clock_Set_Register();
		
	for (int i=0 ; i< 8 ;i++)
	{
	  u4g_SrcData[i] =i * 10 + 20;
	  u4g_DstData[i] = 0x00000000U;
	}
		
    /*-----------------------------------------------------------------------*/
    /* DMA設定 */
    /*-----------------------------------------------------------------------*/
	DMACONbits.ON = 1U;        //DMA有効
	DMACONbits.PRIORITY = 0U;  //Fixed
	DMACONbits.SIDL = 0UL;

	DMABUF = 0x00000000u;

	DMALOW = 0x4000U;
	DMAHIGH = 0x7FFFU;

	DMA0CH = 0x00000000U;
	DMA0CHbits.SIZE = 2U;	 //32Bit
	DMA0CHbits.TRMODE = 1U;  //ワンショットリピート
	DMA0CHbits.DAMODE = 1U; //Increment
	DMA0CHbits.SAMODE = 1U; //Increment
	DMA0CHbits.DAMODE = 1U;  //リロード
	DMA0CHbits.SAMODE = 1U;  //リロード

	DMA0SEL = 0x00000000U;
	DMA0STAT = 0x00000000U;
	DMA0SRC = (unsigned int)& u4g_SrcData;  //転送元
	DMA0DST = (unsigned int)& u4g_DstData; //転送先
	DMA0CNT = 8u;                           //転送回数
	DMA0CLR = 0x00000000U;
	DMA0SET = 0x00000000U;
	DMA0INV = 0x00000000U;
	DMA0MSK = 0x00000000U;
	DMA0PAT = 0x00000000U;
		
	DMA0CHbits.CHEN = 1U;  //DMA0チャネル有効化
	
	while(1)
	{
		DMA0CHbits.CHREQ = 1U;
		while(DMA0CHbits.CHREQ){;}	
	}	
} 

ワンショット転送モード(Peripheral → RAM)

動作説明

dsPIC33AKになって、大きく進化した点にADCの変換速度が最大40Mspsと非常に高速になった点が挙げられます。ただこの速度でADC変換したデータを取得することは困難です。

そこで今回は例として50kHzの信号を5MHzでサンプリングするという仕様を検討します。
下記のブロック図のようにSCCP0のトリガ(5MHz)によってサンプリングを行い、そのAD変換完了によってDMA転送トリガを発動し、DMAによりで256回データを転送したあとに、チャネルを無効化するものとします。

(fig.5-4)ワンショットモード(AD変換)

ソースコード

ソースコード全体

#include <stdio.h>
#include <stdlib.h>
#include <xc.h>
#include "config.h"
#include "clock_driver.h"
#include <dsp.h>

uint32_t u4g_AdcData[256];
int main() 
{
    /*-----------------------------------------------------------------------*/
    /*初期化*/
    /*-----------------------------------------------------------------------*/
        vdg_Clock_Set_Register();
		
  /*-----------------------------------------------------------------------*/
    /*ADC設定*/
    /*-----------------------------------------------------------------------*/
	ANSELAbits.ANSELA11 = 1u;	//PortA11をアナログ入力に設定
		
	AD1CH0CONbits.TRG1SRC = 0x0Cu;	//SCCP1 Trig
	AD1CH0CONbits.PINSEL = 10u;	//AD1CH0+入力はAD1AN10
	AD1CH0CONbits.MODE = 0u;	//シングル変換モード
		
	AD1CON = 0x00000000U;
	AD1CONbits.ON = 1U;   
	while(AD1CONbits.ADRDY == 0U)
	{
		;
	}

  /*-----------------------------------------------------------------------*/
  /* DMAレジスタ */
  /*-----------------------------------------------------------------------*/
	DMACONbits.ON = 1u;
	DMACONbits.PRIORITY = 0U;		//Fixed
	DMACONbits.SIDL = 0UL;

	DMABUF = 0x00000000u;
	DMALOW = 0x4000U;
	DMAHIGH = 0x7FFFU;

	DMA0CH = 0x00000000U;
	DMA0CHbits.CHEN = 0U;
	DMA0CHbits.HALFEN = 0U;
	DMA0CHbits.MATEN = 0U;
	DMA0CHbits.INTOEN = 0U;
	DMA0CHbits.CHREQ = 0U;
	DMA0CHbits.SIZE = 2U;		//32Bit
	DMA0CHbits.FLWCON =  0U;
	DMA0CHbits.TRMODE = 0U;		//One-Shot
	DMA0CHbits.DAMODE = 1U;		//インクリメント
	DMA0CHbits.SAMODE = 0U;		//変更無
	DMA0CHbits.RETEN = 0U;
	DMA0CHbits.RELOADS = 0U;
	DMA0CHbits.RELOADD = 0U;
	DMA0CHbits.RELOADC = 0U;
	DMA0CHbits.PCHAEN = 0U;
	DMA0CHbits.PPEN = 0U;

	DMA0SEL = 0x2Bu;
		
	DMA0STAT = 0x00000000U;
	DMA0SRC = (unsigned int)& AD1CH0DATA;
	DMA0DST = (unsigned int)& u4g_AdcData;
	DMA0CNT = 256u;
	DMA0CLR = 0x00000000U;
	DMA0SET = 0x00000000U;
	DMA0INV = 0x00000000U;
	DMA0MSK = 0x00000000U;
	DMA0PAT = 0x00000000U;
		
	DMA0CHbits.CHEN = 1U;
		
  /*-----------------------------------------------------------------------*/
    /* CCP1レジスタ*/
    /*-----------------------------------------------------------------------*/
	CCP1CON1 = 0x00000000u;
	CCP1CON2 = 0x00000000u;
	CCP1CON3 = 0x00000000u;

	CCP1PR = 19U;			 //100MHz / 5MHz -1 = 19
	CCP1RA = 0x00000000u;
	CCP1RB = 0x00000000u;
		
	CCP1CON1bits.ON = 1u;
	while(1)
	{

	}
}	

結果

以下に測定結果を示します。50kHzの信号を5MHzでサンプリングした結果、計算通りに2.5周期分のデータがサンプリングされていることが確認できました。
ちなみに入力信号を500kHz、サンプリング周波数を20MHzにした時も、計算通りデータが取得できています。

Ping-Pongモードについて

動作説明

DMAによるPing-Pongモードは、データ転送を途切れなく行うための高度なテクニックです。このモードは、2つのバッファ(通常はバッファAとバッファB)を交互に使用してデータを転送します。これにより、1つのバッファがデータを受け取っている間に、もう1つのバッファが次のデータを処理できる状態になります。

DMAによるPing-Pongモードの動作フロー:

  1. バッファAへのデータ転送: DMAがまずバッファAにデータを転送します。
  2. バッファBの準備: バッファAへの転送が行われている間、バッファBが次のデータを受け取る準備をします。
  3. バッファBへのデータ転送: バッファAが満杯になったら、DMAは自動的にバッファBにデータを転送し始めます。
  4. バッファAの準備: バッファBがデータを受け取っている間、バッファAが次の転送に備えてクリアされます。

このプロセスは連続的に行われるため、データの転送と処理がスムーズに進行し、遅延を最小限に抑えることができます。Ping-Pongモードは、リアルタイム処理や高頻度でデータが転送されるシステムで特に有効です。たとえば、音声データやセンサーデータの処理でよく使われます。

(fig.6-1)Ping-Pongモード受信
DMAにシリコンエラッタ

DMAに関するシリコンエラッタが何点か報告されています。
dsPIC33AK128MC106 Family Silicon Errata and Data Sheet Clarification (microchip.com)

A2リビジョンではPing-Pongモードが完全に動作せず、1回のペア転送が完了した時に動作が停止してしまう事が報告されています。

なお2nd Generation であるdsPIC33AK512MPS512系ではこの問題は解消されている模様です

今回は、AD変換データをBufferA(DMACH0)からBufferB(DMACH1)へ連続して保存するプロセスを確認します。

ソースコード

ソースコード全体

#include <stdio.h>
#include <stdlib.h>
#include <xc.h>
#include "peripheral_init.h"
#include "BoardSupportPackage.h"
#include <dsp.h>

uint32_t u4g_AdcDataA[256];
uint32_t u4g_AdcDataB[256];
int main() 
{
    /*-----------------------------------------------------------------------*/
    /*初期化*/
    /*-----------------------------------------------------------------------*/
        vdg_Clock_Set_Register();
		
  /*-----------------------------------------------------------------------*/
    /*ADC設定*/
    /*-----------------------------------------------------------------------*/
	ANSELAbits.ANSELA11 = 1u;	//PortA11をアナログ入力に設定
		
	AD1CH0CONbits.TRG1SRC = 0x0Cu;	//SCCP1 Trig
	AD1CH0CONbits.PINSEL = 10u;	//AD1CH0+入力はAD1AN10
	AD1CH0CONbits.MODE = 0u;	//シングル変換モード
		
	AD1CON = 0x00000000U;
	AD1CONbits.ON = 1U;   
	while(AD1CONbits.ADRDY == 0U)
	{
		;
	}
  /*-----------------------------------------------------------------------*/
  /* DMAレジスタ */
  /*-----------------------------------------------------------------------*/
	DMACONbits.ON = 1u;
	DMACONbits.PRIORITY = 0U;		//Fixed
	DMACONbits.SIDL = 0UL;
	DMABUF = 0x00000000u;
	DMALOW = 0x4000U;
	DMAHIGH = 0x7FFFU;
	DMA0CH = 0x00000000U;
	DMA0CHbits.CHEN = 0U;
	DMA0CHbits.HALFEN = 0U;
	DMA0CHbits.MATEN = 0U;
	DMA0CHbits.INTOEN = 1U;		//
	DMA0CHbits.CHREQ = 0U;
	DMA0CHbits.SIZE = 2U;		//32Bit
	DMA0CHbits.FLWCON =  0U;
    DMA0CHbits.TRMODE = 1U;		//One-Shotリピート
	DMA0CHbits.DAMODE = 1U;		//インクリメント
    DMA0CHbits.SAMODE = 0U;		//変更無
	DMA0CHbits.RETEN = 0U;
	DMA0CHbits.RELOADS = 1U;        //リロード有効
	DMA0CHbits.RELOADD = 1U;        //リロード有効
	DMA0CHbits.RELOADC = 0U;
	DMA0CHbits.PCHAEN = 1U;
	DMA0CHbits.PPEN = 1U;		//Ping-Pong 有効化

	DMA0SEL = 0x2Bu;
		
	DMA0STAT = 0x00000000U;
	DMA0SRC = (unsigned int)& AD1CH0DATA;
	DMA0DST = (unsigned int)& u4g_AdcDataA;
	DMA0CNT = 256u;

	DMA0CHbits.CHEN = 1U;

	DMA1CH = 0x00000000U;
	DMA1CHbits.CHEN = 0U;
	DMA1CHbits.HALFEN = 0U;
	DMA1CHbits.MATEN = 0U;
	DMA1CHbits.INTOEN = 1U;
	DMA1CHbits.CHREQ = 0U;
	DMA1CHbits.SIZE = 2U;		//32Bit
	DMA1CHbits.FLWCON =  0U;
	DMA1CHbits.TRMODE = 1U;		//One-Shotリピート
	DMA1CHbits.DAMODE = 1U;		//インクリメント
	DMA1CHbits.SAMODE = 0U;		//変更無
	DMA1CHbits.RETEN = 0U;
	DMA1CHbits.RELOADS = 1U;        //リロード有効
	DMA1CHbits.RELOADD = 1U;        //リロード有効
	DMA1CHbits.RELOADC = 0U;
	DMA1CHbits.PCHAEN = 0U;
	DMA1CHbits.PPEN = 1U;		//Ping-Pong 有効化

	DMA1SEL = 0x2Bu;
		
	DMA1STAT = 0x00000000U;
	DMA1SRC = (unsigned int)& AD1CH0DATA;
	DMA1DST = (unsigned int)& u4g_AdcDataB;
	DMA1CNT = 256u;
		
	DMA1CHbits.CHEN = 1U;
  /*-----------------------------------------------------------------------*/
    /* CCP1CON1初期化*/
    /*-----------------------------------------------------------------------*/
	CCP1CON1 = 0x00000000u;
	CCP1CON2 = 0x00000000u;
	CCP1CON3 = 0x00000000u;
	CCP1STAT = 0x00000000u;
	CCP1TMR = 0x00000000u;
	CCP1PR = 19U;		//100MHz / 5MHz -1 = 19
	CCP1RA = 0x00000000u;
	CCP1RB = 0x00000000u;   
	CCP1BUF = 0x00000000u;
		
	CCP1CON1bits.ON = 1u;
	while(1)
	{

	}
}	

結果

CH0(青)が256回サンプリングを終了した後に連続してCH1(赤)が256回データを取得している事が確認できました。

記事についての注意点

本記事は慎重に内容を検討し正確さに努めておりますが、内容に誤りがあったとしても、この記事を参考にして生じた損害等については一切の責任を負いません。

コメント

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