本帖最后由 TI_MCU 于 2012-3-16 17:52 编辑
最近没怎么上论坛,忽然想起还有篇很久前写成的**,发上来分享下:
TI Stellaris LM4F ADC指南
[V1.0]
[作者: Richard Ma]
[Email: mxschina@gmail.com]
TI Stellaris LM4F ADC指南.pdf
(637.37 KB)
=========================================================
Texas Instruments在Stellaris LM4F上提供了模拟部分全新设计的ADC模块,提供了最高可到1MSPS的12-bit高精度ADC,较之M3系列有不少变化。本文将从硬件功能、软件使用两个方面介绍ADC模块的使用。软件方面结合了TI的StellarisWare驱动库,以避免繁琐复杂的寄存器操作,故硬件功能介绍时也尽量避免具体的寄存器。读者可以先阅读第一章了解ADC模块的工作方式及特点,再结合第二章的示例代码深入理解ADC的使用。
1.ADC硬件功能
Stellaris LM4F系列中,内置了12-bit的模/数转换模块(ADC),提供了以下特性:
- 最高采样速率可达1MSPS
- 支持单端及差分输入
- 内置温度传感器
- 64x硬件平均
- 可编程采样序列控制器及相应深度的结果FIFO
- 多触发源启动采样
- 数字比较器
- 支持DMA结果传输
本章中将对ADC的功能及特性进行介绍,希望读者能在读完这篇**后对LM4F 中ADC有初步了解。
1.1.ADC模块结构
如下图所示,M4中提供了2个12-bit 模/数转换模块(ADC0和ADC1),这些模块共享相同的通道,不同的型号通道数量有所区别(如232系列有24个通道,231系列有12个通道)。除了这些通道以外,还有一个温度传感器,用于测量芯片内部温度以监视芯片状态,可以视作一路额外的通道。
使用ADC单元时需要注意,输入ADC模块的时钟应不低于16MHz。
1.2. ADC 转换单元及参考电压
TI Stellaris LM4F中的ADC使用了逐次逼近 (SAR) 型的ADC转换单元,在芯片内部没有提供参考源。根据器件手册,为不同的器件提供参考电压的方式不同,如上图所示,主要有两种。
如左边所示,其中一种(如LM4F231H5QR)不支持由外部提供参考电压,而使用VDDA作为参考电压。在使用这种类型的器件时,需要务必保证VDDA的稳定。
上图右边的另一类(如LM4F232H5QD)可以由外部的VREF+和VREF-管脚提供外部参考电压。
1.3. ADC 功能及使用
不同于传统单片机内ADC的采样-读取的方式,TI Stellaris LM4F中ADC的采样通过采样序列控制器(SampleSequencers)控制,可以采样多组数据后,一次性获得结果。在Stellaris中,即使只需采样一组数据,也需要使用Sequencer。如上图所示,启动测量需要触发(Trigger),由其它设备、外来触发源或内核产生。当转换完成或其它条件(用户配置)满足时,会产生响应的中断(Interrupt)或触发(Trigger)。中断用于通知内核,触发用于控制其它模块的动作(如关闭PWM输出)。使用ADC完成ADC采样需要进行如下步骤:
1.3.1. 采样序列控制器(Sample Sequencer)
从1.1节可以看出,使用M4中ADC的即是对Sequencer的设置和使用。配置完成后,Sequencer将自动控制ADC转换及保存数据。采用Sequencer + FIFO的好处是,可以在ADC完成一系列采样后,再读取全部结果,中间过程全部由硬件自动完成而无需消耗指令周期。
下图展示了Sequencer的工作原理,以ADC中的Sequencer0 (SS0)为例,SS0最多可以设置8组采样序列,且不一定填满8组(可以停止在任意位置)。Sequencer中存储的是ADC通道(如0代表通道0),序列中采样通道允许重复。
如上图配置SS0后,启动Sequencer,ADC会自动按设定顺序采集通道0 (CH0)、通道5 (CH5)、通道8
(CH8)……本例中,第5次采样(CH3)被定为采样序列的终止,当完成该次采样后,会自动停止,并根据配置通知处理器内核。
采样的结果会被自动存入采样结果缓存中。缓存采用FIFO进行存储,每一组序列(Sequencer)都有对应的FIFO,其深度等于该序列的最多序列组数,以存储本组序列的采样结果。采样结果可以在序列采样完成后,由内核从同一个寄存器中依次读出,也可以设置DMA模块自动传送到所需位置。转换完成时,若FIFO已满,新数据不会写入,但会溢出状态寄存器会被置位。
在TI Stellaris LM4F中,每个ADC模块包含了4组采样序列,每个采样序列的最多组数不同,FIFO的大小也各不相同,可以根据用户的需求灵活使用。这些序列及组数、FIFO深度的情况如下表所示。
在序列中,最大组数不可超过,但不一定充满。任意位置都可以设为序列的终点;同时也可以配置任意位置也触发中断。
同一个ADC模块中的多个序列允许同时启动,这时其优先级决定其工作的先后。优先级为0-3,可以由用户配置,但须保证每个Sequencer的优先级各不相同。
- Sequencer启动可以使用以下的触发源:
- 内核触发(默认)
- 模拟比较器单元(Analog Comparator)
- GPIO输入信号
- 通用定时器(Timer)
- PWM模块
- Sequencer自己(使用连续采样模式)
1.3.2.硬件平均单元
有时候,为了获得更加准确的结果,需要将多次采样的结果进行平均,Stellaris LM4F中提供了硬件平均单元来完成这一任务。硬件平均的原理是连续进行多次转换,通过硬件计算结果的平均值。计算完成后,结果会被放入结果FIFO作为一次采样的结果。目前,Stellaris LM4F系列支持2x、4x、8x、16x、32x以及64x硬件平均。
硬件平均会降低输出结果的最高速率,若使用8x硬件平均(即使用8个结果进行平均),当设置ADC的采样速率为1MSPS时,则结果的最高输出速率为125KSPS(1M / 8)。
2.ADC驱动及代码示例
2.1.ADC驱动库使用
使用ADC需要通过调用StellarisWare驱动库进行如下步骤:
1)通过SysCtlPeripheralEnable使能ADC模块及使用的通道所在管脚。示例代码:
SysCtlPeripheralEnable(SYSCTL_PERIPH_ADC0);
SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOE);
2)使用GPIOPinTypeADC将GPIO管脚配置为ADC功能。示例代码:
GPIOPinTypeADC(GPIO_PORTE_BASE,GPIO_PIN_5 | GPIO_PIN_6);
3)配置启动采样的信号源,使用ADCSequenceConfigure。示例代码:
ADCSequenceConfigure(ADC0_BASE, 0,ADC_TRIGGER_PROCESSOR, 0);
参数中第一个为ADC的基址;第二个为使用的采样序列号,可以为0~3;第三个是信号源,可以是如下值:
ADC_TRIGGER_PROCESSOR – 程序中调用ADCProcessorTrigger函数启动
ADC_TRIGGER_COMP0 – 通过比较器0启动
ADC_TRIGGER_COMP1 – 通过比较器1启动
ADC_TRIGGER_COMP2 – 通过比较器2启动
ADC_TRIGGER_EXTERNAL – 通过GPIO引脚外部输入信号启动
ADC_TRIGGER_TIMER – 通过Timer启动
ADC_TRIGGER_PWM0 – 通过PWM0模块启动
ADC_TRIGGER_PWM1 – 通过PWM1模块启动
ADC_TRIGGER_PWM2 – 通过PWM2模块启动
ADC_TRIGGER_PWM3 – 通过PWM3模块启动
ADC_TRIGGER_ALWAYS – 一直反复启动
第四个参数为优先级,可以为0~3,0的优先级最高,3最低。当使用多个序列时,优先级不可重复。
4)通过ADCSequenceStepConfigure配置每一步序列。使用时需要配置如下参数:
ADCSequenceStepConfigure(ADC0_BASE,序列器编号, 步数, 采样通道配置);
采样通道可以选择从ADC_CTL_CH0直到ADC_CTL_CHx之一 (x为最大通道数减一)。同时也可以配置为ADC_CTL_TS采集温度。还可以附加如下参数:
ADC_CTL_IE – 完成该次采样时,触发中断
ADC_CTL_END – 本次采样为本序列终点
ADC_CTL_CMP0 ~ ADC_CTL_CMP7中一个,将结果送入比较器0~7
使用示例:
ADCSequenceStepConfigure(ADC0_BASE,1, 1, ADC_CTL_CH9);
ADCSequenceStepConfigure(ADC0_BASE, 1, 2,ADC_CTL_CH21 | ADC_CTL_IE | ADC_CTL_END)
5)使能采样序列,使用ADCSequenceEnable。示例代码:
ADCSequenceEnable(ADC0_BASE, 1);
代码中数字1表示使用采样序列1。
6)当完成上面配置后,ADC就准备好启动采样了。根据配置不同,当不同的触发源触发后,ADC采样序列控制器会自动启动,控制ADC完成采样。如果配置为直接由处理器内核启动,可以调用ADCProcessorTrigger启动采样。
7)当采样完成,若配置了中断,会进入中断处理函数。同时也可以通过查询ADC中断寄存器状态,来判断转换是否完成。
8)转换完成后,可以使用ADCSequenceDataGet读取数据。该函数可以一次性将结果填入数组,但须保证所给的数组的空间足够大。如转换了5组结果在FIFO中,所给数组空间应大于5,否则可能导致数组溢出。示例代码:
unsigned long ADCResult[8];
ADCSequenceDataGet(ADC0_BASE, 0,ADCResult);
ADCSequenceDataGet中的数字0表示读取采样序列控制器序列0中存储的结果。读取出结果的个数等于当前FIFO中存储的结果的个数。
9)M4中的ADC为12位,所以读出的结果应该在0~4095之间。
2.2.示例代码
如下为ADC使用的示例代码,该代码在LM4F232H5QD上调试通过。
#include "inc/hw_types.h"
#include "inc/hw_memmap.h"
#include "driverlib/adc.h"
#include "driverlib/sysctl.h"
#include "driverlib/pin_map.h"
#include "driverlib/gpio.h"
int main(void)
{
// 存储结果的数组
unsigned longulADC0_Value[3];
// 配置系统时钟为50MHz
SysCtlClockSet(SYSCTL_SYSDIV_4| SYSCTL_USE_PLL | SYSCTL_XTAL_16MHZ | SYSCTL_OSC_MAIN);
// 使能ADC0.
SysCtlPeripheralEnable(SYSCTL_PERIPH_ADC0);
// 使能ADC0中使用到的通道所在管脚对应的GPIO
SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOE);
// 将通道所在管脚配置为GPIO功能
GPIOPinTypeADC(GPIO_PORTE_BASE,GPIO_PIN_4 | GPIO_PIN_5 | GPIO_PIN_6);
// 配置采样序列1的启动条件为处理器触发
ADCSequenceConfigure(ADC0_BASE,1, ADC_TRIGGER_PROCESSOR, 0);
// 配置采样序列1的采样步骤:
// - 第0步:采通道8
// - 第1步:采通道9
// - 第2步:采通道21,并在采样结束后停止,置中断寄存器标志位
ADCSequenceStepConfigure(ADC0_BASE,1, 0, ADC_CTL_CH8);
ADCSequenceStepConfigure(ADC0_BASE,1, 1, ADC_CTL_CH9);
ADCSequenceStepConfigure(ADC0_BASE,1, 2, ADC_CTL_CH21 | ADC_CTL_IE | ADC_CTL_END);
// 使能采样序列1
ADCSequenceEnable(ADC0_BASE,1);
// 清除采样序列1的中断标志位以方便之后查询
ADCIntClear(ADC0_BASE,1);
while(1)
{
// 启动采样序列1的转换
ADCProcessorTrigger(ADC0_BASE,1);
// 等待采样序列1转换完成
while(!ADCIntStatus(ADC0_BASE,1, false));
// 读取序列1 FIFO中的采样结果
ADCSequenceDataGet(ADC0_BASE,1, ulADC0_Value);
// 使用数据
// 用户代码…
// 用户代码…
}
}
|