第一章 A/D轉(zhuǎn)換的基本工作原理
A/D轉(zhuǎn)換(Analog-to-Digital Conversion)是將模擬信號轉(zhuǎn)換為數(shù)字信號的過程。在各種電子系統(tǒng)中廣泛應(yīng)用,包括微控制器、數(shù)據(jù)采集系統(tǒng)、傳感器接口等。
A/D轉(zhuǎn)換器的基本工作原理如下:
(1)采樣(Sampling):A/D轉(zhuǎn)換開始時,模擬輸入信號被以固定時間間隔采樣。采樣是指在一段時間內(nèi)測量并記錄模擬輸入信號的電壓值或電流值。采樣速率決定了每秒對信號進(jìn)行采樣的次數(shù),也稱為采樣頻率。
(2)量化(Quantization):采樣后,模擬信號的幅度需要被量化為離散的數(shù)字值。這個過程將連續(xù)的模擬信號劃分為有限數(shù)量的離散級別,它決定了數(shù)字表示的精度。量化過程涉及將每個采樣值映射到最接近的離散級別上。
(3)編碼(Encoding):量化后,所得到的離散級別需要被編碼為二進(jìn)制數(shù)字。在大多數(shù)情況下,使用二進(jìn)制編碼來表示每個離散級別。編碼的位數(shù)決定了A/D轉(zhuǎn)換器的分辨率和所能表示的數(shù)字范圍。
(4)樣本保持(Sample and Hold):在進(jìn)行A/D轉(zhuǎn)換的過程中,模擬信號的值需要保持不變,以便進(jìn)行準(zhǔn)確的量化和編碼。為了實現(xiàn)這一點,樣本保持電路用于在樣本期間“凍結(jié)”輸入信號,直到轉(zhuǎn)換完成。
(5)轉(zhuǎn)換速率(Conversion Rate):A/D轉(zhuǎn)換器的轉(zhuǎn)換速率指的是它可以執(zhí)行的轉(zhuǎn)換操作的頻率。轉(zhuǎn)換速率取決于A/D轉(zhuǎn)換器的性能和應(yīng)用需求。較高的轉(zhuǎn)換速率對于需要實時數(shù)據(jù)獲取和高速處理的應(yīng)用是重要的。
A/D轉(zhuǎn)換的基本工作原理包括采樣、量化、編碼和樣本保持等步驟。通過這些步驟,模擬信號被轉(zhuǎn)換為離散的數(shù)字表示,從而使得數(shù)字系統(tǒng)能夠處理和分析這些信號。A/D轉(zhuǎn)換器在許多應(yīng)用中都扮演著至關(guān)重要的角色,例如傳感器數(shù)據(jù)采集、音頻處理、儀器測量等。
第二章 CC2530的A/D轉(zhuǎn)換模塊
CC2530的ADC模塊支持最高14位二進(jìn)制的模擬數(shù)字轉(zhuǎn)換,具有12位的有效數(shù)據(jù)位,它包括一個模擬多路轉(zhuǎn)換器,具有8個各自可配置的通道,以及一個參考電壓發(fā)生器。
該ADC模塊有如下主要特征:
<1> 可選取的抽取率,設(shè)置分辨率(7~12位)。
<2> 8個獨立的輸入通道,可接收單端或差分信號。
<3> 參考電壓可選為內(nèi)部單端、外部單端、外部差分或AVDD5。
<4> 單通道轉(zhuǎn)換結(jié)束可產(chǎn)生中斷請求。
<5> 序列轉(zhuǎn)換結(jié)束可發(fā)出DMA觸發(fā)。
<6> 可將片內(nèi)溫度傳感器作為輸入。
<7> 電池電壓測量功能。
第三章 ADC模塊的信號輸入
端口0引腳可以配置為ADC輸入端,依次為AIN0~AIN7:
<1> 可以把輸入配置為單端輸入或差分輸入。
<2> 差分輸入對:AIN0AIN1、AIN2AIN3、AIN4AIN5、AIN6AIN7。
<3> 片上溫度傳感器的輸出也可以作為ADC的輸入用于測量芯片的溫度。
<4> 可以將一個對應(yīng)AVDD5/3的電壓作為ADC輸入,實現(xiàn)電池電壓監(jiān)測。
<5> 負(fù)電壓和大于VDD的電壓都不能用于這些引腳。
<6> 單端電壓輸入AIN0AIN7,以通道號碼07表示;四個差分輸入對則以 通道號碼8~11表示;溫度傳感器的通道號碼為14;AVDD5/3電壓輸入的通道號碼為15。
第四章 ADC相關(guān)的幾個概念
<1> 序列ADC轉(zhuǎn)換:可以按序列進(jìn)行多通道的ADC轉(zhuǎn)換,并把結(jié)果通過DMA傳送到存儲器,而不需要CPU任何參與。
<2> 單通道ADC轉(zhuǎn)換:在程序設(shè)計中,通過寫ADCCON3寄存器觸發(fā)單通道ADC轉(zhuǎn)換,一旦寄存器被寫入,轉(zhuǎn)換立即開始。
<3> 參考電壓:內(nèi)部生成的電壓、AVDD5引腳、適用于AIN7輸入引腳的外部電壓,或者 適用于AIN6~AIN7輸入引腳的差分電壓。
<4> 轉(zhuǎn)換結(jié)果:數(shù)字轉(zhuǎn)換結(jié)果以2的補碼形式表示。對于單端,結(jié)果總是正的。對于差分配置,兩個引腳之間的差分被轉(zhuǎn)換,可以是負(fù)數(shù)。 當(dāng)ADCCON1.EOC設(shè)置為1時,數(shù)字轉(zhuǎn)換結(jié)果可以獲得,且結(jié)果總是駐留在ADCH和ADCL寄存器組合的MSB段中。
<5> 中斷請求:通過寫ADCCON3觸發(fā)一個單通道轉(zhuǎn)換完成時,將產(chǎn)生一個中斷,而完成 一個序列轉(zhuǎn)換時,是不產(chǎn)生中斷的。當(dāng)每完成一個序列轉(zhuǎn)換,ADC將產(chǎn)生 一個DMA觸發(fā)。
<6> 寄存器:ADC有兩個數(shù)據(jù)寄存器:ADCL和ADCH;三個控制寄存器:ADCCON1、ADCCON2、ADCCON3;分別用來配置ADC并返回轉(zhuǎn)換結(jié)果。
第五章 ADC配置步驟
【1】配置APCFG寄存器
當(dāng)使用ADC時,端口0的引腳必須配置為ADC模擬輸入。要配置一個端口0引腳為一個ADC輸入,APCFG寄存器中相應(yīng)的位必須設(shè)置為1。這個寄存器的默認(rèn)值是0,選擇端口0為非模擬輸入,即作為數(shù)字I/O端口。
注意:寄存器的設(shè)置將覆蓋P0SEL的設(shè)置。
【2】配置ADCCON3寄存器
單通道的ADC轉(zhuǎn)換,只需將控制字寫入ADCCON3寄存器即可。
【3】ADC初始化
主要對端口的功能進(jìn)行選擇,設(shè)置其傳輸方向,并將端口設(shè)置為模擬輸入。
【4】ADC數(shù)據(jù)采集
首先將ADCIF標(biāo)志位清0,接著對ADCCON3寄存器設(shè)置,該寄存器一旦被寫入,轉(zhuǎn)換立即開啟;然后等待ADCIF置1,這時候轉(zhuǎn)換完成,讀取數(shù)據(jù)即可。
第六章 源代碼
【1】內(nèi)置溫度采集
/******************************************************************************
CC2530模塊AD測試程序
通過內(nèi)置溫度傳感器實現(xiàn)溫度采集
******************************************************************************/
#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)
?
/**************************
系統(tǒng)時鐘 不分頻
計數(shù)時鐘 32分頻
**************************/
void InitClock(void)
{
CLKCONCMD = 0x28; //時器計數(shù)時鐘設(shè)定為1M Hz, 系統(tǒng)時鐘設(shè)定為32 MHz
while(CLKCONSTA & 0x40); //等晶振穩(wěn)定
}
?
/*****************************************
串口初始化函數(shù):初始化串口 UART0
*****************************************/
void InitUART0(void)
{
PERCFG = 0x00; //位置1 P0口
P0SEL = 0x3c; //P0用作串口
P2DIR &= ~0XC0; //P0優(yōu)先作為UART0
U0CSR |= 0x80; //串口設(shè)置為UART方式
U0GCR |= 9;
U0BAUD |= 59; //波特率設(shè)為19200
?
UTX0IF = 1; //UART0 TX中斷標(biāo)志初始置位1
U0CSR |= 0X40; //允許接收
IEN0 |= 0x84; //開總中斷,接收中斷
}
?
/****************************************************************
串口發(fā)送字符串函數(shù)
****************************************************************/
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;
}
?
/****************************************************************
延時函數(shù)
****************************************************************/
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;
?
/****************************************************************
溫度傳感器初始化函數(shù)
****************************************************************/
void initTempSensor(void)
{
DISABLE_ALL_INTERRUPTS(); //關(guān)閉所有中斷