ZigBee開發(7)--基礎實驗AD
一、A/D轉換的基本工作原理
將時間上連續變化的模擬量轉化為脈沖有無的數字量,這一過程就叫做數字化,實現數字化的關鍵設備是ADC。
ADC:數模轉換器,將時間和幅值連續的模擬量轉化為時間和幅值離散的數字量,A/D轉換一般要經過采樣、保持、量化和編碼4個過程。
二、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> 差分輸入對:AIN0~AIN1、AIN2~AIN3、AIN4~AIN5、AIN6~AIN7。
<3> 片上溫度傳感器的輸出也可以作為ADC的輸入用於測量芯片的溫度。
<4> 可以將一個對應AVDD5/3的電壓作為ADC輸入,實現電池電壓監測。
<5> 負電壓和大於VDD的電壓都不能用於這些引腳。
<6> 單端電壓輸入AIN0~AIN7,以通道號碼0~7表示;四個差分輸入對則以 通道號碼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並返回轉換結果。
【1】配置APCFG寄存器
當使用ADC時,端口0的引腳必須配置為ADC模擬輸入。要配置一個端口0引腳為一個ADC輸入,APCFG寄存器中相應的位必須設置為1。這個寄存器的默認值是0,選擇端口0為非模擬輸入,即作為數字I/O端口。
註意:APCFG寄存器的設置將覆蓋P0SEL的設置。
【2】配置ADCCON3寄存器
單通道的ADC轉換,只需將控制字寫入ADCCON3寄存器即可。
【3】ADC初始化
主要對端口的功能進行選擇,設置其傳輸方向,並將端口設置為模擬輸入。
【4】ADC數據采集
首先將ADCIF標誌位清0,接著對ADCCON3寄存器設置,該寄存器一旦被寫入,轉換立即開啟;然後等待ADCIF置1,這時候轉換完成,讀取數據即可。
/************************************** 程序描述:通過內部 AD 控制把溫度信息通過 串口發送給上位機,部分芯片誤差 較大,需要校準。手摸著芯片,溫度 明顯變大。 **************************************/ #include <ioCC2530.h> //#include “InitUART_Timer.h” //註意在 option 裏設置路徑 #include<stdio.h> #define uint unsigned int #define uchar unsigned char /*===================UR0初始化函數====================*/ void usart_Init(void) { PERCFG &= ~0x01;//位置 1 P0 口 P0SEL |= 0x0c;//P0_2,P0_3用作串口,第二功能 P2DIR &= ~0XC0; //P0 優先作為 UART0 ,優先級 U0CSR |= 0x80;//UART 方式 U0UCR |= 0x0c; U0GCR |= 11;//U0GCR 與 U0BAUD 配合 U0BAUD |= 216;// 波特率設為 115200 U0CSR |= 0x40;//允許接收 EA = 1;//開總中斷 URX0IE = 1;//開串口接收中斷 UTX0IF = 0;//UART0 TX 中斷標誌初始置位 URX0IF = 0;//UART0 RX 中斷標誌初始置位 } void usart_Send_Byte(uchar c) { U0DBUF = c; while( !UTX0IF );//等待發送完成標誌位置1 UTX0IF = 0; } void usart_Send_String(uchar *data,uint len) { while(len--) { usart_Send_Byte(*data++); } } /**************************************************************** 溫度傳感器初始化函數 ****************************************************************/ void initTempSensor(void) { EA = 0; CLKCONCMD &= ~0x40; //設置系統時鐘源為 32MHZ晶振 while(CLKCONSTA & 0x40); //等待晶振穩定為 32M CLKCONCMD &= ~0x47; //設置系統主時鐘頻率為 //DISABLE_ALL_INTERRUPTS(); //關閉所有中斷 //InitClock(); //設置系統主時鐘為 32M //TR0=0X01; //set ‘1’ to connectthe temperature sensorto theSOC_ADC. //ATEST=0X01; // Enablesthe temperature sensor } /**************************************************************** 讀取溫度傳感器 AD 值函數 ****************************************************************/ float getTemperature(void){ uint value; ADCCON3 = (0x3E); //選擇 1.25V 為參考電壓;12 位分辨率;對片內溫度傳感器采樣 ADCCON1 |= 0x30; //選擇 ADC 的啟動模式為手動 ADCCON1 |= 0x40; //啟動 AD 轉化 while(!(ADCCON1 & 0x80)); //等待 AD 轉換完成 value = ADCL >> 4; //ADCL 寄存器低 4 位無效 value |= (((uint)ADCH) << 4); return (value-1367.5)/4.5-4; //根據 AD 值,計算出實際的溫度,芯片、 //手冊有錯,溫度系數應該是 4.5 /℃ //進行溫度校正,這裏減去 4℃(不同芯片根據具體情況校正) } /**************************************************************** 主函數 ****************************************************************/ void main(void) { uchar I; uchar TempValue[6]; float AvgTemp; usart_Init(); //初始化串口 initTempSensor(); //初始化 ADC while(1) { AvgTemp = 0; for(I = 0 ; I < 64 ; I++) { AvgTemp += getTemperature(); AvgTemp=AvgTemp/2; //每次累加後除 2 } /****溫度轉換成 ascii 碼發送****/ TempValue[0] = (unsigned char)(AvgTemp)/10 + 48; //十位 TempValue[1] = (unsigned char)(AvgTemp)%10 + 48; //個位 TempValue[2] = ‘.‘; //小數點 TempValue[3] = (unsigned char)(AvgTemp*10)%10+48; //十分位 TempValue[4] = (unsigned char)(AvgTemp*100)%10+48; //百分位 TempValue[5] = ‘\0‘; //字符串結束符 usart_Send_String( TempValue,6); //Delayms(2000); //使用 32M 晶振,故這裏 2000 約等於 1S } }
ZigBee開發(7)--基礎實驗AD