TinyOS下CC2430单片机ADC使用方法

1.TinyOS提供的组件和接口
CC2430被广泛应用于无线传感器网络,其片上自带的ADC可以将传感器采集到的模拟信号转换为数字信号进行相应处理 。
开源组织TinyOS 8051 working group 提供可以移植到CC2430EM平台上的TinyOS,该平台TinyOS含有可用于控制CC2430单片机ADC的组件AdcC:
components new AdcC(); // 用于控制CC2430 ADC
该组件可将P0口8路输入任一通道中的模拟信号转换为数字信号 。
为调用该组件提供有如下接口:
provides interface AdcControl; // 用于控制和打开指定ADC端口
provides interface Read; //用于进行指定端口的ADC转换
2.AdcC使用实例分析
【TinyOS下CC2430单片机ADC使用方法】2.1组成AdcC组件的内部组件连接关系定义如下:
generic configuration AdcC() {
provides interface AdcControl;
provides interface Read;
}
implementation {
components MainC, AdcP;
MainC.SoftwareInit -> AdcP.Init;
/*****该枚举变量是关键,ID =unique("UNIQUE_ADC_PORT"),表明ID值是一个常量函数的返回值,常量函数unique()的具体使用方法参考tinyos-programming.pdf文档中的介绍**********/
enum { ID = unique("UNIQUE_ADC_PORT"), };
AdcControl = AdcP.AdcControl[ID]; // ID值为0当unique只调用1次
Read = AdcP.Read[ID]; // 同上
}
2.2下面进入到组件(模块)AdcP中查看AdcControl[ID]、Read[ID]接口的具体实现:
module AdcP {
provides interface Init;
provides interface AdcControl[uint8_t id];
provides interface Read[uint8_t id];
}
implementation
{
#include "Adc.h"
uint8_t references[uniqueCount("UNIQUE_ADC_PORT")]; //uniqueCount()等于unique()函数在程序中的调用次数,该数组用于存放参考电压值
uint8_t resolutions[uniqueCount("UNIQUE_ADC_PORT")]; //该数组用于存放对应端口的转换精度:8bit/10bit/12bit/14bit
uint8_t inputs[uniqueCount("UNIQUE_ADC_PORT")]; //该数组用于存放对应的端口号(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;
}
// 三个参数分别为参考电压、转换精度、端口号
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,产生新的ADC转换序列,停止正在进行的转换
}
/* enable channel if not already enabled */
if (!inUse[id]) { // 查询对应ADC端口是否已经使用,否,使能
inUse[id] = TRUE;
counter++;
ADC_ENABLE_CHANNEL(inputs[id]); // ADC Input Configuration 对应端口输入使能,该宏定义在Adc.h中实现
}
/* save parameters */
references[id] = reference; //参考电压
resolutions[id] = resolution; //转换位数
inputs[id] = input; //端口号
}
// 对应端口ADC功能关闭
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; //貌似没啥用,覆盖了 我给注释了结果是一样的
//temp = ADCL; //貌似没啥用,覆盖了 我给注释了结果是一样的
/* start conversion 根据数组中存储的对应端口的参数改变控制寄存器ADCCON3,进行ADC转换 */
ADC_SINGLE_CONVERSION(references[id] | resolutions[id] | inputs[id]);
return SUCCESS;
}
}
task void signalReadDone();
int16_t value;
/* Interrupt handler 中断服务函数 */
MCS51_INTERRUPT(SIG_ADC) {
/* read value from register */
value = http://www.dg8.com.cn/tool/(( (uint16_t) ADCH) << 8); // 高8位右移8为存储到16位value中
value |= ADCL; //ADC转换的低8位存到value的低8位
post signalReadDone(); // 通知上层组件ADC转化成功任务
}
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位,因为转化结果是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
// 通知上层组件转换成功,value为传递的ADC转换的值
signal Read.readDone[tmp](SUCCESS, value);
}
default event void Read.readDone[uint8_t id](error_t result, int16_t val) {
}
}
通过以上对AdcP.nc文件的分析,可以看出CC2430单片机ADC转换的实现需要以下操作:
ADCIE // 端口使能,设置为输入
ADCCFG // 中断配置寄存器
ADCCON3 //ADC控制寄存器的操作
寄存器的具体定义参考CC2430 datasheet,内有使用详细说明 。
2.3 ADC组件的使用实例分析
2.3.1顶层应用组件定义:
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应用组件实现:
#define DEBUG
module TestAppP {
provides interface Init;
uses interface Boot;
uses interface Leds;
uses interface StdOut;
#ifdef __cc2430em__
uses interface Read as Read;
uses interface AdcControl;
#elif__mi

    推荐阅读