概述
Luminary Micro在Stellaris系列微控制器的部分产品中提供了模数转换器(ADC)模块。ADC的硬件分辨率为10位,但由于噪音和其它使精度变小的因素的影响,实际的精度小于10位。本应用文档提供了一个基于软件的过采样技术,从而使转换结果的有效位数(ENOB)得到了改善。文档中描述了对输入信号执行过采样的方法,以及在精度和整个系统性能上的影响。
过采样
过采样,顾名思义就是从输入信号中采集额外的转换数据。模拟信号采样的标准约定指出:采样频率fS至少是输入信号的最高频率成分fH的两倍。这被称作奈奎斯特采样定理(Nyquist Theorem)(见等式1)。
等式1 奈奎斯特采样定理:
fS=2fH
只要所选的采样频率高于fS就被看作是过采样。当过采样与平均技术相结合时,可改善ENOB。这是可以实现的,因为在将过采样的结果进行平均的同时也将量化噪音进行了平均,这样就提高了信噪比(SNR),信噪比的提高会在ENOB上产生一个直接的影响,从而改善ENOB。
精度上每提高一位,必须对信号进行4倍的过采样,即过采样频率fOS与采样频率fS的关系如等式2所示:
等式2 过采样频率:
fOS=4X*fS
x为ENOB上需改进的位数(例如,需要改进2位,则x=2)。
平均
平均操作可看作是输入信号上的一个低通滤波器,当采样数据宽度(simple size)增加时滤波器的通带变窄。有两种方法可对转换结果进行平均:常规平均和滑动平均(rolling average)。
常规平均
对输入信号进行n次采样,将采样值相加并将结果除以n,这即是常规平均。当在过采样方案中使用常规平均时,使用该技术之后,用于计算平均值的采样数据被丢弃。每次应用程序需要一个新的转换结果时,重复该处理。
在应用中,常规平均方案可理想地用于采样频率与ADC的采样率相比较小的情况。
要点:当在常规平均方案中执行n倍过采样时,有效的ADC采样率将按照相同的因子降低。例如,在对输入信号进行4倍过采样时,最大的有效ADC采样率降低为原来的1/4,即采样率为250K/s的ADC有效地变为62.5K/s的ADC。
解决方案使用常规平均对输入源进行4倍过采样。在该例中,应用要求在每个t阶段(t0、t1、t2等等)准备好一个新值(平均操作完成)。
在使用平均技术时,因为计算后的转换结果要与上面的n个采样点对应,因此稍微有一点延迟。延迟时间使用等式3中的公式来计算:
等式3 平均后的采样延迟:
tdelay=(tSn-tS0)/2+tprocess
tS0为进行平均时第一个采样点出现的时间,tSn为最后一个采样点出现的时间。中断处理程序处理采样数据所需的时间,并被计算为供应用使用的平均tproces也被分解到等式中。
滑动平均
滑动平均在平均计算中使用存放n个最近采样值的采样缓冲区,允许ADC在其最大采样率时采样(ADC采样率并不象常规平均那样减小为原来的1/n),这样它可理想地用于要求过采样和更高采样率的应用中。在未知状态中,采样缓冲区能够用有效的采样数据预先填充(通过捕获第一个“实际”数据点之前的n-1个采样点),也可保持为空,由应用来决定。不预先填充缓冲区的危害是前面的n-1个采样点包含无效的数据,并在滑动平均计算中产生不利的影响。如果这些影响可被应用所接受,并且如果软件能够解决前面的n-1个偏移的采样点的可能性,则可去除缓冲区填充操作。
显示了采用滑动平均的过采样实例。图中显示的情况为:输入信号进行4倍过采样,即采样缓冲区使用4个最近的采样值来计算平均值。在该例中,应用要求在每个t时刻有一个新的采样值。在t0时刻计算第一个过采样的结果之前,采样缓冲区收集了3个采样值,这样提供给应用的第一个数据有效。
在使用滑动平均时,等式3中计算得来的采样延迟也同样适用。要点:因为必须在每次中断过程中执行采样缓冲区处理,因此使用滑动平均增加了额外的处理开销。
实现
Luminary Micro在ADC中使用采样定序器(sample sequencer)结构,它使用一次触发就可采集到高达17个不同的采样值(来自任意的模拟通道),这样过采样的实现就变得非常简单。而通过向应用提供在任意给定的时刻对多个通道进行过采样的方法,使得软件的实现也具有极大的灵活性。
下面将给出使用Stellaris微控制器的多种过采样实现。有许多方法是将采样定序器的配置、ADC触发和中断相结合来工作的。这里所举的例子焦点都集中在最常使用的技术上。
所有的实例代码都使用Stellaris系统驱动库的ADC函数。驱动库和本文档中显示的软件实例的源代码可从Luminary Micro网站:http://www.luminarymicro.com中获得。
使用驱动库函数的8倍过采样
Stellaris驱动库具有内置的允许进行高达8倍过采样的函数。该级别的过采样能够使ENOB改进大约1.4位,因此在大多数应用中已足够了。
使用驱动库的过采样函数是对输入信号进行过采样的最简单的方法。配置“典型”ADC转换和过采样转换的主要不同在于函数调用。过采样函数有一个ADCSoftwareOversample前缀,很容易从标准ADC函数中识别出。
一旦确定好ADC转换处理的参数(采样频率、触发源、通道、等等),写代码是非常简单的。举例:例1中的代码段即为建立一个8倍过采样的10ms周期转换(由定时器触发)的代码。
代码段1.a ADC配置-驱动库函数
//
// 初始化ADC,使用定序器0对通道1进行8x过采样
// 定序器将被其中一个通用定时器触发
//
ADCSequenceConfigure(ADC_BASE, 0, ADC_TRIGGER_TIMER, 0);
ADCSoftwareOversampleConfigure(ADC_BASE, 0, 8);
ADCSoftwareOversampleStepConfigure(ADC_BASE, 0, 0, (ADC_CTL_CH1
| ADC_CTL_IE | ADC_CTL_END));
//
// 初始化定时器0,每隔10ms触发一次ADC转换
//
TimerConfigure(TIMER0_BASE, TIMER_CFG_32_BIT_PER);
TimerLoadSet(TIMER0_BASE, TIMER_A, SysCtlClockGet() / 100);
TimerControlTrigger(TIMER0_BASE, TIMER_A, true);
代码段1.a的ADC配置表示在采样完成时产生一个中断,这样就必须具有中断处理程序(见代码段1.b)。驱动库的过采样函数自动将采样的数据进行平均,因此,中断处理函数相对来说也是很基础的。但要记住:要将每次中断中计算的平均值和计算的开销提供给中断处理程序。
代码段1.b ADC中断处理程序
void
ADCIntHandler(void)
{
long lStatus;
//
// 清除ADC中断
//
ADCIntClear(ADC_BASE, 0);
//
// 获得ADC的平均数据
//
lStatus = ADCSoftwareOversampleDataGet(ADC_BASE, 0, g_ulAverage);
//
// 占位符,供ADC处理数据
//
}
在将配置步骤和中断处理程序放在适当位置后,启动转换处理。定时器打开(开始计数)之前,ADC定序器和中断必须使能(见代码段1.c)。
代码段1.c 使能ADC和中断
//
// 使能ADC定序器0及其中断 (在ADC和NVIC中)
//
ADCSequenceEnable(ADC_BASE, 0);
ADCIntEnable(ADC_BASE, 0);
IntEnable(INT_ADC0);
//
//使能定时器并启动转换处理
//
TimerEnable(TIMER0_BASE, TIMER_A);
使用多个定序器或一个定时器实现大于8倍的过采样
驱动库的过采样函数最大只能进行8倍过采样(根据采样定序器的硬件限制),因此需要更大过采样因子的应用必须使用其它的实现。本小节将描述如何使用下面的两种方法:在过采样频率下运行的多个采样定序器和一个定时器来解决这个问题。
例2:使用多个采样定序器的16x过采样
采样定序器的灵活性允许对其进行多种配置。将采样定序器0-2累积起来可获得16个采样(8+4+4),因此使用采样定序器0-2可实现16倍过采样。为使该级别的过采样能够工作,定序器中的所有阶段必须设置为对相同的模拟输入进行采样,这意味着丢弃了使用一个定序器采样多个输入的功能。
代码段2.a使用定序器0-2配置一个10ms的周期转换。使用一个定时器触发就可启动所有3个定序器的采样操作,而无需复杂的触发配置。为获得所需的结果,要对采样定序器的优先级进行配置,这样,采样定序器2的优先级最低(即它最后采样),并且在采样定序器2的最后一步之后,配置为发出一个“转换结束”中断。