//*********************************************************** // A/D convert -> Moving Avarage -> PWM out wave // 7.37MHz Internal RC oscillator, 16x PLL enabled // Fcy=7.37MHzx16/4=29.48MHz, Tcy=33.92ns // Toshio Iwata at DIGITALFILTER.COM all rights reserved // Last modified on 2007/06/06 //========================================================= // // オリジナル・プログラムは、上記コメントの岩田さん // // dsPIC30F4013による移動平均によるLPFの実験 // 2012+ブートローダー使用を、4013+PICkit2に変更して実験 // 「自作FRAもどき」にて周波数特性を確認してみる。 // // 2016/3/16 N.Ishii //*********************************************************** //#include #include #include #include #include // configuration _FWDT(WDT_OFF); _FGS(CODE_PROT_OFF); _FOSC(CSW_FSCM_OFF & FRC_PLL16); _FBORPOR(PBOR_OFF & PWRT_64 & MCLR_EN); // A/D control register unsigned int _ADCON1; unsigned int _ADCON2; unsigned int _ADCON3; unsigned int _ADCHS; unsigned int _ADPCFG; unsigned int _ADCSSL; // PWM control register unsigned int _PTCON; unsigned int _PWMCON1; unsigned int _PWMCON2; // data unsigned int ResultData; int DelayLine[10]; int Coeff[10]; int outdata; int indata; void CoeffInit() { // 移動平均フィルタ(10タップ)の係数を代入 int i; // +1.0 -> 32767(0x7FFF), -1.0 -> -32768(0x8000) // したがって +0.1 -> 3276 となる。 for(i = 0; i < 10; i++) Coeff[i] = 3276; } void PushDelay(int din) { // 遅延器のプッシュ int tmpDelayLine[10]; VectorCopy(10-1, tmpDelayLine+1, DelayLine); // 配列を一個ずらしてコピー(DSPライブラリ使用) tmpDelayLine[0] = din; // 新しいデータを入れる VectorCopy(10, DelayLine, tmpDelayLine); // グローバル配列にコピー(DSPライブラリ使用) } int CalOutWave() { // デジタルフィルタの出力を計算 int tmp; tmp = VectorDotProduct(10, DelayLine, Coeff); // データと係数積和演算(DSPライブラリ使用) return tmp; } // Timer subroutine //void __attribute__((__interrupt__, __shadow__, no_auto_psv)) _AltT3Interrupt(void) void __attribute__((__interrupt__, __shadow__, no_auto_psv)) _T3Interrupt(void) { // --- A/D is 12bits, filtering is 12bits, then truncate 2bits, PWM is 10bits while(!IFS0bits.ADIF); // wait A/D ResultData = ReadADC12(0); // 12bit resolution (28.8kHz sampling) indata = ResultData - 2048; // 符号付きにする PushDelay(indata); // 遅延器のプッシュ outdata = CalOutWave(); // デジタルフィルタの出力を計算 outdata += 2048; // 符号なしにする if(outdata > 4095) outdata = 4095; // オーバフローリミッタ if(outdata < 0) outdata = 0; // アンダーフローリミッタ ResultData = outdata >> 2; // 10ビットにする SetDCOC2PWM(ResultData); IFS0bits.ADIF = 0; // clear A/D interuppt flag IFS0bits.T3IF = 0; // clear T3 interuppt flag } // Main routine int main(void) { // port init TRISB=0x01FF; // Use Alternate Interrupt Vector Table // INTCON2bits.ALTIVT=1; // Confirm to turn off ADC ADCON1bits.ADON=0; // ADC init _ADCHS= ADC_CH0_POS_SAMPLEA_AN3 & ADC_CH0_NEG_SAMPLEA_NVREF; // A-D channel-3 select SetChanADC12(_ADCHS); _ADCON1=ADC_MODULE_ON & ADC_IDLE_CONTINUE & ADC_FORMAT_INTG & ADC_CLK_TMR & ADC_AUTO_SAMPLING_ON & ADC_SAMP_OFF; _ADCON2=ADC_VREF_AVDD_AVSS & ADC_SCAN_OFF & ADC_SAMPLES_PER_INT_1 & ADC_ALT_BUF_OFF & ADC_ALT_INPUT_OFF; // Tad={Tcy(ADCS+1)}/2>334ns, Then ADCS>18.7, Tad=10*Tcy _ADCON3=ADC_SAMPLE_TIME_1 & ADC_CONV_CLK_SYSTEM & ADC_CONV_CLK_10Tcy; _ADPCFG=ENABLE_AN3_ANA; // A-D channel-3 analog input _ADCSSL=SCAN_NONE; OpenADC12(_ADCON1, _ADCON2, _ADCON3, _ADPCFG, _ADCSSL); // Timer3 setting OpenTimer3(T3_ON & T3_GATE_OFF & T3_PS_1_1 & T3_SOURCE_INT, 1024-1); // 28.8kHz sampling ADC ConfigIntTimer3(T3_INT_PRIOR_5 & T3_INT_ON); // Timer2 setting OpenTimer2(T2_ON & T2_GATE_OFF & T2_PS_1_1 & T2_SOURCE_INT, 1024-1); // 28.8kHz carrier PWM OpenOC2(OC_IDLE_CON & OC_TIMER2_SRC & OC_PWM_FAULT_PIN_DISABLE, 0, 0); // enable interrupt DISICNT = 0x0000; CoeffInit(); // 移動平均フィルタ(10タップ)の係数を代入 // main loop while(1) { // A/D result store in ResultData } // CloseTimer3(); // never excute // CloseADC12(); // never excute // CloseOC1(); // never excute }