Other Parts Discussed in Thread: C2000WARE
首先对Ti工程师,Ti公司致以诚挚敬意!
回到问题本身,我在研究Ti提供的C2000WARE F2837Xd 库函数驱动例程adc_ex5_soc_continuous.c中,有一些体会和疑虑。
- (问题1):首先,我成功测出来了相当不错的波形,这是一个5次顺序谐波,失真度是40%,基频10kHz。
注:在测量中我对转换缓存容量进行了扩大(从256到1024)
#define RESULTS_BUFFER_SIZE 1024 //buffer for storing conversion results
图示中的三个波形,第一个和最后一个都相当好看,因此我认为实验成功。但是为什么中间这个会出现半段的波动呢?我反复测定了多次,一直如此。大约每3个波形会有一个出现问题。(我用的是杜邦线连接探头)
我的连线图如下
我对ADC采样的转化方法有一些理解问题。我说一下我的理解,如果不对请工程师指正。
首先经过一系列初始化( Device_init();Device_initGPIO;Interrupt_initModule;Interrupt_initVectorTable)之后,我们开始adc配置:configureADC(ADCA_BASE);配置了ADC时钟并给ADCA供电(ADC时钟不影响采样频率);
其次,我们进行ADCA 通道0 的连续采样配置:setupADCContinuous(ADCA_BASE, ADC_CH_ADCIN0);
在这个函数内部我们首先配置了12位采样窗口长度;然后把ADC_SOC_NUMBER0到ADC_SOC_NUMBER15这16个SOC/EOC标签,以软件触发(ADC_TRIGGER_SW_ONLY)的形式链接到ADC_CH_ADCIN0上,并规范了采样窗口。 这个过程通过ADC_setupSOC函数实现。
随后我们进行SOC的中断配置,在这里,我插一段我对SOC的理解:
SOC理解:


