//******************************************************************************* // A/D convert -> Delay&Add -> PWM out wave→これをDAC out waveに変更 N.Ishii // 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 2008/01/04 //=============================================================================== // // オリジナル・プログラムは、上記コメントの岩田さん // // dsPIC30F4013による遅延+加算くし型フィルタの実験(DAC+LPF出力) // 2012+ブートローダー使用を、4013+PICkit2に変更して実験 // 「自作FRAもどき」にて周波数特性を確認してみる。 // 50Hzのノイズが除去される。(心電計の実験) // fs= 1.6kHz, Td= 10mS // // 2017/4/7 N.Ishii //******************************************************************************* #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; // MCP4822 control bit #define selDAC_A 0x3000 #define selDAC_B 0xb000 #define GAIN_2x 0x9000 #define GAIN_1x 0xb000 #define DAC_DOWN 0xa000 #define DAC_OE 0xb000 // SPI control register; unsigned int _SPI1STAT; unsigned int _SPI1CON; // data unsigned int ResultData; unsigned int TmpData; int DelayLine[18]; int outdata; int indata; void PushDelay(int din) { // 遅延器のプッシュ int tmpDelayLine[18]; // ローカル配列の宣言 VectorCopy(18-1, tmpDelayLine+1, DelayLine); // 配列を一個ずらしてコピー(DSPライブラリ使用) tmpDelayLine[0] = din; // 新しいデータを入れる VectorCopy(18, DelayLine, tmpDelayLine); // グローバル配列にコピー(DSPライブラリ使用) } int CalOutWave() { // 遅延前のデータと遅延後のデータを加算 int tmp; tmp = DelayLine[0] + DelayLine[16]; return tmp; } // Timer subroutine void __attribute__((__interrupt__, __shadow__, no_auto_psv)) _T3Interrupt(void) { // --- A/D is 12bits, filtering is 12bits, DAC is 12bits while(!IFS0bits.ADIF); // wait A/D ResultData = ReadADC12(0); // 12bit resolution indata = ResultData - 2048; // 符号付きにする PushDelay(indata); // 遅延器のプッシュ outdata = CalOutWave(); // 遅延前のデータと遅延後のデータを加算 outdata += 2048; // 符号なしにする if(outdata > 4095) outdata = 4095; // オーバフローリミッタ if(outdata < 0) outdata = 0; // アンダーフローリミッタ ResultData = outdata; TmpData = SPI1BUF; // clear SPI receive flag TmpData = selDAC_A & GAIN_2x & DAC_OE; // set DAC control bit TmpData |= ResultData; // set value PORTBbits.RB2 = 0; // MCP4822 #CS assert WriteSPI1(TmpData); // send data while(SPI1STATbits.SPIRBF == 0); // waiting transmittion complete PORTBbits.RB2 = 1; // MCP4822 #CS negate IFS0bits.ADIF = 0; // clear A/D interuppt flag IFS0bits.T3IF = 0; // clear T3 interuppt flag } // Main routine int main(void) { // port init TRISB=0x01FF; TRISBbits.TRISB2 = 0; PORTBbits.RB2 = 1; // MCP4822 #CS negate // 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); // SPI init _SPI1CON = FRAME_ENABLE_OFF & FRAME_SYNC_INPUT & ENABLE_SDO_PIN & SPI_MODE16_ON & SPI_SMP_ON & SPI_CKE_OFF & CLK_POL_ACTIVE_LOW & SLAVE_ENABLE_OFF & MASTER_ENABLE_ON & SEC_PRESCAL_2_1 & PRI_PRESCAL_1_1; _SPI1STAT = SPI_ENABLE & SPI_IDLE_CON & SPI_RX_OVFLOW_CLR; OpenSPI1(_SPI1CON, _SPI1STAT); // DAC initialize TmpData = SPI1BUF; // clear SPI receive flag TmpData = selDAC_A & GAIN_2x & DAC_OE; // set DAC control bit TmpData |= 2048; // center position PORTBbits.RB2 = 0; // MCP4822 #CS assert WriteSPI1(TmpData); // send data while(SPI1STATbits.SPIRBF == 0); // waiting transmittion complete PORTBbits.RB2 = 1; // MCP4822 #CS negate // Timer3 setting OpenTimer3(T3_ON & T3_GATE_OFF & T3_PS_1_1 & T3_SOURCE_INT, 18430-1); // 29.48MHz/18430 = 1.6kHz sampling ADC ConfigIntTimer3(T3_INT_PRIOR_5 & T3_INT_ON); // enable interrupt DISICNT = 0x0000; // main loop while(1) { // A/D result store in ResultData } }