天天看點

CC2530ADC轉換

一、ADC簡介

            ADC支援 14 位的模拟數字轉換,具有多達12 位的 ENOB(有效數字位)。它包括一個模拟多路轉換器,具有多達8 個各自可配置的通道,以及一個參考電壓發生器。轉換結果通過DMA寫入存儲器。還具有若幹運作模式。

二、A/D轉換的基本工作原理

将時間上連續變化的模拟量轉化為脈沖有無的數字量,這一過程就叫做數字化,實作數字化的關鍵裝置是ADC。

        ADC:數模轉換器,将時間和幅值連續的模拟量轉化為時間和幅值離散的數字量,A/D轉換一般要經過采樣、保持、量化和編碼4個過程。

CC2530ADC轉換

三、CC2530的A/D轉換子產品

ADC的主要特性如下:

● 可選的抽取率,這也設定了分辨率(7 到 12 位)

● 8 個獨立的輸入通道,可接受單端或差分信号

● 參考電壓可選為内部單端、外部單端、外部差分或 AVDD5

● 産生中斷請求

● 轉換結束時的 DMA 觸發

● 溫度傳感器輸入

● 電池測量功能

CC2530ADC轉換

四、一些關于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的設定。

CC2530ADC轉換

主要對端口的功能進行選擇,設定其傳輸方向,并将端口設定為模拟輸入。

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

CC2530ADC轉換

首先将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