// Configure interrupt triggers
//
ADC_setInterruptSource(adcBase, ADC_INT_NUMBER1, ADC_SOC_NUMBER6);
ADC_setInterruptSource(adcBase, ADC_INT_NUMBER2, ADC_SOC_NUMBER14);
ADC_setInterruptSource(adcBase, ADC_INT_NUMBER3, ADC_SOC_NUMBER7);
ADC_setInterruptSource(adcBase, ADC_INT_NUMBER4, ADC_SOC_NUMBER15);
(问题3):为什么是ADC_SOC_NUMBER6,14,7,15呢?为什么不是其他的SOCnumber?然后ADC_INT_NUMBER3,4的作用又是什么?
我带着问题继续研究代码,现在回到主函数里面,在对结果存储数组初始化(置零)并用EINT,ERTM开启中断之后,我看到以下代码:
使能中断,这个很好理解,但是到这里我还是不知道ADCINT3,4的作用,让我们继续。
//
// Enable ADC interrupts
//
ADC_enableInterrupt(ADCA_BASE, ADC_INT_NUMBER1);
ADC_enableInterrupt(ADCA_BASE, ADC_INT_NUMBER2);
ADC_enableInterrupt(ADCA_BASE, ADC_INT_NUMBER3);
ADC_enableInterrupt(ADCA_BASE, ADC_INT_NUMBER4);
(问题4):清除标志位,下面这段代码(HWREGH(ADCA_BASE + ADC_O_INTFLGCLR) = 0x000F)应该就是库函数ADC_clearInterruptStatus的作用,然后一次性清理完成4个ADCINT,提高效率
//
// Clear all interrupts flags(INT1-4)
//
HWREGH(ADCA_BASE + ADC_O_INTFLGCLR) = 0x000F;
初始化存储数组指示符index,便于存储
//
// Initialize results index
//
resultsIndex = 0;
(问题5):
软件强制触发SOC0到SOC7,我想请问,这里已经开始采集了吗,这段代码改怎么理解?
值得注意的是,下面的代码(HWREGH(ADCA_BASE + ADC_O_SOCFRC1) = 0x00FF;)应该是库函数ADC_forceMultipleSOC,把SOC0到7一口气配置完成,也是提高效率,我应该没理解错吧?
//
// Software force start SOC0 to SOC7
//
HWREGH(ADCA_BASE + ADC_O_SOCFRC1) = 0x00FF;
然后我们继续看代码:我的理解是,当这个存储数组没装满,我们继续存,
当第一系列的8个转换完成,ADC_INT_NUMBER3的标志位会置1,也就是true,此时,ADC_getInterruptStatus(ADCA_BASE, ADC_INT_NUMBER3)读到的值是true,跳出while,执行之后的语句。
我的疑问是,为啥当第一系列的8个转换完成时,ADC_INT_NUMBER3的标志位会置1呢?
到这里,我大约明白了ADCINT3,4的作用。但也说不清楚。
while(resultsIndex < RESULTS_BUFFER_SIZE)
{
//
// Wait for first set of 8 conversions to complete
while(false == ADC_getInterruptStatus(ADCA_BASE, ADC_INT_NUMBER3));
//
// Clear the interrupt flag
// 清除中断标志
ADC_clearInterruptStatus(ADCA_BASE, ADC_INT_NUMBER3);
(问题6):
下面一段代码我觉得理解没问题,但我仍然不知道第二个系列的8个转换是谁,怎么,或者说基于什么条件触发,才开始转换的呢?
其实第一个系列的8个转换触发条件我也不是很确定,是HWREGH(ADCA_BASE + ADC_O_SOCFRC1) = 0x00FF实现的吗?
且下面这段代码也写了是SOC/EOC6,链接到ADCINT1触发,但是具体如何触发呢?触发会不会改变ADCINT1的中断标志位(供给ADC_getInterruptStatus)读取呢?
//
// Save results for first 8 conversions
// 保存前8次转换的结果
// Note that during this time, the second 8 conversions have
// already been triggered by EOC6->ADCIN1 and will be actively
// converting while first 8 results are being saved
// 注意,在保存(把前八次转换的结果写入寄存器)的过程中,第二系列的8个转换
// 已经开始触发了,且开始转换(通过SOC/EOC 6,对应的是ADCIN1)。
// 这里的存储方式是:实际上是一个ADCARESULT_BASE 对应ADCA的结果,加上偏移
// 量,偏移量就是SOC的number编号,实现唯一性
adcAResults[resultsIndex++] = ADC_readResult(ADCARESULT_BASE,
ADC_SOC_NUMBER0);
adcAResults[resultsIndex++] = ADC_readResult(ADCARESULT_BASE,
ADC_SOC_NUMBER1);
adcAResults[resultsIndex++] = ADC_readResult(ADCARESULT_BASE,
ADC_SOC_NUMBER2);
adcAResults[resultsIndex++] = ADC_readResult(ADCARESULT_BASE,
ADC_SOC_NUMBER3);
adcAResults[resultsIndex++] = ADC_readResult(ADCARESULT_BASE,
ADC_SOC_NUMBER4);
adcAResults[resultsIndex++] = ADC_readResult(ADCARESULT_BASE,
ADC_SOC_NUMBER5);
adcAResults[resultsIndex++] = ADC_readResult(ADCARESULT_BASE,
ADC_SOC_NUMBER6);
adcAResults[resultsIndex++] = ADC_readResult(ADCARESULT_BASE,
ADC_SOC_NUMBER7);
接下来的代码跟上面类似,我的疑惑也是类似的,为什么是ADCINT4的中断标志位置1?
//
// Wait for the second set of 8 conversions to complete
// 等待第二组8个转换完成
// 第二组的8个通道值转换完成后,ADC_INT_NUMBER4的值会置1,此时跳出循环
// 所以ADC_INT_NUMBER4标志着第二组的8个通道是否转换完成。
while(false == ADC_getInterruptStatus(ADCA_BASE, ADC_INT_NUMBER4));
//
// Clear the interrupt flag
//
ADC_clearInterruptStatus(ADCA_BASE, ADC_INT_NUMBER4);
//
// Save results for second 8 conversions
//
// Note that during this time, the first 8 conversions have
// already been triggered by EOC14->ADCIN2 and will be actively
// converting while second 8 results are being saved
//
adcAResults[resultsIndex++] = ADC_readResult(ADCARESULT_BASE,
ADC_SOC_NUMBER8);
adcAResults[resultsIndex++] = ADC_readResult(ADCARESULT_BASE,
ADC_SOC_NUMBER9);
adcAResults[resultsIndex++] = ADC_readResult(ADCARESULT_BASE,
ADC_SOC_NUMBER10);
adcAResults[resultsIndex++] = ADC_readResult(ADCARESULT_BASE,
ADC_SOC_NUMBER11);
adcAResults[resultsIndex++] = ADC_readResult(ADCARESULT_BASE,
ADC_SOC_NUMBER12);
adcAResults[resultsIndex++] = ADC_readResult(ADCARESULT_BASE,
ADC_SOC_NUMBER13);
adcAResults[resultsIndex++] = ADC_readResult(ADCARESULT_BASE,
ADC_SOC_NUMBER14);
adcAResults[resultsIndex++] = ADC_readResult(ADCARESULT_BASE,
ADC_SOC_NUMBER15);
}
统观全局
(问题7):
ADCINT3,ADCINT4中断标志位置1是通过前面的
//
// Configure interrupt triggers
//
ADC_setInterruptSource(adcBase, ADC_INT_NUMBER1, ADC_SOC_NUMBER6);
ADC_setInterruptSource(adcBase, ADC_INT_NUMBER2, ADC_SOC_NUMBER14);
ADC_setInterruptSource(adcBase, ADC_INT_NUMBER3, ADC_SOC_NUMBER7);
ADC_setInterruptSource(adcBase, ADC_INT_NUMBER4, ADC_SOC_NUMBER15);
实现的吗?
(问题8):
最后,关闭相关的中断,采样结束。我计算了一下,100kHz的输入波形,每个周期可以采集20个点左右,似乎最高采样频率在2MHz左右?如果使用DMA技术,能提高这个采样频率吗?或者说,到底什么地方,是ADC转换,还是写入寄存器,会较大程度占用CPU资源呢?
之后准备研究ex6,ADC与DMA技术的结合,特别希望Ti的工程师帮我解决ADC连续采样的这些问题。作为本科生,我觉得我的理解能力有所不足,还望工程师先生,不吝赐教。
祝好!