第一章 A/D轉換的基本工作原理
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的A/D轉換模塊
CC2530的ADC模塊支持最高14位二進制的模擬數字轉換,具有12位的有效數據位,它包括一個模擬多路轉換器,具有8個各自可配置的通道,以及一個參考電壓發生器。
該ADC模塊有如下主要特征:
<1> 可選取的抽取率,設置分辨率(7~12位)。
<2> 8個獨立的輸入通道,可接收單端或差分信號。
<3> 參考電壓可選為內部單端、外部單端、外部差分或AVDD5。
<4> 單通道轉換結束可產生中斷請求。
<5> 序列轉換結束可發出DMA觸發。
<6> 可將片內溫度傳感器作為輸入。
<7> 電池電壓測量功能。
第三章 ADC模塊的信號輸入
端口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。
第四章 ADC相關的幾個概念
<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并返回轉換結果。
第五章 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,這時候轉換完成,讀取數據即可。
第六章 源代碼
【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(); //關閉所有中斷