概要
以前の記事にも有りますように、dsPICシリーズは「dsP」と頭文字がつくように、DSPが内蔵されています。今回は、dsPIC33AKシリーズのDSPの使い方をご紹介します。
関連記事
| 関連記事 | リンク |
| DSPライブラリの使い方1(デジタルフィルタ) | DSPライブラリの使い方1(デジタルフィルタ) – ぴくおの電子工作的な何かWP (electricpico.com) |
| DSPライブラリの使い方2(FFT) | DSPライブラリの使い方2(FFT) – ぴくおの電子工作的な何かWP (electricpico.com) |
開発環境
開発環境を以下に示します。
今回はCPUボード(EV02G02A)で動作確認を行います。
| 項目 | 値 | リンク |
| ベースボード | dsPIC33A CURIOSITY PLATFORM DEVELOPMENT BOARD | dsPIC33A Curiosity Platform Development Board User’s Guide (microchip.com) |
| CPUボード(EV68M17A) | EV68M17A – dsPIC33AK128MC106 Motor Control DIM | dsPIC33AK128MC106 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.20 | MPLAB® X IDE | Microchip Technology |
| コンパイラ | MPLAB XC DSC v3.10 | MPLAB® XC DSC Compiler | Microchip Technology |

フィルタ特性について
今回はサンプリング周波数を48kHzに設定し、LPF/BPF/HPFの3種類のフィルタを試してみます。フィルタ設計については、以前の記事を参考にしてください。
| タイプ | カットオフ周波数[Hz] | ゲイン・フェーズ特性 |
| LPF | 5k | ![]() |
| BPF | 7k – 10k | ![]() |
| HPF | 10k | ![]() |
ただし、今回は下表のとおり分解能は16ビットではなく32ビットに設定します
| dsPIC33F/E/C | dsPIC33A | |
| 説明文 | ⑥Quantize Coefficients ウィンドウが開きますので、Quantize by に16bit / Format to save coeffsを Dec に設定し「OK」をクリック。 | ⑥Quantize Coefficients ウィンドウが開きますので、Quantize by に32bit / Format to save coeffsを Dec に設定し「OK」をクリック。 |
| イメージ | ![]() | ![]() |
ソースコード
インクルードファイル
コンフィグレーションファイル、クロック設定ファイルは以下のファイルをインクルードしてください。
■コンフィグレーションファイル (config.h)
■クロック設定ソースファイル(Clock_Driver.c)
■クロックヘッダーファイル(clock_driver.h)
ライブラリインポート
DSPを使用する場合、dsp.hのインクルードとlibdsp-elf.aのインポートが必須です。

