目录
一、CC2530 ADC介绍:
ADC 支持 14 位的模拟数字转换,具有多达 12 位的有效位(ENOB)。它包括一个模拟多路转换器,具有多达 8 个各自可配置的通道,以及一个参考电压发生器。转换结果通过 DMA 写入存储器。还具有若干运行模式。
(1)ADC特性说明:
特性名称 | 描述 |
---|---|
抽取率及分辨率 | 可选的抽取率,设置分辨率(7到12位) |
输入通道 | 8个独立的输入通道,可接受单端或差分信号 |
参考电压 | 内部单端、外部单端、外部差分或 AVDD5 |
中断请求 | 产生中断请求 |
DMA触发 | 转换结束时的 DMA 触发 |
温度传感器输入 | 温度传感器输入 |
电池测量功能 | 电池测量功能 |
(2)ADC方框图:
(3)ADC配置:
当使用 ADC 时,端口 0 引脚必须配置为 ADC 输入。可以使用多达八个 ADC 输入引脚。要配置一个端口0引脚为一个 ADC 输 入 ,APCFG 寄存器中相应的位必须设置为 1。这个寄存器的默认值选择端口 0 引脚为非 ADC输入,即数字输入/输出。
APCFG 寄存器的设置将覆盖 P0SEL 的设置。
ADC 可以配置为使用通用 I/O 引脚 P2.0 作为内部触发器来启动转换。当用作 ADC 内部触发器时,P2.0 必须在输入模式下配置为通用 I/O。
APCFG (0xF2) - 模拟外设 I/O 配置
位 | 名称 | 复位 | R/W | 描述 |
---|---|---|---|---|
7:0 | APCFG[7:0] | 0x00 | R/W | 模拟外设I/O配置。APCFG[7:0]选择P0.7-P0.0作为模拟I/O。 0: 模拟I/O禁用; 1: 模拟I/O使能; |
二、ADC 操作:
(1)ADC 输入:
端口 0 引脚的信号可以用作 ADC 输入。在下面的描述中,这些端口引脚指的是 AIN0-AIN7 引脚。输入引脚 AIN0-AIN7 是连接到 ADC 的。
可以把输入配置为单端或差分输入。在选择差分输入的情况下,差分输入包括输入对AIN0-1、AIN2-3、AIN4-5 和 AIN6-7。注意负电压不适用于这些引脚,大于 VDD(未调节电压)的电压也不能。它们之间的差别是在差分模式下转换。它是在差分模式下转换的输入对之间的差。
除了输入引脚 AIN0-AIN7,片上温度传感器的输出也可以选择作为 ADC 的输入,用于温度测量。为此寄存器 TR0.ADCTM 和 ATEST.ATESTCTRL 必须分别按ADC 寄存器和 无线电寄存器所述设置。
还可以输入一个对应 AVDD5/3 的电压作为一个 ADC 输入。这个输入允许诸如需要在应用中实现一个电池监测器的功能。注意在这种情况下参考电压不能取决于电源电压,比如 AVDD5 电压不能用作一个参考电压。
单端电压输入 AIN0 到 AIN7 以通道号码 0 到 7 表示。通道号码 8 到 11 表示差分输入,由 AIN0–AIN1、AIN2–AIN3、AIN4–AIN5 和 AIN6–AIN7 组成。通道号码12到15表示 GND(12)温度传感器(14),和 AVDD5/3(15)。这些值在 ADCCON2.SCH 和 ADCCON3.SCH 域中使用。
(2)ADC 转换序列:
ADC 将执行一系列的转换,并把结果移动到存储器(通过 DMA),不需要任何 CPU 干预。
转换序列可以被 APCFG 寄存器影响,八位模拟输入来自 I/O 引脚,不必经过编程变为模拟输入。如果一个通道正常情况下应是序列的一部分,但是相应的模拟输入在 APCFG 中禁用,那么通道将被跳过。
当使用差分输入,处于差分对的两个引脚都必须在 APCFG 寄存器中设置为模拟输入引脚。
ADCCON2.SCH 寄存器位用于定义一个 ADC 转换序列,它来自 ADC 输入。如果ADCCON2.SCH 设置为一个小于 8 的值,转换序列包括一个转换,来自每个通道,从 0 往上,包括 ADCCON2.SCH 编程的通道号码。
当 ADCCON2.SCH 设置为一个在 8 和 12 之间的值,序列包括差分输入,从通道 8 开始,在已编程的通道结束。对于 ADCCON2.SCH 大于或等于 12,序列仅包括所选的通道。
(3)单个 ADC 转换:
除了这一转换序列,ADC 可以编程为从任何通道执行一个转换。这样一个转换通过写 ADCCON3 寄存器触发。除非一个转换序列已经正在进行,转换立即开始,在这种情况下序列一完成单个转换就被执行。
(4)ADC运行模式:
控制寄存器:
ADC 有三种控制寄存器:ADCCON1、ADCCON2 和 ADCCON3。这些寄存器用于配置 ADC 并报告结果。
ADCCON1 寄存器:
- EOC 位:状态位,当一个转换结束时设置为高电平,当读取 ADCH 时被清除。
- ST 位:用于启动一个转换序列。当设置为高电平且 ADCCON1.STSEL = 11,且当前没有转换正在进行时,就启动一个序列。
- STSEL 位:选择哪个事件将启动新的转换序列。选项包括外部引脚 P2.0 上升沿、外部引脚事件、之前序列的结束事件、定时器 1 的通道 0 比较事件或 ADCCON1.ST = 1。
ADCCON2 寄存器:
- SREF 位:用于选择参考电压。可选的参考电压包括内部单端、外部单端、外部差分或 AVDD5。参考电压只能在没有转换运行时修改。
- DIV 位:选择抽取率(并因此也设置了分辨率和完成一个转换所需的时间,或样本率)。抽取率只能在没有转换运行时修改。
- SCH 位:选择转换序列的最后一个通道。
ADCCON3 寄存器:
-
ADCCON3 寄存器控制单个转换的通道号码、参考电压和抽取率。单个转换在寄存器ADCCON3 写入后将立即发生,或如果一个转换序列正在进行,该序列结束之后立即发生。该寄存器位的编码和 ADCCON2 是完全一样的。
(5)ADC 转换结果:
数字转换结果以 2 的补码形式表示。对于单端配置,结果总是为正。这是因为结果是输入信号和地面之间的差值,它总是一个正符号数(Vconv=Vinp-Vinn,其中 Vinn=0V)。当输入幅度等于所选的电压参考 VREF时,达到最大值。对于差分配置,两个引脚对之间的差分被转换,这个差分可以是负符号数。对于抽取率是 512的一个数字转换结果的 12 位 MSB,当模拟输入 Vconv 等于 VREF 时,数字转换结果是 2047。当模拟输入等于-VREF 时,数字转换结果是-2048。
当 ADCCON1.EOC 设置为 1 时,数字转换结果是可以获得的,且结果放在 ADCH 和 ADCL 中。注意转换结果总是驻留在 ADCH 和 ADCL 寄存器组合的 MSB 段中。
当读取 ADCCON2.SCH 位时,它们将指示转换在哪个通道上进行。ADCL 和 ADCH 中的结果一般适用于之前的转换。如果转换序列已经结束,ADCCON2.SCH 的值大于最后一个通道号码,但是如果最后写入ADCCON2.SCH 的通道号码是 12 或更大,将读回同一个值。
(6)ADC 参考电压:
模拟数字转换的正参考电压可选择为一个内部生成的电压,AVDD5 引脚,适用于 AIN7 输入引脚的外部电压,或适用于 AIN6-AIN7 输入引脚的差分电压。
转换结果的准确性取决于参考电压的稳定性和噪音属性。希望的电压有偏差会导致 ADC 增益误差,与希望电压和实际电压的比例成正比。参考电压的噪音必须低于 ADC 的量化噪音,以确保达到规定的 SNR。
(7)ADC 转换时间:
ADC 只能运行在 32 MHz XOSC 上,用户不能整除系统时钟。实际 ADC 采样的 4 MHz 的频率由固定的内部划分器产生。执行一个转换所需的时间取决于所选的抽取率。总的来说,转换时间由以下公式给定:Tconv = (抽取率 + 16) x 0.25 μs。
(8)ADC 中断:
当通过写 ADCCON3 触发的一个单个转换完成时,ADC 将产生一个中断。当完成一个序列转换时,不产生一个中断。
(9)ADC DMA 触发:
每完成一个序列转换,ADC 将产生一个 DMA 触发。当完成一个单个转换,不产生 DMA 触发。
对于 ADCCON2.SCH 中头 8 位可能的设置所定义的八个通道,每一个都有一个 DMA 触发。当通道中一个新的样本准备转换,DMA 触发是活动的。DMA 触发命名为表 8-1 中的 ADC_CHsd,其中 s 是单端通道,d 是差分通道。
另外,还有一个 DMA 触发 ADC_CHALL,当 ADC 转换序列的任何通道中有新的数据准备好时,它是活动的。
三、ADC 寄存器:
ADCL(0xBA)-ADC数据低位
位 | 名称 | 复位 | R/W | 描述 |
---|---|---|---|---|
7:2 | ADC[5:0] | 000000 | R | ADC转换结果的低位部分 |
1:0 | - | 00 | R0 | 没有使用。读出来一直是 0 |
ADCH(0xBB)-ADC数据高位
位 | 名称 | 复位 | R/W | 描述 |
---|---|---|---|---|
7:0 | ADC[13:6] | 0x00 | R | ADC转换结果的高位部分 |
ADCON1(0xB4)-ADC控制1
位 | 名称 | 复位 | R/W | 描述 |
---|---|---|---|---|
7 | EOC | 0 | R/H0 | 转换结束。当ADCH被读取的时候清除。如果已读取前一数据之前,完成一个新的转换,EOC位仍然为高。 0: 转换没有完成; 1: 转换完成 |
6 | ST | 0 | R/W | 开始转换。读为1,直到转换完成。 0: 没有转换正在进行; 1: 如果ADCCON1.STSEL=11并且没有序列正在运行就启动一个转换序列。 |
5:4 | STSEL[1:0] | 11 | R/W1 | 启动选择。选择该事件,将启动一个新的转换序列。 00: P2.0引脚的外部触发; 01: 全速。不等待触发器; 10: 定时器1通道0比较事件; 11: ADCCON1.ST=1; |
3:2 | RCTRL[1:0] | 00 | R/W | 控制16位随机数发生器。当写01时,当操作完成时设置将自动返回到00。 00: 正常运行。(13X型展开); 01: LFSR的时钟一次(没有展开); 10: 保留; 11: 停止。关闭随机数发生器; |
1:0 | - | 11 | R/W | 保留。一直设为11 |
ADCCON2(0xB5)-ADC控制2
位 | 名称 | 复位 | R/W | 描述 |
---|---|---|---|---|
7:6 | SREF[1:0] | 00 | R/W | 选择参考电压用于序列转换。 00: 内部参考电压; 01: AIN7引脚上的外部参考电压; 10: AVDD5引脚; 11: AIN6-AIN7差分输入外部参考电压; |
5:4 | SDIV[1:0] | 01 | R/W | 为包含在转换序列内的通道设置抽取率。抽取率也决定完成转换需要的时间和分辨率。 00: 64抽取率(7位ENOB); 01: 128抽取率(9位ENOB); 10: 256抽取率(10位ENOB); 11: 512抽取率(12位ENOB); |
3:0 | SCH[3:0] | 0000 | R/W | 序列通道选择。选择序列转换的通道。一个序列可以是从AIN0到AIN7(SCH<=7)也可以是从差分输入AIN0-AIN1到AIN6-AIN7(8<=SCH<=11)。对于其他的设置,只能执行单个转换。当读取的时候,这些位将代表有转换进行的通道号码。 0000: AIN0; 0001: AIN1; 0010: AIN2; 0011: AIN3; 0100: AIN4; 0101: AIN5; 0110: AIN6; 0111: AIN7; 1000: AIN0-AIN1; 1001: AIN2-AIN3; 1010: AIN4-AIN5; 1011: AIN6-AIN7; 1100: GND; 1101: 正电压参考; 1110: 温度传感器; 1111: VDD/3; |
ADCCON3(0xB6)–ADC控制3
位 | 名称 | 复位 | R/W | 描述 |
---|---|---|---|---|
7:6 | EREF[1:0] | 00 | R/W | 选择用于额外转换的参考电压。 00: 内部参考电压; 01: AIN7引脚上的外部参考电压; 10: AVDD5引脚; 11: 在AIN6-AIN7差分输入的外部参考电压 |
5:4 | EDIV[1:0] | 00 | R/W | 设置用于额外转换的抽取率。抽取率也决定了完成转换需要的时间和分辨率。 00: 64抽取率(7位ENOB); 01: 128抽取率(9位ENOB); 10: 256抽取率(10位ENOB); 11: 512抽取率(12位ENOB); |
3:0 | ECH[3:0] | 0000 | R/W | 单个通道选择。选择写ADCCON3触发的单个转换所在的通道号码。当单个转换完成,该位自动清除。 0000: AIN0; 0001: AIN1; 0010: AIN2; 0011: AIN3; 0100: AIN4; 0101: AIN5; 0110: AIN6; 0111: AIN7; 1000: AIN0-AIN1; 1001: AIN2-AIN3; 1010: AIN4-AIN5; 1011: AIN6-AIN7; 1100: GND; 1101: 正电压参考; 1110: 温度传感器; 1111: VDD/3; |
TRO(0x624B)-测试寄存器0
位 | 名称 | 复位 | R/W | 描述 |
---|---|---|---|---|
7:1 | - | 0000 000 | R0 | 保留。写作0。 |
0 | ACTM | 0 | R/W | 设置为1来连接温度传感器到SOC_ADC。也可以看ATEST寄存器描述来使能温度传感器 |
四、代码编写:
(1)ADC.C文件编写:
#include <ioCC2530.h>
/*
APCFG (0xF2) –模拟外设 I/O 配置
位 名称 复位 R/W 描述
7:0 APCFG[7:0] 0x00 R/W 模拟外设I/O配置。
APCFG[7:0]选择P0.7 - P0.0作为模拟I/O
0: 模拟I/O禁用
1: 模拟I/O使能
*/
/*
ADCL (0xBA) – ADC 数据低位
位 名称 复位 R/W 描述
7:2 ADC[5:0] 000000 R ADC转换结果的低位部分
1:0 - 00 R0 没有使用。读出来一直是 0
*/
/*
ADCH (0xBB) – ADC 数据高位
位 名称 复位 R/W 描述
7:0 ADC[13:6] 0x00 R ADC转换结果的高位部分。
*/
/*
ADCCON1 (0xB4)–ADC 控制 1
位 名称 复位 R/W 描述
7 EOC 0 R/H0 转换结束。当 ADCH 被读取的时候清除。
如果已读取前一数据之前,完成一个新的转换,EOC 位仍然为高。
0: 转换没有完成
1: 转换完成
6 ST 0 开始转换。读为1,直到转换完成
0: 没有转换正在进行
1: 如果 ADCCON1.STSEL = 11并且没有序列正在运行就启动一个转换序列。
5:4 STSEL[1:0] 11 R/W1 启动选择。选择该事件,将启动一个新的转换序列。
00: P2.0引脚的外部触发。
01: 全速。不等待触发器
10: 定时器1通道0比较事件
11: ADCCON1.ST = 1
3:2 RCTRL[1:0] 00 R/W 控制16位随机数发生器(第 13 章)。
当写 01 时,当操作完成时设置将自动返回到 00。
00: 正常运行。(13X 型展开)
01: LFSR 的时钟一次(没有展开).
10: 保留
11: 停止。关闭随机数发生器
1:0 - 11 R/W 保留。一直设为 11 。
*/
/*
ADCCON2 (0xB5)–ADC 控制 2
位 名称 复位 R/W 描述
7:6 SREF[1:0] 00 R/W 选择参考电压用于序列转换
00: 内部参考电压
01: AIN7 引脚上的外部参考电压
10: AVDD5 引脚
11: AIN6 - AIN7 差分输入外部参考电压
5:4 SDIV[1:0] 01 R/W 为包含在转换序列内的通道设置抽取率。
抽取率也决定完成转换需要的时间和分辨率。
00: 64 抽取率(7 位 ENOB)
01: 128 抽取率(9 位 ENOB)
10: 256 抽取率(10 位 ENOB)
11: 512 抽取率(12 位 ENOB)
3:0 SCH[3:0] 0000 R/W 序列通道选择。选择序列结束。一个序列可以是从 AIN0 到 AIN7(SCH<=7)
也可以从差分输入AIN0-AIN1到AIN6-AIN7(8<=SCH<=11)。
对于其他的设置,只能执行单个转换。
当读取的时候,这些位将代表有转换进行的通道号码。
0000: AIN0
0001: AIN1
0010: AIN2
0011: AIN3
0100: AIN4
0101: AIN5
0110: AIN6
0111: AIN7
1000: AIN0-AIN1
1001: AIN2-AIN3
1010: AIN4-AIN5
1011: AIN6-AIN7
1100: GND
1101: 正电压参考
1110: 温度传感器
1111: VDD/3
*/
/*
ADCCON3 (0xB6)–ADC 控制 3
位 名称 复位 R/W 描述
7:6 EREF[1:0] 00 R/W 选择用于额外转换的参考电压
00: 内部参考电压
01: AIN7 引脚上的外部参考电压
10: AVDD5 引脚
11: 在 AIN6-AIN7 差分输入的外部参考电压
5:4 EDIV[1:0] 00 R/W 设置用于额外转换的抽取率。抽取率也决定了完成转换需要的时间和分辨率。
00: 64 抽取率(7 位 ENOB)
01: 128 抽取率(9 位 ENOB)
10: 256 抽取率(10 位 ENOB)
11: 512 抽取率(12 位 ENOB)
3:0 ECH[3:0] 0000 R/W 单个通道选择。选择写 ADCCON3 触发的单个转换所在的通道号码。
当单个转换完成,该位自动清除。
0000: AIN0
0001: AIN1
0010: AIN2
0011: AIN3
0100: AIN4
0101: AIN5
0110: AIN6
0111: AIN7
1000: AIN0-AIN1
1001: AIN2-AIN3
1010: AIN4-AIN5
1011: AIN6-AIN7
1100: GND
1101: 正电压参考
1110: 温度传感器
1111: VDD/3
*/
/*
TR0 (0x624B) –测试寄存器 0
位 名称 复位 R/W 描述
7:1 - 0000000 R0 保留。写作0。
0 ACTM 0 R/W 设置为1来连接温度传感器到SOC_ADC。
也参考ATEST寄存器描述来使能温度传感器
*/
// ADC初始化函数
void ADC_Init(void) {
// 配置P0.0为ADC输入
APCFG |= 0x01; // 使能P0.0作为模拟输入
// APCFG寄存器的设置将覆盖P0SEL的设置
// P0DIR &= ~0x01; //P0_0端口设置为输入端口 ,默认输入可不写
// 配置ADC控制寄存器
ADCCON1 = 0x30; // 选择手动启动转换,STSEL = 11 (ADCCON1.ST = 1)
ADCCON2 = 0xB0; // 使用AVDD5引脚电压,512 抽取率(12 位 ENOB),选择AIN0通道
}
// ADC读取函数
unsigned int ADC_Read(void) {
unsigned int ADC_Value;
// 启动ADC转换
ADCCON1 |= 0x40; // 设置ST位为1,启动转换
// 等待转换完成
while (!(ADCCON1 & 0x80)); // 等待EOC位变为1
// 读取ADC结果
ADC_Value = ADCL; // 读取低字节
ADC_Value |= (ADCH << 8); // 读取高字节并组合成完整的ADC值
/*
数据手册存在问题,有效位ADC[13:0],其中ADC[0]为无效位
ADC[13]为符号位,ADC[12:1]为数据位
即,读取的ADC值要右移三位才正确
*/
ADC_Value >>=3; // 0-4095
return ADC_Value;
}
(2)main.c文件编写:
#include <ioCC2530.h>
#include <stdio.h>
#include "Delay.h"
#include "Clock.h"
#include "uart.h"
#include "LED.h"
#include "ADC.h"
unsigned int ADC;
void main(void) {
Clock_config_32MHz(); // 时钟配置32MHz
Uart_Init();
ADC_Init();
while (1) {
ADC=ADC_Read();
printf("%d\n",ADC);
Delay_s(1);
}
}
(3)ADC读取光敏示例:
五、代码下载:
http://通过网盘分享的文件:ADCRead 链接: https://pan.baidu.com/s/1_zd0A4z1QFIwEDQZI02ABA?pwd=gxhy 提取码: gxhy