ZHCACE4A March 2023 – August 2024 TMS320F2800132 , TMS320F2800133 , TMS320F2800135 , TMS320F2800137 , TMS320F2800152-Q1 , TMS320F2800153-Q1 , TMS320F2800154-Q1 , TMS320F2800155 , TMS320F2800155-Q1 , TMS320F2800156-Q1 , TMS320F2800157 , TMS320F2800157-Q1 , TMS320F280021 , TMS320F280021-Q1 , TMS320F280023 , TMS320F280023-Q1 , TMS320F280023C , TMS320F280025 , TMS320F280025-Q1 , TMS320F280025C , TMS320F280025C-Q1 , TMS320F280033 , TMS320F280034 , TMS320F280034-Q1 , TMS320F280036-Q1 , TMS320F280036C-Q1 , TMS320F280037 , TMS320F280037-Q1 , TMS320F280037C , TMS320F280037C-Q1 , TMS320F280038-Q1 , TMS320F280038C-Q1 , TMS320F280039 , TMS320F280039-Q1 , TMS320F280039C , TMS320F280039C-Q1 , TMS320F28P650DK
C2000™ 实时微控制器提供模数转换器 (ADC),广泛应用于从控制电机到读取传感器的众多应用。有时客户设计要求的分辨率会高于所选器件的 ADC 分辨率。该应用手册介绍了如何通过加入过采样方式来提高 ADC 分辨率,使其超过当前可实现的位数。这有助于使用分辨率较低的 ADC 对信号进行过采样并获得分辨率较高的结果,从而降低系统构建的成本。提供了详细说明,并已在 TMDSCNCD28P65X 器件上测试了软件过采样和硬件过采样以及器件初始化。
C2000™is a TM ofTI corporate name.
Other TMs
模数转换器 (ADC) 模块具有离散位数,可用于对模拟信号或分辨率进行数字化。理想的 ADC 会准确地将数字化信号复制到指定的分辨率范围内。然而,在现实世界中,各种电气缺陷和噪声因素会导致实现的信号分辨率低于指定值。当考虑这些缺陷时,实现的信号分辨率被称为有效位数(即 ENOB)。
ADC 信号过采样是一种技术,能够克服这些固有缺陷并实现比器件基线标称值更高的 ENOB。本应用报告讨论了过采样背后的用途,并提供了过采样示例的以下详细信息:理论、硬件和软件设置以及测量结果。本应用手册中提供的示例使用 TMDSCNCD28P65X 器件和 12 位 ADC 进行软件过采样和硬件过采样。
过采样的目标是通过减少在信号中观察到的噪声来增加 ENOB。过采样会对同一输入信号执行多次转换,并累加数字值以获得高于 ADC 固有 ENOB 的 ENOB。结果的精度会提高,具体取决于发生了多少过采样。通过测量变化的输入信号来确定信号的主要频率,可以证明这种精度。理论上,过采样的可能量限制为用于存储转换结果的变量的数据宽度。例如,一个 16 位结果会限制您在 12 位 ADC 上进行 16 倍过采样,最大累计值为 65535。
除了数据大小限制外,过采样量还受 ADC 吞吐量与输入信号基频之间关系的限制,因为每秒过采样转换数不能低于奈奎斯特速率。这还意味着过采样因子受实现系统性能要求所需的控制环路频率的限制。
出现大小限制的原因是过采样会累积结果,这必然需要比原始结果更多的存储器,因为加法可能会溢出。不对累加的值求平均值,因为这会有效地消除所获得的额外精度。因此,平均值计算可保持存储结果的大小和更低的噪声,但这不会显著影响观察到的结果 ENOB。
累积过采样可改善所获得的最终值中的降噪,但如果有显著的噪声影响信号,ENOB 不会增加太多。有几个电路板布局布线指南,如果遵循这些指南,则有助于更大限度地减少 ADC 转换模拟信号中的噪声源。其中包括:
有关 C2000 ADC 良好硬件设计的详细信息,请参阅节 4。
本文档使用快速傅里叶变换 (FFT) 来处理存储在存储器中的过采样 ADC 结果。FFT 图提供了信号噪声和谐波失真的视图,这些失真会影响观察到的主要频率,从而减小 ENOB。这些值通过 FFT 数据进行量化,并用于计算近似的 ENOB 值。为了进行测试,使用从 RAM 导出的 ADC 数据计算 FFT。对 ADC 结果执行 FFT 之前,需要对存储在存储器中的数据进行窗口化,避免在信号中产生伪影。这是因为起始点和结束点并不总是保持一致以形成完整的波形。本应用手册中使用的窗口化函数是 7 项 Blackman-Harris 函数。FPU DSP 库还能够使用窗口操作对存储器中的数据执行快速傅里叶变换。可用的不同窗口化函数可在 SysConfig 中的 FFT 模块中查看,也可在目录 C2000Ware_X_XX_XX_XX\libraries\dsp\FPU\c28\include\fpu32 中查看,文件标为 fpu_fft_<name>.h。
信号中存在的噪声幅度可使用信噪比 (SNR) 表示,而信号中观察到的谐波可使用
本应用手册中的示例使用带有 driverlib 的 SysConfig 来配置 ADC、ePWM 和其他外设。在程序代码内,设置 ADC 来更大限度地减少开销,从而在各次转换之间留出更多时间来执行控制循环。对于本应用手册中使用的示例,SOC 配置为具有循环优先级的突发模式,以便在过采样时一起触发 SOC 并进行累加,而不会丢失任何值。中断设置为在最后一个 SOC(用于 F28003x 的 SOC15)到达转换结束时触发。中断会运行相应的 ISR,该 ISR 会存储 ADC 结果,如果启用了过采样,则累加多个 SOC 结果。
ePWM 会触发此处的 SOC,但也可以使用软件触发器和 CPU 计时器触发器。选择触发周期时应小心,使 SOC 采样保持一致,并在控制循环其余部分保持适当的转换时间。一旦突发序列中的最后一个 SOC 发出转换结束信号,ISR 便会执行控制循环。在此示例中,控制循环包含一个简单的累加函数,用于过采样和存储结果。应避免对值求平均,因为这会丢弃结果较低位中包含的信息,进而有效降低测量精度。在触发下一次突发之前,最终结果存储在存储器中。
以下代码是使用突发 ISR 设置进行基线采样的示例:
__interrupt void adcA1ISR(void)
{
//
// Clear the interrupt flag
//
ADC_clearInterruptStatus(ADCA_BASE, ADC_INT_NUMBER1);
//
// 1X Oversampling
//
lv_results[nloops++] = ADC_readResult(myADC0_RESULT_BASE, ADC_SOC_NUMBER0);
//
// Check if overflow has occurred
//
if(true == ADC_getInterruptOverflowStatus(ADCA_BASE, ADC_INT_NUMBER1))
{
ADC_clearInterruptOverflowStatus(ADCA_BASE, ADC_INT_NUMBER1);
ADC_clearInterruptStatus(ADCA_BASE, ADC_INT_NUMBER1);
}
//
// Check if all results are stored
//
if(nloops >= numBins)
{
//
// Disable ADC interrupt
//
ADC_disableInterrupt(myADC0_BASE, ADC_INT_NUMBER1);
ESTOP0;
}
//
// Acknowledge the interrupt
//
Interrupt_clearACKGroup(INTERRUPT_ACK_GROUP1);
}
使用 ISR 对信号进行 8 倍过采样的示例如下:
__interrupt void adcA1ISR(void)
{
//
// Clear the interrupt flag
//
ADC_clearInterruptStatus(ADCA_BASE, ADC_INT_NUMBER1);
//
// Accumulate 8 ADC results to oversample 8X
//
lv_results[nloops++] = (ADC_readResult(myADC0_RESULT_BASE, ADC_SOC_NUMBER0) + ADC_readResult(myADC0_RESULT_BASE, ADC_SOC_NUMBER1) +
ADC_readResult(myADC0_RESULT_BASE, ADC_SOC_NUMBER2) + ADC_readResult(myADC0_RESULT_BASE, ADC_SOC_NUMBER3) +
ADC_readResult(myADC0_RESULT_BASE, ADC_SOC_NUMBER4) + ADC_readResult(myADC0_RESULT_BASE, ADC_SOC_NUMBER5) +
ADC_readResult(myADC0_RESULT_BASE, ADC_SOC_NUMBER6) + ADC_readResult(myADC0_RESULT_BASE, ADC_SOC_NUMBER7));
//
// Check if overflow has occurred
//
if(true == ADC_getInterruptOverflowStatus(ADCA_BASE, ADC_INT_NUMBER1))
{
ADC_clearInterruptOverflowStatus(ADCA_BASE, ADC_INT_NUMBER1);
ADC_clearInterruptStatus(ADCA_BASE, ADC_INT_NUMBER1);
}
//
// Acknowledge the interrupt
//
Interrupt_cl