ADC模数转换器
LPC824芯片内含有12路12位逐次逼近型的ADC,分别复用在PIO0的一些引脚上,它们具有以下特性。
(1)12位逐次逼近型模数转换器。
(2)输入在12个引脚中多路复用。
(3)两个可配置转换序列具有独立的触发。
(4)可选自动阈值上/下限比较和过零检测。
(5)掉电模式和低功耗工作模式。
(6)测量范围:VREFN至VREFP(3 V典型值;不超过VDDA电压电平)。
(7)12位转换速率高达1.2 MSPS。
(8)用于单个或多个输入的突发转换模式。
(9)DMA支持。
(10)硬件校准模式。
下图是ADC模块的功能框图。

LPC824的ADC模块一共可以支持12路模拟信号输入,但默认并没有把这些输入端与外部引脚连接上,需要通过设置PINENABLE0寄存器(详见“开关矩阵SWM”部分)来使能ADC外部引脚,具体如下表所示。

注意,必须通过开关矩阵寄存器选择ADC功能,以便监控引脚上得到的精确电压读数。此外,连接到ADC的引脚,在其IOCON寄存器中的MODE位,要禁用上拉和下拉电阻。对于用作ADC输入的引脚而言,不可能选择数字功能的引脚而得到有效ADC读数。只要该引脚选择了数字功能,内部电路就会将ADC硬件与相关引脚断开连接。除此以外,LPC824的ADC还有两路外部触发输入选择(ADC_PINTRIG0和ADC_PINTRIG1),这两路触发信号可以通过设置PINASSIGN10和PINASSIGN11寄存器连接到任意的GPIO引脚。
ADC模块所涉及到的寄存器一共有25个,具体如下表所示。

在MDK环境中,针对以上ADC寄存器,定义了如下的结构体。
typedef struct {
__IO uint32_t CTRL;
__I uint32_t RESERVED0;
__IO uint32_t SEQA_CTRL;
__IO uint32_t SEQB_CTRL;
__IO uint32_t SEQA_GDAT;
__IO uint32_t SEQB_GDAT;
__I uint32_t RESERVED1[2];
__I uint32_t DAT0;
__I uint32_t DAT1;
__I uint32_t DAT2;
__I uint32_t DAT3;
__I uint32_t DAT4;
__I uint32_t DAT5;
__I uint32_t DAT6;
__I uint32_t DAT7;
__I uint32_t DAT8;
__I uint32_t DAT9;
__I uint32_t DAT10;
__I uint32_t DAT11;
__IO uint32_t THR0_LOW;
__IO uint32_t THR1_LOW;
__IO uint32_t THR0_HIGH;
__IO uint32_t THR1_HIGH;
__IO uint32_t CHAN_THRSEL;
__IO uint32_t INTEN;
__IO uint32_t FLAGS;
__IO uint32_t TRM;
} LPC_ADC_Type;
ADC组的基址为0x4001C000,所以要将基址指针强制转换为上述结构体,还要加上下面的定义。
#define LPC_ADC_BASE 0x4001C000UL
#define LPC_ADC ((LPC_ADC_Type *) LPC_ADC_BASE)
下面就一一对上述寄存器进行讨论,先来看A/D控置寄存器CTRL,其字节地址为0x4001C000,下表给出了它的全部位结构。

该寄存器用于指定ADC时钟的时钟分频值,以及包括低功耗模式在内的通用工作模式位,允许在不使用的时候关断A/D降低功耗。ADC的时钟结构如下图所示。

在使用ADC模块前,需要先配置SYSAHBCLKCTRL寄存器来使能ADC寄存器接口时钟和ADC时钟。
下面是A/D转换时序A控制寄存器,其字节地址为0x4001C008,下表给出了它的全部位结构。

在ADC模块中,提供了两个独立的转换时序,每个时序都包含一个或多个通道的一组转换。此控制寄存器指定时序A的通道选择和触发条件,包含允许软件初始化该转换时序的位。为了避免伪触发转换,仅当转换时序禁用时更改触发配置。软件或硬件可以触发转换时序的转换操作,但如果转换仅由软件触发,则必须防止伪硬件触发。
下面是A/D转换时序B控制寄存器,其字节地址为0x4001C00C,下表给出了它的全部位结构。

同前面的时序A控制寄存器一样,此控制寄存器指定时序B的通道选择和触发条件,还包含允许软件初始化该转换时序的位。以上两个时序控制寄存器中的第12-14位(TRIGGER位),均用于选择启动A/D转换的触发条件,一共有6个,如下图所示。

TRIGGER的3位二进制数,分别对应上图中的输入数(第6、第7未使用)。默认使用输入0,即非硬件触发或软件触发方式。
接下来看A/D时序A全局数据寄存器SEQA_GDAT,其字节地址为0x4001C010,下表是它的全部位结构。

下面是A/D时序B全局数据寄存器SEQB_GDAT,其字节地址为0x4001C014,下表给出了它的全部位结构。

A/D全局数据寄存器包含了每次转换时序完成时的最新A/D转换结果。一般有两种方法可以读取A/D转换结果,一种是使用上述的A/D全局数据寄存器,在每一次A/D转换结束后从RESULT位域读取数据。另一种是读取单个A/D通道数据寄存器(见下表),通常是在整个时序完成后再读取。对于特定时序,建议始终使用同一种方法。全局寄存器与DMA操作配合使用时会很有用,尤其对于选择的转换通道不连贯时(因此单个结果寄存器的地址将是非顺序的,使得DMA引擎难以寻址),操作更高效。对于中断驱动代码而言,较好的做法是等待整个时序完成,然后从单个通道寄存器中获取结果。
下面是单个的数据寄存器DAT0~DAT11, 一共有12个分别对应12路输入,其字节地址为0x4001C020~0x4001C04C,下表给出了它们的全部位结构。
![DAT[0-11]](https://img2024.cnblogs.com/blog/1553657/202605/1553657-20260531180034453-778275228.png)
从上表中可以看出,它们与全局数据寄存器是完全一样的。DAT寄存器中的信息始终对应该通道上完成的最新转换,无论是哪个时序请求的转换或哪个触发所导致。注意,各通道采用的方法应在相应SEQ_CTRL寄存器的MODE位中反映,这将影响中断和溢出标志的产生。
--待续--

浙公网安备 33010602011771号