dsPIC30F3012 で PCMデータ再生
比較的メモリサイズの大きい PIC である dsPIC30F3012 を使うと、18 pin DIP の1チップで2秒程度PCMデータが鳴らせます。
2秒あると意外といろいろできますよ!
実装例 (動画)
回路図
詳細は、ソースコードを見たほうが手っ取り早いと思いますので貼り付けます。フリーのC30コンパイラを利用しています。
ソースコード他一式はこちらからダウンロードしてください。
//-------------------------------------------------------
// dsPIC30F3012 で PCM データ再生 (2008/2/25, ksasao)
//-------------------------------------------------------
// - 8kHz, 8bit の PCMデータを再生します。外付けメモリ
// 無しで合計約2秒間鳴らせます。
// - PCMの再生には RD0 の PWM 出力を利用します。
// - dsPICの内蔵クロックを PLLx8 で利用すると3Vで駆動
// できます(PLLx16にしたい場合は5Vが必要です)。
// 本ソースコードは煮たり焼いたりお好きなように。
//-------------------------------------------------------
#include <p30f3012.h>
#include <outcompare.h>
#include <timer.h>
// 設定値は、
// %ProgramFiles%MicrochipMPLAB C30supporthp30f3012.h や
// dsPIC30F3012の PDF を参照してください。
_FWDT(WDT_OFF); // ウォッチドッグタイマ無効
_FGS(CODE_PROT_OFF); // コードプロテクト無効
_FOSC(CSW_FSCM_OFF & FRC_PLL8); // FRC(7.37MHz)xPLL8/4=7.37MIPS * 2
_FBORPOR(PBOR_OFF & PWRT_64 & MCLR_EN);
// 遅延のための関数です
void delay(int count){
while(count--);
}
// 再生処理の宣言です。
void playP(int start,int end);
// 8kHz, 8bitの PCMデータを適当に作成してください(128が中央値です)
const unsigned char WAV_DATA[] = {
129,130,128,126,128,128,131,128,125,128,128,129,128,128,128,128,
// 略
127,126,125,126,128,129,130,131,130,129,128,128,128,128,127,126
};
// ピン割り当て (dsPIC30F3012)
//--------------------------------------------------------------
// 1(I) /MCLR (10kでプルアップ) 18(I) AVdd (+3V)
// 2(I) スイッチ0(RB0) 17(I) AVss (GND)
// 3(I) スイッチ1(RB1) 16(N.C.)
// 4(I) スイッチ2(RB2) 15(N.C.)
// 5(I) スイッチ3(RB3) 14(I) Vdd (+3V)
// 6(N.C.) 13(I) Vss (GND)
// 7(N.C.) 12(N.C)
// 8(I) スイッチ4(RC13) 11(N.C)
// 9(I) スイッチ5(RC14) 10(O) PWM出力(RD0)
//--------------------------------------------------------------
// dsPIC30F3021 の 2 - 5, 8, 9 番ピンは 10kΩでプルアップしておき、
// スイッチが押されたら Lになるよう1kΩの抵抗を各スイッチのGND側に
// 配置します。
int main(void){
// 各ポートの出力値設定
PORTB = 0xFFFF;
PORTC = 0xFFFF;
PORTD = 0xFFFE;
// 入出力設定 (O: 出力, I: 入力, -:無効)
TRISB = 0x000F; // ---- ---- OOOO IIII
TRISC = 0x6000; // OII- ---- ---- ----
TRISD = 0x0000; // ---- ---- ---- ---O
// ADコンバータ設定(0:ADコンバータを利用 1:ディジタルI/Oを利用)
// デフォルトでは、ADコンバータが有効なため、PORTB をディジタル
// I/Oとして利用したい場合は、下記設定は必須です><
ADPCFG = 0xFFFF;
// 今回は適当です。各ボタンが押されたら単純に
// 指定した範囲を再生します。
while (1) {
if(!PORTCbits.RC13){
playP(0,116*16-1);
}
if(!PORTCbits.RC14){
playP(116*16,218*16-1);
}
int b = PORTB;
if(!(b & 0x1)){
playP(218*16,437*16-1);
}
if(!(b & 0x2)){
playP(437*16,570*16-1);
}
if(!(b & 0x4)){
playP(570*16,722*16-1);
}
if(!(b & 0x8)){
playP(722*16,972*16-1);
}
}
return 0;
}
// PCMデータを start から end まで再生します。
void playP(int start,int end){
int p = start;
const int MAX = 256;
TRISD = 0x0000; // ---- ---- ---- ---O
// PWM関連の設定です。リンクするライブラリが結構大きいので、
// インラインアセンブラで書いたほうが良いと思います。
SetDCOC1PWM(0);
OpenOC1(OC_IDLE_CON & OC_TIMER2_SRC & OC_PWM_FAULT_PIN_DISABLE, 0, 0);
// 7.37MHz * 8逓倍(PLL) / 4命令 / MAX段階 = 57.6kHz(@MAX=256)
OpenTimer2(T2_ON & T2_GATE_OFF & T2_PS_1_1 & T2_SOURCE_INT, MAX - 1);
const int WAIT = 360; // 決めうち :-)
// スピーカーが「カチっ!」というのを抑える
int startup = 0;
while(startup < 128){
SetDCOC1PWM(startup++);
delay(WAIT);
}
// ここからがメインの再生
unsigned int c0;
while(p<end) {
c0 = WAV_DATA[p];
p++;
SetDCOC1PWM(c0);
delay(WAIT);
}
// スピーカーが「カチっ!」というのを抑える
int count = 127;
while(count > 0){
SetDCOC1PWM(count--);
delay(WAIT);
}
// ここではスピーカーが停止状態
}
2秒あると意外といろいろできますよ!
実装例 (動画)
回路図
詳細は、ソースコードを見たほうが手っ取り早いと思いますので貼り付けます。フリーのC30コンパイラを利用しています。
ソースコード他一式はこちらからダウンロードしてください。
//-------------------------------------------------------
// dsPIC30F3012 で PCM データ再生 (2008/2/25, ksasao)
//-------------------------------------------------------
// - 8kHz, 8bit の PCMデータを再生します。外付けメモリ
// 無しで合計約2秒間鳴らせます。
// - PCMの再生には RD0 の PWM 出力を利用します。
// - dsPICの内蔵クロックを PLLx8 で利用すると3Vで駆動
// できます(PLLx16にしたい場合は5Vが必要です)。
// 本ソースコードは煮たり焼いたりお好きなように。
//-------------------------------------------------------
#include <p30f3012.h>
#include <outcompare.h>
#include <timer.h>
// 設定値は、
// %ProgramFiles%MicrochipMPLAB C30supporthp30f3012.h や
// dsPIC30F3012の PDF を参照してください。
_FWDT(WDT_OFF); // ウォッチドッグタイマ無効
_FGS(CODE_PROT_OFF); // コードプロテクト無効
_FOSC(CSW_FSCM_OFF & FRC_PLL8); // FRC(7.37MHz)xPLL8/4=7.37MIPS * 2
_FBORPOR(PBOR_OFF & PWRT_64 & MCLR_EN);
// 遅延のための関数です
void delay(int count){
while(count--);
}
// 再生処理の宣言です。
void playP(int start,int end);
// 8kHz, 8bitの PCMデータを適当に作成してください(128が中央値です)
const unsigned char WAV_DATA[] = {
129,130,128,126,128,128,131,128,125,128,128,129,128,128,128,128,
// 略
127,126,125,126,128,129,130,131,130,129,128,128,128,128,127,126
};
// ピン割り当て (dsPIC30F3012)
//--------------------------------------------------------------
// 1(I) /MCLR (10kでプルアップ) 18(I) AVdd (+3V)
// 2(I) スイッチ0(RB0) 17(I) AVss (GND)
// 3(I) スイッチ1(RB1) 16(N.C.)
// 4(I) スイッチ2(RB2) 15(N.C.)
// 5(I) スイッチ3(RB3) 14(I) Vdd (+3V)
// 6(N.C.) 13(I) Vss (GND)
// 7(N.C.) 12(N.C)
// 8(I) スイッチ4(RC13) 11(N.C)
// 9(I) スイッチ5(RC14) 10(O) PWM出力(RD0)
//--------------------------------------------------------------
// dsPIC30F3021 の 2 - 5, 8, 9 番ピンは 10kΩでプルアップしておき、
// スイッチが押されたら Lになるよう1kΩの抵抗を各スイッチのGND側に
// 配置します。
int main(void){
// 各ポートの出力値設定
PORTB = 0xFFFF;
PORTC = 0xFFFF;
PORTD = 0xFFFE;
// 入出力設定 (O: 出力, I: 入力, -:無効)
TRISB = 0x000F; // ---- ---- OOOO IIII
TRISC = 0x6000; // OII- ---- ---- ----
TRISD = 0x0000; // ---- ---- ---- ---O
// ADコンバータ設定(0:ADコンバータを利用 1:ディジタルI/Oを利用)
// デフォルトでは、ADコンバータが有効なため、PORTB をディジタル
// I/Oとして利用したい場合は、下記設定は必須です><
ADPCFG = 0xFFFF;
// 今回は適当です。各ボタンが押されたら単純に
// 指定した範囲を再生します。
while (1) {
if(!PORTCbits.RC13){
playP(0,116*16-1);
}
if(!PORTCbits.RC14){
playP(116*16,218*16-1);
}
int b = PORTB;
if(!(b & 0x1)){
playP(218*16,437*16-1);
}
if(!(b & 0x2)){
playP(437*16,570*16-1);
}
if(!(b & 0x4)){
playP(570*16,722*16-1);
}
if(!(b & 0x8)){
playP(722*16,972*16-1);
}
}
return 0;
}
// PCMデータを start から end まで再生します。
void playP(int start,int end){
int p = start;
const int MAX = 256;
TRISD = 0x0000; // ---- ---- ---- ---O
// PWM関連の設定です。リンクするライブラリが結構大きいので、
// インラインアセンブラで書いたほうが良いと思います。
SetDCOC1PWM(0);
OpenOC1(OC_IDLE_CON & OC_TIMER2_SRC & OC_PWM_FAULT_PIN_DISABLE, 0, 0);
// 7.37MHz * 8逓倍(PLL) / 4命令 / MAX段階 = 57.6kHz(@MAX=256)
OpenTimer2(T2_ON & T2_GATE_OFF & T2_PS_1_1 & T2_SOURCE_INT, MAX - 1);
const int WAIT = 360; // 決めうち :-)
// スピーカーが「カチっ!」というのを抑える
int startup = 0;
while(startup < 128){
SetDCOC1PWM(startup++);
delay(WAIT);
}
// ここからがメインの再生
unsigned int c0;
while(p<end) {
c0 = WAV_DATA[p];
p++;
SetDCOC1PWM(c0);
delay(WAIT);
}
// スピーカーが「カチっ!」というのを抑える
int count = 127;
while(count > 0){
SetDCOC1PWM(count--);
delay(WAIT);
}
// ここではスピーカーが停止状態
}
TOP PAGE △