TinyOS下CC2430單片機(jī)ADC使用方法
1.TinyOS提供的組件和接口
CC2430被廣泛應(yīng)用于無(wú)線(xiàn)傳感器網(wǎng)絡(luò),其片上自帶的ADC可以將傳感器采集到的模擬信號(hào)轉(zhuǎn)換為數(shù)字信號(hào)進(jìn)行相應(yīng)處理。
開(kāi)源組織TinyOS 8051 working group 提供可以移植到CC2430EM平臺(tái)上的TinyOS,該平臺(tái)TinyOS含有可用于控制CC2430單片機(jī)ADC的組件AdcC:
components new AdcC(); // 用于控制CC2430 ADC
該組件可將P0口8路輸入任一通道中的模擬信號(hào)轉(zhuǎn)換為數(shù)字信號(hào)。
為調(diào)用該組件提供有如下接口:
provides interface AdcControl; // 用于控制和打開(kāi)指定ADC端口
provides interface Read
2.AdcC使用實(shí)例分析
2.1組成AdcC組件的內(nèi)部組件連接關(guān)系定義如下:
generic configuration AdcC() {
provides interface AdcControl;
provides interface Read
}
implementation {
components MainC, AdcP;
MainC.SoftwareInit -> AdcP.Init;
/*****該枚舉變量是關(guān)鍵,ID =unique("UNIQUE_ADC_PORT"),表明ID值是一個(gè)常量函數(shù)的返回值,常量函數(shù)unique()的具體使用方法參考tinyos-programming.pdf文檔中的介紹**********/
enum { ID = unique("UNIQUE_ADC_PORT"), };
AdcControl = AdcP.AdcControl[ID]; // ID值為0當(dāng)unique只調(diào)用1次
Read = AdcP.Read[ID]; // 同上
}
2.2下面進(jìn)入到組件(模塊)AdcP中查看AdcControl[ID]、Read[ID]接口的具體實(shí)現(xiàn):
module AdcP {
provides interface Init;
provides interface AdcControl[uint8_t id];
provides interface Read
}
implementation
{
#include "Adc.h"
uint8_t references[uniqueCount("UNIQUE_ADC_PORT")]; //uniqueCount()等于unique()函數(shù)在程序中的調(diào)用次數(shù),該數(shù)組用于存放參考電壓值
uint8_t resolutions[uniqueCount("UNIQUE_ADC_PORT")]; //該數(shù)組用于存放對(duì)應(yīng)端口的轉(zhuǎn)換精度:8bit/10bit/12bit/14bit
uint8_t inputs[uniqueCount("UNIQUE_ADC_PORT")]; //該數(shù)組用于存放對(duì)應(yīng)的端口號(hào)(P0(0~7)口的任一端口)
bool inUse[uniqueCount("UNIQUE_ADC_PORT")]; // 端口是否使用FLAG
uint8_t counter;
uint8_t lastId = uniqueCount("UNIQUE_ADC_PORT");
// 一些用到的變量的初始化操作
command error_t Init.init() {
uint8_t i;
for (i = 0; i < uniqueCount("UNIQUE_ADC_PORT"); i++) {
inUse[i] = FALSE;
}
counter = 0;
return SUCCESS;
}
// 三個(gè)參數(shù)分別為參考電壓、轉(zhuǎn)換精度、端口號(hào)
command void AdcControl.enable[uint8_t id](uint8_t reference, uint8_t resolution, uint8_t input) {
/* enable interrupt when a channel is enabled (and stop any sampling in progress */
if (counter == 0) {
ADCIE = 1; // 使能ADC中斷
ADC_STOP(); // start select,產(chǎn)生新的ADC轉(zhuǎn)換序列,停止正在進(jìn)行的轉(zhuǎn)換
}
/* enable channel if not already enabled */
if (!inUse[id]) { // 查詢(xún)對(duì)應(yīng)ADC端口是否已經(jīng)使用,否,使能
inUse[id] = TRUE;
counter++;
ADC_ENABLE_CHANNEL(inputs[id]); // ADC Input Configuration 對(duì)應(yīng)端口輸入使能,該宏定義在A(yíng)dc.h中實(shí)現(xiàn)
}
/* save parameters */
references[id] = reference; //參考電壓
resolutions[id] = resolution; //轉(zhuǎn)換位數(shù)
inputs[id] = input; //端口號(hào)
}
// 對(duì)應(yīng)端口A(yíng)DC功能關(guān)閉
command void AdcControl.disable[uint8_t id]() {
/* disable channel if it has been enabled */
if (inUse[id]) {
inUse[id] = FALSE;
ADC_DISABLE_CHANNEL(inputs[id]);
counter--;
/* disable interrupts if no more channels are used by ADC */
if (counter == 0) {
ADCIE = 0;
}
}
}
/**
* Initiates a read of the value.
*
* @return SUCCESS if a readDone() event will eventually come back.
*/
command error_t Read.read[uint8_t id]() {
/* check if ADC is in use */
if (lastId < uniqueCount("UNIQUE_ADC_PORT")) {
return FAIL;
} else {
uint8_t temp;
/* remember caller */
lastId = id;
/* read out any old conversion value */
//temp = ADCH; //貌似沒(méi)啥用,覆蓋了 我給注釋了結(jié)果是一樣的
//temp = ADCL; //貌似沒(méi)啥用,覆蓋了 我給注釋了結(jié)果是一樣的
/* start conversion 根據(jù)數(shù)組中存儲(chǔ)的對(duì)應(yīng)端口的參數(shù)改變控制寄存器ADCCON3,進(jìn)行ADC轉(zhuǎn)換 */
ADC_SINGLE_CONVERSION(references[id] | resolutions[id] | inputs[id]);
return SUCCESS;
}
}
task void signalReadDone();
int16_t value;
/* Interrupt handler 中斷服務(wù)函數(shù) */
MCS51_INTERRUPT(SIG_ADC) {
/* read value from register */
value = (( (uint16_t) ADCH) << 8); // 高8位右移8為存儲(chǔ)到16位value中
value |= ADCL; //ADC轉(zhuǎn)換的低8位存到value的低8位
post signalReadDone(); // 通知上層組件ADC轉(zhuǎn)化成功任務(wù)
}
task void signalReadDone() {
uint8_t tmp;
/* mark ADC as not in use */
tmp = lastId;
lastId = uniqueCount("UNIQUE_ADC_PORT");
/* map out value according to resolution */
value >>= (8 - (resolutions[tmp] >> 3)); // 左移2位,因?yàn)檗D(zhuǎn)化結(jié)果是14BIT的植
/* sign extend to int16_t */
//8bit
// value >>= 2;
// value |= 0xC000 * ((value & 0x2000) >> 13);
//#define ADC_8_BIT 0x00 // 64 decimation rate
//#define ADC_10_BIT 0x10 // 128 decimation rate
//#define ADC_12_BIT 0x20 // 256 decimation rate
//#define ADC_14_BIT 0x30 // 512 decimation rate
// 通知上層組件轉(zhuǎn)換成功,value為傳遞的ADC轉(zhuǎn)換的值
signal Read.readDone[tmp](SUCCESS, value);
}
default event void Read.readDone[uint8_t id](error_t result, int16_t val) {
}
}
通過(guò)以上對(duì)AdcP.nc文件的分析,可以看出CC2430單片機(jī)ADC轉(zhuǎn)換的實(shí)現(xiàn)需要以下操作:
ADCIE // 端口使能,設(shè)置為輸入
ADCCFG // 中斷配置寄存器
ADCCON3 //ADC控制寄存器的操作
寄存器的具體定義參考CC2430 datasheet,內(nèi)有使用詳細(xì)說(shuō)明。
2.3 ADC組件的使用實(shí)例分析
2.3.1頂層應(yīng)用組件定義:
configuration TestAppC {
}
implementation {
components MainC, TestAppP;
MainC.SoftwareInit -> TestAppP.Init;
MainC.Boot <- TestAppP;
components LedsC;
TestAppP.Leds -> LedsC;
components StdOutC;
TestAppP.StdOut -> StdOutC;
#ifdef __cc2430em__
components new AdcC();
TestAppP.Read -> AdcC;
TestAppP.AdcControl -> AdcC;
#elif __micro4__
components new Msp430InternalTemperatureC();
TestAppP.Read -> Msp430InternalTemperatureC;
#endif
}
2.3.2應(yīng)用組件實(shí)現(xiàn):
#define DEBUG
module TestAppP {
provides interface Init;
uses interface Boot;
uses interface Leds;
uses interface StdOut;
#ifdef __cc2430em__
uses interface Read
uses interface AdcControl;
#elif __mi