ソースコード全体
#include <stdio.h>
#include <stdlib.h>
#include <xc.h>
#include "config.h"
#include "clock_driver.h"
#include <dsp.h>
#define FIR_TAP 100 //FIRタップ数
#define FIR_SFREQ 48000 //FIRサンプリング周波数
#define FIR_DUMMY_A_FREQ 2000.0
#define FIR_DUMMY_B_FREQ 8500.0
#define FIR_DUMMY_C_FREQ 12000.0
#define FIR_DUMMY_A_GAIN 0.9
#define FIR_DUMMY_B_GAIN 0.5
#define FIR_DUMMY_C_GAIN 0.2
#define FIR_SPL_NUM 256
//入力ダミーデータ
float fl_FIRDummyData[FIR_SPL_NUM];
fractional fir_FIRDummyData[FIR_SPL_NUM];
//フィルタ構造
FIRStruct firFilterLPF;
FIRStruct firFilterBPF;
FIRStruct firFilterHPF;
//フィルタ出力
fractional fir_OutputLPF[FIR_SPL_NUM];
fractional fir_OutputBPF[FIR_SPL_NUM];
fractional fir_OutputHPF[FIR_SPL_NUM];
/*
U_0
Remez Algorithm LPF
Sampling Frequency = 48000.0
cutoff1 = 5000.0000000
cutoff2 = 6000.0000000
Tap Count = 100
attenuate = -40.00
ripple factor = 0.1000000
*/
fractional LPF_SF48k_CF5k_100T[FIR_TAP] __attribute__((space(xmemory), far))=
{
-11345875 ,
-1348086 ,
2101441 ,
3038787 ,
5320409 ,
2845042 ,
747979 ,
-4361683 ,
-5804455 ,
-6403468 ,
-1598913 ,
2916012 ,
8395421 ,
8350743 ,
5483385 ,
-2429496 ,
-8614922 ,
-12542608 ,
-8780894 ,
-1148515 ,
9536639 ,
15288686 ,
14825745 ,
5135436 ,
-7568629 ,
-19050243 ,
-20872508 ,
-12669195 ,
4491020 ,
20858908 ,
29241529 ,
22277659 ,
2901321 ,
-21887197 ,
-38217748 ,
-37139217 ,
-14921886 ,
19215710 ,
50152787 ,
59427382 ,
37944823 ,
-10987720 ,
-67344991 ,
-103091528 ,
-90561247 ,
-16586082 ,
111645541 ,
265039300 ,
402334708 ,
483213741 ,
483213741 ,
402334708 ,
265039300 ,
111645541 ,
-16586082 ,
-90561247 ,
-103091528 ,
-67344991 ,
-10987720 ,
37944823 ,
59427382 ,
50152787 ,
19215710 ,
-14921886 ,
-37139217 ,
-38217748 ,
-21887197 ,
2901321 ,
22277659 ,
29241529 ,
20858908 ,
4491020 ,
-12669195 ,
-20872508 ,
-19050243 ,
-7568629 ,
5135436 ,
14825745 ,
15288686 ,
9536639 ,
-1148515 ,
-8780894 ,
-12542608 ,
-8614922 ,
-2429496 ,
5483385 ,
8350743 ,
8395421 ,
2916012 ,
-1598913 ,
-6403468 ,
-5804455 ,
-4361683 ,
747979 ,
2845042 ,
5320409 ,
3038787 ,
2101441 ,
-1348086 ,
-11345875
};
/*
U_0
Remez Algorithm BPF
Sampling Frequency = 48000.0
cutoff1 = 7000.0000000
cutoff2 = 8000.0000000
cutoff3 = 9000.0000000
cutoff4 = 10000.0000000
Tap Count = 100
attenuate = -100.00
ripple factor = 0.1000000
*/
fractional BPF_SF48k_CF7k10k__100T[FIR_TAP] __attribute__((space(xmemory), far))=
{
-137284 ,
383693 ,
50904 ,
55042 ,
336813 ,
429783 ,
-265282 ,
-1314330 ,
-1083485 ,
1197710 ,
3332260 ,
1767570 ,
-3449184 ,
-6574309 ,
-1874078 ,
7746838 ,
10915680 ,
459622 ,
-14686346 ,
-15734882 ,
3640738 ,
24458855 ,
19853859 ,
-11550546 ,
-36596100 ,
-21646933 ,
23990460 ,
49829102 ,
19335100 ,
-40914960 ,
-62152223 ,
-11427647 ,
61265420 ,
71118683 ,
-2805381 ,
-82951371 ,
-74335670 ,
22953832 ,
103105517 ,
70049274 ,
-47328536 ,
-118598930 ,
-57653816 ,
73130196 ,
126696283 ,
37981890 ,
-96925144 ,
-125687009 ,
-13262466 ,
115322660 ,
115322660 ,
-13262466 ,
-125687009 ,
-96925144 ,
37981890 ,
126696283 ,
73130196 ,
-57653816 ,
-118598930 ,
-47328536 ,
70049274 ,
103105517 ,
22953832 ,
-74335670 ,
-82951371 ,
-2805381 ,
71118683 ,
61265420 ,
-11427647 ,
-62152223 ,
-40914960 ,
19335100 ,
49829102 ,
23990460 ,
-21646933 ,
-36596100 ,
-11550546 ,
19853859 ,
24458855 ,
3640738 ,
-15734882 ,
-14686346 ,
459622 ,
10915680 ,
7746838 ,
-1874078 ,
-6574309 ,
-3449184 ,
1767570 ,
3332260 ,
1197710 ,
-1083485 ,
-1314330 ,
-265282 ,
429783 ,
336813 ,
55042 ,
50904 ,
383693 ,
-137284
};
/*
U_0
Remez Algorithm HPF
Sampling Frequency = 48000.0
cutoff1 = 10000.0000000
cutoff2 = 11000.0000000
Tap Count = 100
attenuate = -100.00
ripple factor = 0.1000000
Quantized by 32 [bits]
631042
*/
fractional HPF_SF48k_CF10k_100T[FIR_TAP] __attribute__((space(xmemory), far))=
{
631042 ,
7886162 ,
-36828284 ,
66598643 ,
-52523460 ,
-3268292 ,
32315499 ,
-2502069 ,
-23918555 ,
794611 ,
20056737 ,
2622472 ,
-17538827 ,
-6674920 ,
15044598 ,
10841364 ,
-11787302 ,
-14803700 ,
7493018 ,
17986285 ,
-1920700 ,
-19990284 ,
-4689383 ,
20145758 ,
12119433 ,
-18091418 ,
-19649860 ,
13301775 ,
26603126 ,
-5607716 ,
-32075079 ,
-4838361 ,
34793249 ,
17998637 ,
-33875157 ,
-33081339 ,
27957117 ,
49302389 ,
-15581318 ,
-65755972 ,
-5098258 ,
81319072 ,
37580014 ,
-94803461 ,
-90977124 ,
105253372 ,
199264175 ,
-111926424 ,
-673824800 ,
1187934027 ,
-673824800 ,
-111926424 ,
199264175 ,
105253372 ,
-90977124 ,
-94803461 ,
37580014 ,
81319072 ,
-5098258 ,
-65755972 ,
-15581318 ,
49302389 ,
27957117 ,
-33081339 ,
-33875157 ,
17998637 ,
34793249 ,
-4838361 ,
-32075079 ,
-5607716 ,
26603126 ,
13301775 ,
-19649860 ,
-18091418 ,
12119433 ,
20145758 ,
-4689383 ,
-19990284 ,
-1920700 ,
17986285 ,
7493018 ,
-14803700 ,
-11787302 ,
10841364 ,
15044598 ,
-6674920 ,
-17538827 ,
2622472 ,
20056737 ,
794611 ,
-23918555 ,
-2502069 ,
32315499 ,
-3268292 ,
-52523460 ,
66598643 ,
-36828284 ,
7886162 ,
631042 ,
0
};
fractional Delays[FIR_TAP] __attribute__((space(ymemory), far));
int32_t i4g_Time[16];
/*----------------------------------------------------------------------------*/
/**
* @fn main(int argc, char** argv)
* @brief PROJECT_4_1_1_DSP_FIR
* @param[in] argc argument count
* @param[in] argv argument vector
* @retval EXIT_SUCCESS 成功
* @retval EXIT_FAILURE 失敗
* @detail DSPによるFFT
* @note
*/
/*----------------------------------------------------------------------------*/
int main(int argc, char** argv)
{
unsigned int u2l_Loop;
unsigned int u2lCnt;
float f4_Time;
float f4_DummyA;
float f4_DummyB;
float f4_DummyC;
CORCON = 0x00;
/*------------------------------------------------------------------------*/
/* クロック初期化*/
/*------------------------------------------------------------------------*/
vdg_Clock_Set_Register(); /* クロック初期化 */
/*-----------------------------------------------------------------------*/
/* Timerレジスタ */
/*-----------------------------------------------------------------------*/
PR1 = 1000000;
T1CONbits.ON = 1;
T1CONbits.TCKPS = 0;
IFS1bits.T1IF = 0;
IEC1bits.T1IE = 0;
IPC6bits.T1IP = 3;
INTCON1bits.GIE = 0;
/*------------------------------------------------------------------------*/
/* フィルタ係数初期化*/
/*------------------------------------------------------------------------*/
FIRStructInit( &firFilterLPF, // フィルター構造体
FIR_TAP, // フィルター係数タップ数
LPF_SF48k_CF5k_100T, // フィルタ係数ポインタ
0, // フィルタ係数PSVページ
Delays ); // ディレイバッファ
FIRStructInit( &firFilterBPF, // フィルター構造体
FIR_TAP, // フィルター係数タップ数
BPF_SF48k_CF7k10k__100T, // フィルタ係数ポインタ
0, // フィルタ係数PSVページ
Delays ); // ディレイバッファ
FIRStructInit( &firFilterHPF, // フィルター構造体
FIR_TAP, // フィルター係数タップ数
HPF_SF48k_CF10k_100T, // フィルタ係数ポインタ
0, // フィルタ係数PSVページ
Delays ); // ディレイバッファ
/*------------------------------------------------------------------------*/
/* ディレイバッファクリア*/
/*------------------------------------------------------------------------*/
FIRDelayInit( &firFilterLPF ); // フィルター構造体
FIRDelayInit( &firFilterBPF ); // フィルター構造体
FIRDelayInit( &firFilterHPF ); // フィルター構造体
/*------------------------------------------------------------------------*/
/* ダミーデータ生成*/
/*------------------------------------------------------------------------*/
for (u2l_Loop = 0;u2l_Loop < FIR_SPL_NUM ;u2l_Loop ++)
{
f4_Time = (float)u2l_Loop/(FIR_SFREQ);
f4_DummyA = sin(f4_Time * FIR_DUMMY_A_FREQ * 2 * PI) * FIR_DUMMY_A_GAIN ;
f4_DummyB = sin(f4_Time * FIR_DUMMY_B_FREQ * 2 * PI) * FIR_DUMMY_B_GAIN ;
f4_DummyC = sin(f4_Time * FIR_DUMMY_C_FREQ * 2 * PI) * FIR_DUMMY_C_GAIN ;
fl_FIRDummyData[u2l_Loop] = (f4_DummyA + f4_DummyB + f4_DummyC);
fir_FIRDummyData[u2l_Loop] = fl_FIRDummyData[u2l_Loop] * 1073741823;
}
/*------------------------------------------------------------------------*/
/* フィルタ演算*/
/*------------------------------------------------------------------------*/
i4g_Time[0] = TMR1;
for (u2lCnt = 0;u2lCnt < FIR_SPL_NUM;u2lCnt ++)
{
FIR( 1, // 入力信号個数
&fir_OutputLPF[u2lCnt], // 出力サンプル変数ポインタ
&fir_FIRDummyData[u2lCnt], // 入力サンプル変数ポインタ
&firFilterLPF ); // フィルター構造体
}
i4g_Time[1] = TMR1;
for (u2lCnt = 0;u2lCnt < FIR_SPL_NUM;u2lCnt ++)
{
FIR( 1, // 入力信号個数
&fir_OutputBPF[u2lCnt], // 出力サンプル変数ポインタ
&fir_FIRDummyData[u2lCnt], // 入力サンプル変数ポインタ
&firFilterBPF ); // フィルター構造体
}
i4g_Time[2] = TMR1;
for (u2lCnt = 0;u2lCnt < FIR_SPL_NUM;u2lCnt ++)
{
FIR( 1, // 入力信号個数
&fir_OutputHPF[u2lCnt], // 出力サンプル変数ポインタ
&fir_FIRDummyData[u2lCnt], // 入力サンプル変数ポインタ
&firFilterHPF ); // フィルター構造体
}
i4g_Time[3] = TMR1;
/*------------------------------------------------------------------------*/
/* メインループ*/
/*------------------------------------------------------------------------*/
while(1)
{
}
return EXIT_SUCCESS
}
結果
生信号に対してそれぞれLPF/BPF/HPF処理を行った結果、目的の周波数の信号と振幅を得られることが確認できました。

今回の256サンプルを実行する処理では、約238μsecで演算を完了しました。
1サンプルの場合、処理は約0.9μsecで完了するため、48kHzのサンプリングごとに実行しても、0.9μsec/20.83μsecで十分な余裕があることが確認できました。
記事についての注意点
本記事は慎重に内容を検討し正確さに努めておりますが、内容に誤りがあったとしても、この記事を参考にして生じた損害等については一切の責任を負いません。






コメント