A/D转换(Analog-to-Digital Conversion)是将模拟信号转换为数字信号的过程。在各种电子系统中广泛应用,包括微控制器、数据采集系统、传感器接口等。
A/D转换器的基本工作原理如下:
(1)采样(Sampling):A/D转换开始时,模拟输入信号被以固定时间间隔采样。采样是指在一段时间内测量并记录模拟输入信号的电压值或电流值。采样速率决定了每秒对信号进行采样的次数,也称为采样频率。
(2)量化(Quantization):采样后,模拟信号的幅度需要被量化为离散的数字值。这个过程将连续的模拟信号划分为有限数量的离散级别,它决定了数字表示的精度。量化过程涉及将每个采样值映射到最接近的离散级别上。
(3)编码(Encoding):量化后,所得到的离散级别需要被编码为二进制数字。在大多数情况下,使用二进制编码来表示每个离散级别。编码的位数决定了A/D转换器的分辨率和所能表示的数字范围。
(4)样本保持(Sample and Hold):在进行A/D转换的过程中,模拟信号的值需要保持不变,以便进行准确的量化和编码。为了实现这一点,样本保持电路用于在样本期间“冻结”输入信号,直到转换完成。
(5)转换速率(Conversion Rate):A/D转换器的转换速率指的是它可以执行的转换操作的频率。转换速率取决于A/D转换器的性能和应用需求。较高的转换速率对于需要实时数据获取和高速处理的应用是重要的。
A/D转换的基本工作原理包括采样、量化、编码和样本保持等步骤。通过这些步骤,模拟信号被转换为离散的数字表示,从而使得数字系统能够处理和分析这些信号。A/D转换器在许多应用中都扮演着至关重要的角色,例如传感器数据采集、音频处理、仪器测量等。
CC2530的ADC模块支持最高14位二进制的模拟数字转换,具有12位的有效数据位,它包括一个模拟多路转换器,具有8个各自可配置的通道,以及一个参考电压发生器。
该ADC模块有如下主要特征:
<1> 可选取的抽取率,设置分辨率(7~12位)。
<2> 8个独立的输入通道,可接收单端或差分信号。
<3> 参考电压可选为内部单端、外部单端、外部差分或AVDD5。
<4> 单通道转换结束可产生中断请求。
<5> 序列转换结束可发出DMA触发。
<6> 可将片内温度传感器作为输入。
<7> 电池电压测量功能。
端口0引脚可以配置为ADC输入端,依次为AIN0~AIN7:
<1> 可以把输入配置为单端输入或差分输入。
<2> 差分输入对:AIN0AIN1、AIN2AIN3、AIN4AIN5、AIN6AIN7。
<3> 片上温度传感器的输出也可以作为ADC的输入用于测量芯片的温度。
<4> 可以将一个对应AVDD5/3的电压作为ADC输入,实现电池电压监测。
<5> 负电压和大于VDD的电压都不能用于这些引脚。
<6> 单端电压输入AIN0AIN7,以通道号码07表示;四个差分输入对则以 通道号码8~11表示;温度传感器的通道号码为14;AVDD5/3电压输入的通道号码为15。
<1> 序列ADC转换:可以按序列进行多通道的ADC转换,并把结果通过DMA传送到存储器,而不需要CPU任何参与。
<2> 单通道ADC转换:在程序设计中,通过写ADCCON3寄存器触发单通道ADC转换,一旦寄存器被写入,转换立即开始。
<3> 参考电压:内部生成的电压、AVDD5引脚、适用于AIN7输入引脚的外部电压,或者 适用于AIN6~AIN7输入引脚的差分电压。
<4> 转换结果:数字转换结果以2的补码形式表示。对于单端,结果总是正的。对于差分配置,两个引脚之间的差分被转换,可以是负数。 当ADCCON1.EOC设置为1时,数字转换结果可以获得,且结果总是驻留在ADCH和ADCL寄存器组合的MSB段中。
<5> 中断请求:通过写ADCCON3触发一个单通道转换完成时,将产生一个中断,而完成 一个序列转换时,是不产生中断的。当每完成一个序列转换,ADC将产生 一个DMA触发。
<6> 寄存器:ADC有两个数据寄存器:ADCL和ADCH;三个控制寄存器:ADCCON1、ADCCON2、ADCCON3;分别用来配置ADC并返回转换结果。
【1】配置APCFG寄存器
当使用ADC时,端口0的引脚必须配置为ADC模拟输入。要配置一个端口0引脚为一个ADC输入,APCFG寄存器中相应的位必须设置为1。这个寄存器的默认值是0,选择端口0为非模拟输入,即作为数字I/O端口。
注意:寄存器的设置将覆盖P0SEL的设置。
【2】配置ADCCON3寄存器
单通道的ADC转换,只需将控制字写入ADCCON3寄存器即可。
【3】ADC初始化
主要对端口的功能进行选择,设置其传输方向,并将端口设置为模拟输入。
【4】ADC数据采集
首先将ADCIF标志位清0,接着对ADCCON3寄存器设置,该寄存器一旦被写入,转换立即开启;然后等待ADCIF置1,这时候转换完成,读取数据即可。
/******************************************************************************
CC2530模块AD测试程序
通过内置温度传感器实现温度采集
******************************************************************************/
#include < ioCC2530.h >
#include < stdio.h >
#define uint unsigned int
// Data
typedef unsigned char BYTE;
// Unsigned numbers
typedef unsigned char UINT8;
typedef unsigned char INT8U;
typedef unsigned short UINT16;
typedef unsigned short INT16U;
typedef unsigned long UINT32;
typedef unsigned long INT32U;
// Signed numbers
typedef signed char INT8;
typedef signed short INT16;
typedef signed long INT32;
#define ADC_REF_1_25_V 0x00
#define ADC_14_BIT 0x30
#define ADC_TEMP_SENS 0x0E
#define DISABLE_ALL_INTERRUPTS() (IEN0 = IEN1 = IEN2 = 0x00)
#define ADC_SINGLE_CONVERSION(settings) \\
do{ ADCCON3 = (settings); }while(0)
#define ADC_SAMPLE_SINGLE() \\
do { ADC_STOP(); ADCCON1 |= 0x40; } while (0)
#define ADC_SAMPLE_READY() (ADCCON1 & 0x80)
#define ADC_STOP() \\
do { ADCCON1 |= 0x30; } while (0)
#define ADC14_TO_CELSIUS(ADC_VALUE) ( ((ADC_VALUE) > > 4) - 335)
/**************************
系统时钟 不分频
计数时钟 32分频
**************************/
void InitClock(void)
{
CLKCONCMD = 0x28; //时器计数时钟设定为1M Hz, 系统时钟设定为32 MHz
while(CLKCONSTA & 0x40); //等晶振稳定
}
/*****************************************
串口初始化函数:初始化串口 UART0
*****************************************/
void InitUART0(void)
{
PERCFG = 0x00; //位置1 P0口
P0SEL = 0x3c; //P0用作串口
P2DIR &= ~0XC0; //P0优先作为UART0
U0CSR |= 0x80; //串口设置为UART方式
U0GCR |= 9;
U0BAUD |= 59; //波特率设为19200
UTX0IF = 1; //UART0 TX中断标志初始置位1
U0CSR |= 0X40; //允许接收
IEN0 |= 0x84; //开总中断,接收中断
}
/****************************************************************
串口发送字符串函数
****************************************************************/
void UartTX_Send_String(char *Data,int len)
{
int j;
for(j=0;j< len;j++)
{
U0DBUF = *Data++;
while(UTX0IF == 0);
UTX0IF = 0;
}
U0DBUF = 0x0A; //换行
while(UTX0IF == 0);
UTX0IF = 0;
}
/****************************************************************
延时函数
****************************************************************/
void Delay(uint n)
{
uint i;
for(i=0;i< n;i++);
for(i=0;i< n;i++);
for(i=0;i< n;i++);
for(i=0;i< n;i++);
for(i=0;i< n;i++);
}
INT16 AvgTemp;
/****************************************************************
温度传感器初始化函数
****************************************************************/
void initTempSensor(void)
{
DISABLE_ALL_INTERRUPTS(); //关闭所有中断
InitClock();