This thread has been locked.
If you have a related question, please click the "Ask a related question" button in the top right corner. The newly created question will be automatically linked to this question.
各位好,
我想使用软件触发ADC进行连续采样,但是我将.ADCSOCFRC1位置1后,在WATCH WINDOW中看.ADCSOCFRC1仍然是0,,
因此ADC也没有正确工作,希望各位看下代码帮我找找原因,谢谢。
————————————————————————————————
void main()
{
// Step 1. Initialize System Control:
// PLL, WatchDog, enable Peripheral Clocks
// This example function is found in the DSP2833x_SysCtrl.c file.
InitSysCtrl();
// Step 2. Initalize GPIO:
// This example function is found in the DSP2833x_Gpio.c file and
// illustrates how to set the GPIO to it's default state.
// InitGpio(); // Skipped for this example
// Step 3. Clear all interrupts and initialize PIE vector table:
// Disable CPU interrupts
DINT;
InitEPwm6Gpio();
// Initialize PIE control registers to their default state.
// The default state is all PIE interrupts disabled and flags
// are cleared.
// This function is found in the DSP2833x_PieCtrl.c file.
InitPieCtrl();
// Disable CPU interrupts and clear all CPU interrupt flags:
IER = 0x0000;
IFR = 0x0000;
InitPieVectTable();
// Interrupts that are used in this example are re-mapped to
// ISR functions found within this file.
EALLOW; // This is needed to write to EALLOW protected register
PieVectTable.ADCINT1 = &adc_isr;
// Enable ADCINT1 in PIE
PieCtrlRegs.PIEIER1.bit.INTx1 = 1; // Enable INT 1.1 in the PIE
EDIS; // This is needed to disable write to EALLOW protected registers
// Step 4. Initialize all the Device Peripherals:
// This function is found in DSP2803x_InitPeripherals.c
// InitPeripherals(); // Not required for this example
InitAdc(); // For this example, init the ADC
InitEPwm6();
// Step 5. User specific code, enable interrupts:
IER |= M_INT1; // Enable CPU Interrupt 1
EINT; // Enable Global interrupt INTM
ERTM; // Enable Global realtime interrupt DBGM
LoopCount = 0;
ConversionCount = 0;
for(i=0;i<512;i++)
{
SampleTable[ConversionCount] = 0;
ConversionCount++;
}
ConversionCount = 0;
Adc_Config();
//Force start of conversion on SOC0
EALLOW;
AdcRegs.ADCSOCFRC1.all = 0x03;
EDIS;
for(;;)
{
asm("NOP");
}
}
interrupt void adc_isr(void)
{
//Wait for end of conversion.
while(AdcRegs.ADCINTFLG.bit.ADCINT1 == 0){} //Wait for ADCINT1
AdcRegs.ADCINTFLGCLR.bit.ADCINT1 = 1; //Clear ADCINT1
SampleTable[ConversionCount] = AdcResult.ADCRESULT0;
// If 512 conversions have been logged, start over
if(ConversionCount == 512)
{
ConversionCount = 0;
}
else ConversionCount++;
AdcRegs.ADCINTFLGCLR.bit.ADCINT1 = 1; //Clear ADCINT1 flag reinitialize for next SOC
PieCtrlRegs.PIEACK.all = PIEACK_GROUP1; // Acknowledge interrupt to PIE
return;
}
void Adc_Config()
{
// Configure ADC
EALLOW;
AdcRegs.ADCCTL1.bit.INTPULSEPOS = 1; //ADCINT1 trips after AdcResults latch
AdcRegs.INTSEL1N2.bit.INT1E = 1; //Enabled ADCINT1
AdcRegs.INTSEL1N2.bit.INT1CONT = 0; //Disable ADCINT1 Continuous mode
AdcRegs.INTSEL1N2.bit.INT1SEL = 1; //setup EOC1 to trigger ADCINT1 to fire
AdcRegs.ADCSOC0CTL.bit.CHSEL = 7; //set SOC0 channel select to ADCINA7
AdcRegs.ADCSOC1CTL.bit.CHSEL = 7; //set SOC1 channel select to ADCINA7
AdcRegs.ADCSOC0CTL.bit.TRIGSEL = 0; //set SOC0 start trigger on software
AdcRegs.ADCSOC1CTL.bit.TRIGSEL = 0; //set SOC1 start trigger on software
AdcRegs.ADCSOC0CTL.bit.ACQPS = 6; //set SOC0 S/H Window to 7 ADC Clock Cycles, (6 ACQPS plus 1)
AdcRegs.ADCSOC1CTL.bit.ACQPS = 6; //set SOC0 S/H Window to 7 ADC Clock Cycles, (6 ACQPS plus 1)
AdcRegs.ADCINTSOCSEL1.bit.SOC0 = 1; //ADCINT1 will trigger SOC0. TRIGSEL field is ignored.
AdcRegs.ADCINTSOCSEL1.bit.SOC1 = 1; //ADCINT1 will trigger SOC0. TRIGSEL field is ignored.
EDIS;
} —————————————————————————————————————————————————————— 谢谢各位了。
1. 建议使用其它方法确定ADC采样能否工作;
2. 建议参考例程的osc_comp工程项目进行软件触发的设置;
3. 确定ADC已使能(ADCCTL1的bit14 ADCENABLE位), ADC clock已提供(PCLKCR0的bit3 ADCENCLK位);
4. 即便你的设置成功,也只能采样一次,因为每置位一次只执行一次采样,所以需要循环赋值;
5. 可以通过调试模式手动更改寄存器的值查看运行状态。
设置两个SOC的目的是为了丢弃第一个采样值 -- 因为每个采样序列的第一个可能不准确(请查看Piccolo B勘误表),它不会导致ADC不能启动。
谢谢您,您的解答对我帮助很大,更加明白了ADC的设置。
用EPWM触发的例程就是ADC_SOC那个是可以正确触发ADC的,说明ADC正常。
我改为在每个中断中都加入了软件触发的语句,这样就正常了。
不过,还请高人给予指点一二:请问如何正确设置软件触发的连续采样,有没有可能就是软件触发后,通过ADCINT1直接触发SOC,进行连续采样的设置?
你的想法很好,正好Piccolo也可以这样设置。
方法就是使用你程序中用到的ADCINTSOCSELn寄存器,但上面的软件触发就不需要在中断里持续赋值了。
你可以在ADC_Config()先用软件进行一次赋值,触发第一次ADC采样,然后将你上面程序中ADC_Config()函数里的ADCINTSOCSEL1操作的两条语句放在ADC中断里,这样之后的ADC触发就都会以ADC中断来实现了。
首先谢谢以上两位的解答,我又做了一些实验,把结果拿出来分享,希望对各位有点帮助。
1.利用软件触发ADC,基本设置如程序里所示,但一开始并没有成功。
错误在于:没有在interrupt void adc_isr(void)中断程序中添加软件触发语句
EALLOW;
AdcRegs.ADCSOCFRC1.all = 0x03;
EDIS;
在中断中添加该语句后,ADC可以正常工作,并正确实现了软件触发的连续采样512个点的目的。
2.若要实现连续采样,可将连续采样模式打开
AdcRegs.INTSEL1N2.bit.INT1CONT = 0; //Disable ADCINT1 Continuous mode
将这一位置1,这样在中断中就不需要再添加软件触发语句就能实现软件触发后,通过ADCINT1
直接触发SOC,进行连续采样的功能。
3.关于“使用软件触发时将两个SOC一起设置”的问题,我做了一下实验,发现如果单独设置SOC0,
而将设置SOC1的语句注释掉,发现ADC并没有正常工作。
但是相反,将设置SOC0的语句注释掉,只保留SOC1的设置,发现ADC仍然可以是实现1,2中所述
的功能。可见,如果单独设置SOC0的软件触发连续采样方式,是有可能(可能是我一些设置问题)
造成ADC不能正常工作的。也有可能是28035一个独特方式吧,希望了解详情的各位给予解答。
再次对楼上两位的帮助,获益良多。BEST WISHES FOR YOU 2。