DSP

Ti的C28x系列的DSP(28069)(28377)使用经验,ADC经验

2019-07-13 10:34发布

笔者使用过的项目中,使用的ADC都是DSP的片内ADC,使用片内ADC的好处是,转换速度快,节约成本,这是相比片外ADC的优势。 DSP_28069的ADC精度是12位,DSP_28377D的ADC精度可以选择为12位,也可以选择为16位,笔者这里采用的是12位,两种DSP的采样模式都是单端模式。 DSP的ADC采样精度和参考电压有很大的关系,一般选择外部参考电压,参考电压一定要加RC滤波电路。 计算公式如下: 关于ADC其他方面的原理,这里就不作介绍了,如果读者想了解更多,可以搜搜其他博客看看。 笔者在项目中使用ADC,基本上只涉及以下几个方面:
  • ADC的初始化
ADC初始化,主要分为两个部分,ADC的模式选择,(精度模式、采样方式(差分或单端)),中断触发时刻,使能中断等。 void InitAdcPart1(void) { EALLOW; SysCtrlRegs.PCLKCR0.bit.ADCENCLK = 1; (*Device_cal)(); EDIS; EALLOW; AdcRegs.ADCCTL1.bit.ADCBGPWD = 1; // Power ADC BG AdcRegs.ADCCTL1.bit.ADCREFPWD = 1; // Power reference AdcRegs.ADCCTL1.bit.ADCPWDN = 1; // Power ADC AdcRegs.ADCCTL1.bit.ADCENABLE = 1; // Enable ADC AdcRegs.ADCCTL1.bit.ADCREFSEL = 1; // External VREFHI or VREFLO pins used for //reference generation EDIS; DELAY_US(1000L); // Delay before converting ADC channels EALLOW; AdcRegs.ADCCTL2.bit.CLKDIV2EN = 0; //ADCCLK = SYSCLK = 80Mhz EDIS; DELAY_US(1000L); // Delay before converting ADC channels } void InitAdcPart2(void) { EALLOW; AdcRegs.ADCCTL2.bit.ADCNONOVERLAP = 1; // Overlap of sample is not allowed AdcRegs.ADCSAMPLEMODE.all = 0; // Single sample mode //物理采样通道选择 AdcRegs.ADCSOC0CTL.bit.CHSEL = 0; //ADCINA0 AdcRegs.ADCSOC1CTL.bit.CHSEL = 1; AdcRegs.ADCSOC2CTL.bit.CHSEL = 2; AdcRegs.ADCSOC3CTL.bit.CHSEL = 3; AdcRegs.ADCSOC4CTL.bit.CHSEL = 4; AdcRegs.ADCSOC5CTL.bit.CHSEL = 5; AdcRegs.ADCSOC6CTL.bit.CHSEL = 6; AdcRegs.ADCSOC7CTL.bit.CHSEL = 7; //ADCINA7 AdcRegs.ADCSOC8CTL.bit.CHSEL = 8; //ADCINB0 AdcRegs.ADCSOC9CTL.bit.CHSEL = 9; AdcRegs.ADCSOC10CTL.bit.CHSEL= 10; AdcRegs.ADCSOC11CTL.bit.CHSEL= 11; AdcRegs.ADCSOC12CTL.bit.CHSEL= 12; AdcRegs.ADCSOC13CTL.bit.CHSEL= 13; AdcRegs.ADCSOC14CTL.bit.CHSEL= 14; AdcRegs.ADCSOC15CTL.bit.CHSEL= 15; //ADCINB7 //采样保持时间 //Sample window =(19 + 1 clock cycles). AdcRegs.ADCSOC0CTL.bit.ACQPS = 19; AdcRegs.ADCSOC1CTL.bit.ACQPS = 19; AdcRegs.ADCSOC2CTL.bit.ACQPS = 19; AdcRegs.ADCSOC3CTL.bit.ACQPS = 19; AdcRegs.ADCSOC4CTL.bit.ACQPS = 19; AdcRegs.ADCSOC5CTL.bit.ACQPS = 19; AdcRegs.ADCSOC6CTL.bit.ACQPS = 19; AdcRegs.ADCSOC7CTL.bit.ACQPS = 19; AdcRegs.ADCSOC8CTL.bit.ACQPS = 19; AdcRegs.ADCSOC9CTL.bit.ACQPS = 19; AdcRegs.ADCSOC10CTL.bit.ACQPS = 19; AdcRegs.ADCSOC11CTL.bit.ACQPS = 19; AdcRegs.ADCSOC12CTL.bit.ACQPS = 19; AdcRegs.ADCSOC13CTL.bit.ACQPS = 19; AdcRegs.ADCSOC14CTL.bit.ACQPS = 19; AdcRegs.ADCSOC15CTL.bit.ACQPS = 19; //ADC触发源 //4//set SOC0 start trigger on XIN2 AdcRegs.ADCSOC0CTL.bit.TRIGSEL = 4; //4;// // 5 set SOC0 start trigger on EPWM1A AdcRegs.ADCSOC1CTL.bit.TRIGSEL = 4; //4; AdcRegs.ADCSOC2CTL.bit.TRIGSEL = 4; //4; AdcRegs.ADCSOC3CTL.bit.TRIGSEL = 4; //4; AdcRegs.ADCSOC4CTL.bit.TRIGSEL = 4; //4; AdcRegs.ADCSOC5CTL.bit.TRIGSEL = 4; //4; AdcRegs.ADCSOC6CTL.bit.TRIGSEL = 4; //4; AdcRegs.ADCSOC7CTL.bit.TRIGSEL = 4; //4; AdcRegs.ADCSOC8CTL.bit.TRIGSEL = 4; //4; AdcRegs.ADCSOC9CTL.bit.TRIGSEL = 4; //4; AdcRegs.ADCSOC10CTL.bit.TRIGSEL = 4; //4; AdcRegs.ADCSOC11CTL.bit.TRIGSEL = 4; //4; AdcRegs.ADCSOC12CTL.bit.TRIGSEL = 4; //4; AdcRegs.ADCSOC13CTL.bit.TRIGSEL = 4; //4; AdcRegs.ADCSOC14CTL.bit.TRIGSEL = 4; //4; AdcRegs.ADCSOC15CTL.bit.TRIGSEL = 4; //4; EDIS; } void InitAdcINT(void) { EALLOW; AdcRegs.ADCCTL1.bit.INTPULSEPOS = 1; // ADCINT1 trips after AdcResults latch AdcRegs.INTSEL1N2.bit.INT1CONT = 0; // Disable ADCINT1 Continuous mode AdcRegs.INTSEL1N2.bit.INT1SEL = 15; // EOC15 is trigger for ADCINT1 EALLOW; } void EnableAdcInterrupt(void) { EALLOW; AdcRegs.INTSEL1N2.bit.INT1E = 1; // Enabled ADCINT1 EDIS; } ADC的触发源,即表示如何启动ADC转换,一般用PWM启动ADC,或者外部GPIO启动ADC,比如FPGA外部触发ADC。
  • ADC转换的结果ADCRESULT
ADCRESULT表示数据采集的源头,各种电压电流,都是通过这个公式(ADCRESULT - 零漂)* 系数而得到的。
  • ADC的转换完成后触发的中断
   ADC触发的中断,一般是整个DSP系统中的主中断,这个中断里会运行一些数据采集、算法、故障保护等实时性要求比较高的函数。 void InitInterrupt(void) { EALLOW; // This is needed to write to EALLOW protected register PieVectTable.ADCINT1 = &Interrupt_Adc1; EDIS; // This is needed to disable write to EALLOW protected registers PieCtrlRegs.PIEIFR1.bit.INTx1 = 0; PieCtrlRegs.PIEIER1.bit.INTx1 = 1; // Enable ADC1 INT 1.1 in the PIE PieCtrlRegs.PIEACK.all = 0x0FFF; //set all ack to 0 } __interrupt void Interrupt_Adc1(void) { ServeMainInt(); AdcRegs.ADCINTFLGCLR.bit.ADCINT1 = 1; //Clear ADCINT1 flag reinitialize //for next SOC PieCtrlRegs.PIEACK.all |= PIEACK_GROUP1; // Acknowledge interrupt to PIE }