一、ADC簡介
ADC支援 14 位的模拟數字轉換,具有多達12 位的 ENOB(有效數字位)。它包括一個模拟多路轉換器,具有多達8 個各自可配置的通道,以及一個參考電壓發生器。轉換結果通過DMA寫入存儲器。還具有若幹運作模式。
二、A/D轉換的基本工作原理
将時間上連續變化的模拟量轉化為脈沖有無的數字量,這一過程就叫做數字化,實作數字化的關鍵裝置是ADC。
ADC:數模轉換器,将時間和幅值連續的模拟量轉化為時間和幅值離散的數字量,A/D轉換一般要經過采樣、保持、量化和編碼4個過程。
三、CC2530的A/D轉換子產品
ADC的主要特性如下:
● 可選的抽取率,這也設定了分辨率(7 到 12 位)
● 8 個獨立的輸入通道,可接受單端或差分信号
● 參考電壓可選為内部單端、外部單端、外部差分或 AVDD5
● 産生中斷請求
● 轉換結束時的 DMA 觸發
● 溫度傳感器輸入
● 電池測量功能
四、一些關于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子產品的信号輸入
端口0引腳可以配置為ADC輸入端,依次為AIN0~AIN7:
<1> 可以把輸入配置為單端輸入或差分輸入。
<2> 在選擇差分輸入的情況下,差分輸入對:AIN0~AIN1、AIN2~AIN3、AIN4~AIN5、AIN6~AIN7。
<3>除了輸入引腳 AIN0-AIN7,片上溫度傳感器的輸出也可以選擇作為 ADC的輸入,用于溫度測量。
<4> 可以将一個對應AVDD5/3的電壓作為ADC輸入,實作電池電壓監測。
<5> 負電壓和大于VDD的電壓都不能用于這些引腳。
<6> 單端電壓輸入AIN0~AIN7,以通道号碼0~7表示;四個差分輸入對則以 通道号碼8~11表示;溫度傳感器的通道号碼為14;AVDD5/3電壓輸入的通道号碼為15。
題目:定時采集電壓資料發送到上位機
将光照度傳感器接到的Zigbee小子產品上,每隔1秒以單通道的傳送到上位機。上位機與CC2530的 序列槽0相連,系統時鐘為傳送到上位機。上位機與CC2530的 序列槽0相連,系統時鐘為16MHz,波特率為9600BPS,發送資料采用查詢的方式。資料幀有4個位元組,格式如下: 0xFA (幀頭) ADCH ADCL 0xAF (幀尾)
思路:
1.初始化定時器1,實作0.1秒定時。
1 void Init_Timer1()
2 {
3 T1CC0L = 0xd4; //設定最大計數值的低8位
4 T1CC0H = 0x30; //設定最大計數值的高8位
5 T1CCTL0 |= 0x04; //開啟通道0的輸出比較模式
6 T1IE = 1; //使能定時器1中斷
7 T1OVFIM = 1; //使能定時器1溢出中斷
8 EA = 1; //使能總中斷
9 T1CTL = 0x0e; //分頻系數是128,模模式
10 }
2.在定時中斷函數中實作1秒定時。
1 unsigned char count = 0;
2 unsigned char F_time = 0;
3 /*================定時器1服務函數====================*/
4 #pragma vector = T1_VECTOR
5 __interrupt void Timer1_Sevice()
6 {
7 T1STAT &= ~0x01; //清除定時器1通道0中斷标志
8 count++;
9 if(count == 10) //定時1秒到
10 {
11 F_time = 1;
12 count = 0;
13 }
14 }
3.按照參數要求初始化序列槽0。
1 void Init_Uart0()
2 {
3 PERCFG = 0x00; //序列槽0的引腳映射到位置1,即P0_2和P0_3
4 P0SEL = 0x0C; //将P0_2和P0_3端口設定成外設功能
5 U0BAUD = 59; //16MHz的系統時鐘産生9600BPS的波特率
6 U0GCR = 9;
7 U0UCR |= 0x80; //禁止流控,8位資料,清除緩沖器
8 U0CSR |= 0xC0; //選擇UART模式,使能接收器
9 UTX0IF = 0; //清除TX發送中斷标志
10 URX0IF = 0; //清除RX接收中斷标志
11 URX0IE = 1; //使能URAT0的接收中斷
12 EA = 1; //使能總中斷
13 }
4.設計位元組數組發送函數。
unsigned char dat[4];
/*===================UR0發送字元串函數==================*/
void UR0SendString(unsigned char *str, unsigned char count)
{
while(count--)
{
U0DBUF = *str++; //将要發送的1位元組資料寫入U0DBUF
while(!UTX0IF); //等待TX中斷标志,即資料發送完成
UTX0IF = 0;
}
}
5.初始化ADC (單通道采集)。
配置APCFG寄存器
當使用ADC時,端口0的引腳必須配置為ADC模拟輸入。要配置一個端口0引腳為一個ADC輸入,APCFG寄存器中相應的位必須設定為1。這個寄存器的預設值是0,選擇端口0為非模拟輸入,即作為數字I/O端口。
注意:APCFG寄存器的設定将覆寫P0SEL的設定。
主要對端口的功能進行選擇,設定其傳輸方向,并将端口設定為模拟輸入。
1 void Init_ADC0()
2 {
3 P0SEL |= 0x01; //P0_0端口設定為外設功能
4 P0DIR &= ~0x01; //P0_0端口設定為輸入端口
5 APCFG |= 0x01; //P0_0作為模拟I/O使用
6 }
6.實作資料采集并發送到上位機。
配置ADCCON3寄存器
單通道的ADC轉換,隻需将控制字寫入ADCCON3寄存器即可。
例子:ADCCON3 = (0x80 | 0x10 | 0x00); //參考電壓選擇AVDD5引腳,256 抽取率,AINO通道0
首先将ADCIF标志位清0,接着對ADCCON3寄存器設定,該寄存器一旦被寫入,轉換立即開啟;然後等待ADCIF置1,這時候轉換完成,讀取資料即可。
1 /*===================讀取ADC的資料====================*/
2 void Get_ADC0_Value()
3 {
4 ADCIF = 0;
5 //參考電壓選擇AVDD5引腳,256抽取率,AIN0通道0
6 ADCCON3 = (0x80 | 0x10 | 0x00);
7 while(!ADCIF); //等待A/D轉換完成,
8 dat[0] = 0xaf;
9 dat[1] = ADCH; //讀取ADC資料低位寄存器
10 dat[2] = ADCL; //讀取ADC資料高位寄存器
11 dat[3] = 0xfa;
12 }
完整代碼:
1 #include "ioCC2530.h"
2 /*===============定時器1初始化函數==================*/
3 void Init_Timer1()
4 {
5 T1CC0L = 0xd4; //設定最大計數值的低8位
6 T1CC0H = 0x30; //設定最大計數值的高8位
7 T1CCTL0 |= 0x04; //開啟通道0的輸出比較模式
8 T1IE = 1; //使能定時器1中斷
9 T1OVFIM = 1; //使能定時器1溢出中斷
10 EA = 1; //使能總中斷
11 T1CTL = 0x0e; //分頻系數是128,模模式
12 }
13 unsigned char count = 0;
14 unsigned char F_time = 0;
15 /*================定時器1服務函數====================*/
16 #pragma vector = T1_VECTOR
17 __interrupt void Timer1_Sevice()
18 {
19 T1STAT &= ~0x01; //清除定時器1通道0中斷标志
20 count++;
21 if(count == 10) //定時1秒到
22 {
23 F_time = 1;
24 count = 0;
25 }
26 }
27 /*===================UR0初始化函數====================*/
28 void Init_Uart0()
29 {
30 PERCFG = 0x00; //序列槽0的引腳映射到位置1,即P0_2和P0_3
31 P0SEL = 0x0C; //将P0_2和P0_3端口設定成外設功能
32 U0BAUD = 59; //16MHz的系統時鐘産生9600BPS的波特率
33 U0GCR = 9;
34 U0UCR |= 0x80; //禁止流控,8位資料,清除緩沖器
35 U0CSR |= 0xC0; //選擇UART模式,使能接收器
36 UTX0IF = 0; //清除TX發送中斷标志
37 URX0IF = 0; //清除RX接收中斷标志
38 URX0IE = 1; //使能URAT0的接收中斷
39 EA = 1; //使能總中斷
40 }
41 unsigned char dat[4];
42 /*===================UR0發送字元串函數==================*/
43 void UR0SendString(unsigned char *str, unsigned char count)
44 {
45 while(count--)
46 {
47 U0DBUF = *str++; //将要發送的1位元組資料寫入U0DBUF
48 while(!UTX0IF); //等待TX中斷标志,即資料發送完成
49 UTX0IF = 0;
50 }
51 }
52 /*===================ADC初始化函數====================*/
53 void Init_ADC0()
54 {
55 P0SEL |= 0x01; //P0_0端口設定為外設功能
56 P0DIR &= ~0x01; //P0_0端口設定為輸入端口
57 APCFG |= 0x01; //P0_0作為模拟I/O使用
58 }
59 /*===================讀取ADC的資料====================*/
60 void Get_ADC0_Value()
61 {
62 ADCIF = 0;
63 //參考電壓選擇AVDD5引腳,256抽取率,AIN0通道0
64 ADCCON3 = (0x80 | 0x10 | 0x00);
65 while(!ADCIF); //等待A/D轉換完成,
66 dat[0] = 0xaf;
67 dat[1] = ADCH; //讀取ADC資料低位寄存器
68 dat[2] = ADCL; //讀取ADC資料高位寄存器
69 dat[3] = 0xfa;
70 }
71 /*=======================主函數======================*/
72 void main()
73 {
74 Init_Uart0();
75 Init_Timer1();
76 Init_ADC0();
77 while(1)
78 {
79 if(F_time == 1) //定時1秒時間到
80 {
81 Get_ADC0_Value(); //進行A/D轉換并讀取資料
82 UR0SendString(dat,4); //向上位機發送資料
83 F_time = 0; //定時1秒标志清0
84 }
85 }
86 }
View Code