打印

TI Stellaris LM4F ADC指南

[复制链接]
6304|14
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主
TI_MCU|  楼主 | 2012-3-16 17:36 | 只看该作者 |只看大图 回帖奖励 |倒序浏览 |阅读模式
本帖最后由 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 InstrumentsStellaris LM4F上提供了模拟部分全新设计的ADC模块,提供了最高可到1MSPS12-bit高精度ADC,较之M3系列有不少变化。本文将从硬件功能、软件使用两个方面介绍ADC模块的使用。软件方面结合了TIStellarisWare驱动库,以避免繁琐复杂的寄存器操作,故硬件功能介绍时也尽量避免具体的寄存器。读者可以先阅读第一章了解ADC模块的工作方式及特点,再结合第二章的示例代码深入理解ADC的使用。

1.ADC硬件功能
Stellaris LM4F系列中,内置了12-bit的模/数转换模块(ADC),提供了以下特性:
    - 最高采样速率可达1MSPS
    - 支持单端及差分输入
    - 内置温度传感器
    - 64x硬件平均
    - 可编程采样序列控制器及相应深度的结果FIFO
    - 多触发源启动采样
    - 数字比较器
    - 支持DMA结果传输

本章中将对ADC的功能及特性进行介绍,希望读者能在读完这篇**后对LM4F ADC有初步了解。

1.1.ADC模块结构
如下图所示,M4中提供了212-bit /数转换模块(ADC0ADC1),这些模块共享相同的通道,不同的型号通道数量有所区别(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 LM4FADC的采样通过采样序列控制器(SampleSequencers)控制,可以采样多组数据后,一次性获得结果。在Stellaris中,即使只需采样一组数据,也需要使用Sequencer。如上图所示,启动测量需要触发(Trigger),由其它设备、外来触发源或内核产生。当转换完成或其它条件(用户配置)满足时,会产生响应的中断(Interrupt)或触发(Trigger)。中断用于通知内核,触发用于控制其它模块的动作(如关闭PWM输出)。使用ADC完成ADC采样需要进行如下步骤:


1.3.1. 采样序列控制器(Sample Sequencer)
1.1节可以看出,使用M4ADC的即是对Sequencer的设置和使用。配置完成后,Sequencer将自动控制ADC转换及保存数据。采用Sequencer + FIFO的好处是,可以在ADC完成一系列采样后,再读取全部结果,中间过程全部由硬件自动完成而无需消耗指令周期。

下图展示了Sequencer的工作原理,以ADC中的Sequencer0 (SS0)为例,SS0最多可以设置8组采样序列,且不一定填满8(可以停止在任意位置)Sequencer中存储的是ADC通道(0代表通道0),序列中采样通道允许重复。



如上图配置SS0后,启动SequencerADC会自动按设定顺序采集通道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系列支持2x4x8x16x32x以及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)使用GPIOPinTypeADCGPIO管脚配置为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~30的优先级最高,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中的ADC12位,所以读出的结果应该在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);


        // 使用数据
        // 用户代码…
        // 用户代码…
    }
}

相关帖子

沙发
u880| | 2012-3-21 23:45 | 只看该作者
好东西

使用特权

评论回复
板凳
huigoushang| | 2012-3-22 00:05 | 只看该作者
感谢分享

使用特权

评论回复
地板
G21372| | 2012-3-22 00:13 | 只看该作者
精简一下就好了

使用特权

评论回复
5
acer4736| | 2012-3-22 10:25 | 只看该作者
感谢分享

使用特权

评论回复
评分
参与人数 1威望 +1 收起 理由
Asiam21 + 1 赞一个!
6
ljy12344321| | 2014-6-22 11:38 | 只看该作者
非常感谢,正在找这个资料

使用特权

评论回复
7
朝阳之光| | 2014-6-22 12:31 | 只看该作者
支持

使用特权

评论回复
8
ws00262753| | 2014-7-7 20:04 | 只看该作者
非常感谢!
自己看了好久都不懂...

使用特权

评论回复
9
miniko| | 2014-10-24 22:27 | 只看该作者
MARK~!

使用特权

评论回复
10
会飞的狼_2058| | 2015-1-29 10:54 | 只看该作者
例程很好,非常感谢!怒赞

使用特权

评论回复
11
会飞的狼_2058| | 2015-5-20 14:56 | 只看该作者
没有添加ADC中断,貌似不对吧?

使用特权

评论回复
12
dirtwillfly| | 2015-5-20 15:08 | 只看该作者
会飞的狼_2058 发表于 2015-5-20 14:56
没有添加ADC中断,貌似不对吧?

用查询方式也可以的。这个例程貌似是单次采样

使用特权

评论回复
13
Thor9| | 2015-5-20 19:29 | 只看该作者
楼上都是大神,小弟来学习

使用特权

评论回复
14
FireRiver9| | 2015-5-20 20:53 | 只看该作者
学习了,顶起

使用特权

评论回复
15
会飞的狼_2058| | 2015-6-1 08:35 | 只看该作者
dirtwillfly 发表于 2015-5-20 15:08
用查询方式也可以的。这个例程貌似是单次采样

楼主正解,谢谢。

使用特权

评论回复
发新帖 我要提问
您需要登录后才可以回帖 登录 | 注册

本版积分规则

0

主题

420

帖子

7

粉丝