本帖最后由 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, 下载次数: 218)
2012-3-16 17:36 上传
点击文件名下载附件
=========================================================
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);
- // 使用数据
- // 用户代码…
- // 用户代码…
- }
- }
复制代码
楼主正解,谢谢。
一周热门 更多>