6月中旬从美国一家公司购买了telosb开发板,开始正式接触telosB,今天写了一个AD转换+串口通信的程序,老大让我给他讲解一下原理,由于一个串口发送问题困扰了我3、4天,所以这个程序写了差不多一个礼拜,前面写好的都忘了,解释的不是很流畅,老大最后说,你的程序是模仿别人的吧?
。。。。。。。
工作7年,以前做的事情现在都不怎么记得,也没有什么资料,悲剧。。。。。。
为了不重复悲剧故事,现在有时间就记下一些东西,“好记性不如烂笔头”<--初中语文老师毛起生语。
先说说困扰我很多天的问题,其实也很简单,telosb自带的程序里面有一个串口和射频共用的发送程序send(TOS_Msg* msg)接口(bareMsgSend.nc),其中TOS_Msg是一个结构体,所以不管是串口发送还是射频发送都可以调用这个函数,省了很多事,但是有个小问题,因为数据格式是为了射频而定义的,所以用在串口上就觉得这个结构是多余的,你用串口助手在PC上收到一串数据,其中很多是格式数据,那我要怎么过滤掉这些没用的数据呢?一开始我是找send函数的下一层,希望可以找到核心的发送函数,直接调用它来过滤掉这些无用的数据格式,但是两天后我失败了。后来找到一个叫HPLUART的接口,它可以从串口发送/接受一个字节。又看到别人用bytecomm接口编了一个发送一串数据的函数,这个bytecomm接口的功能也是从串口(或者射频)发送/接收一个字节。我模仿他用HPLUART接口做了一个从串口发送一串数据的函数,其实一点不复杂,但是这个小小的事情折磨了我3天!
/***********************************************************/
第一个关于telosb的程序:
function:用两路ADC检测电压,通过比较电压值,得到瓦斯浓度,然后由串口输出到PC.
相关文件:gasM.nc
gasC.nc
gas.h
senseGas.nc
senseGasM.nc
makefile
//gasM.nc
includes Gas; //包含gas.h文件
module GasM { //定义模块GasM
provides {
interface StdControl; //提供接口StdControl
}
uses {
interface ADCControl; //使用接口ADCControl,用来绑定ADC和I/O口
}
}
implementation {
command result_t StdControl.init() {
return SUCCESS;
}
command result_t StdControl.start() {
result_t ok;
atomic P6SEL |= 0x03; //选定P6.0和P6.1,使之bind到ADC0和ADC1
ok = call ADCControl.init();
//P6.0绑定到ADC0
ok &= call ADCControl.bindPort(TOS_ADC_GAS_REF_PORT, TOSH_ACTUAL_ADC_GAS_REF_PORT);
//P6.1绑定到ADC1
ok &= call ADCControl.bindPort(TOS_ADC_GAS_RESULT_PORT,
TOSH_ACTUAL_ADC_GAS_RESULT_PORT);
return ok;
}
command result_t StdControl.stop() {
atomic P6SEL &= ~0x03;//解绑定?
return SUCCESS;
}
}
//gasC.nc
includes Gas;
configuration GasC
{
provides {
interface ADC as GAS_REF;
interface ADC as GAS_RESULT;
interface StdControl;
}
}
implementation
{
components GasM, ADCC;
StdControl = ADCC;
StdControl = GasM;
GAS_REF = ADCC.ADC[TOS_ADC_GAS_REF_PORT];
GAS_RESULT = ADCC.ADC[TOS_ADC_GAS_RESULT_PORT];
GasM.ADCControl -> ADCC;
}
//gas.h
#ifndef _H_Gas_h
#define _H_Gas_h
#include "MSP430ADC12.h"
// PAR, Photosynthetically Active Radiation
enum
{
TOS_ADC_GAS_REF_PORT = unique("ADCPort"),
TOSH_ACTUAL_ADC_GAS_REF_PORT = ASSOCIATE_ADC_CHANNEL(
INPUT_CHANNEL_A0,
REFERENCE_VREFplus_AVss,
REFVOLT_LEVEL_1_5
)
};
// TSR, Total Solar Radiation
enum
{
TOS_ADC_GAS_RESULT_PORT = unique("ADCPort"),
TOSH_ACTUAL_ADC_GAS_RESULT_PORT = ASSOCIATE_ADC_CHANNEL(
INPUT_CHANNEL_A1,
REFERENCE_VREFplus_AVss,
REFVOLT_LEVEL_1_5
)
};
#endif//_H_Gas_h
//senseGas.nc
configuration SenseGas {
//provides{
//interface StdControl;
//}
}
implementation
{
components Main,
HPLUARTC,
SenseGasM,
LedsC,
TimerC,
GasC;
Main.StdControl -> GasC;
Main.StdControl -> TimerC;
Main.StdControl -> SenseGasM;
SenseGasM.ADCControl -> GasC;
SenseGasM.GasCH0 -> GasC.GAS_REF;
SenseGasM.GasCH1 -> GasC.GAS_RESULT;
SenseGasM.HPLUART -> HPLUARTC;
SenseGasM.Leds -> LedsC;
SenseGasM.Timer0 -> TimerC.Timer[unique("Timer")];
SenseGasM.Timer1 -> TimerC.Timer[unique("Timer")];
}
//senseGasM.nc
module SenseGasM {
provides {
interface StdControl;
}
uses {
interface HPLUART;
interface Timer as Timer0;
interface Timer as Timer1;
interface ADC as GasCH0;
interface ADC as GasCH1;
interface StdControl as ADCControl;
interface Leds;
}
}
implementation {
uint8_t dataArray[2] = {0};
uint8_t* msgPtr;
uint16_t refData;
uint16_t resultData;
uint8_t txCount;
uint16_t temp;
#define txLength 2 //发送固定长度的数据,有待改进为发送任意长度的数据
/**
* Module scoped method. Displays the lowest 3 bits to the LEDs,
* with RED being the most signficant and YELLOW being the least significant.
*
* @return returns <code>SUCCESS</code>
**/
// display is module static function
result_t display(uint16_t value)
{
if (value &1) call Leds.yellowOn();
else call Leds.yellowOff();
if (value &2) call Leds.greenOn();
else call Leds.greenOff();
if (value &4) call Leds.redOn();
else call Leds.redOff();
return SUCCESS;
}
/**
* Initialize the component. Initialize ADCControl, Leds
*
* @return returns <code>SUCCESS</code> or <code>FAILED</code>
**/
// implement StdControl interface
command result_t StdControl.init() {
atomic{
txCount = 0;
refData = 0;
resultData = 0;
//txLength = 0;
temp = 0;
msgPtr = dataArray;
}
call Leds.init();
display(0x1+0x2+0x4);
return SUCCESS;
}
/**
* Start the component. Start the clock.
*
* @return returns <code>SUCCESS</code> or <code>FAILED</code>
**/
command result_t StdControl.start() {
call HPLUART.init();
//note:2个定时器的值不能相同,否则会出现问题。个中缘由还不明白
call Timer0.start(TIMER_REPEAT, 2000);
return call Timer1.start(TIMER_REPEAT, 1000);
}
/**
* Stop the component. Stop the clock.
* @return returns <code>SUCCESS</code> or <code>FAILED</code>
**/
command result_t StdControl.stop() {
call HPLUART.stop();
call Timer0.stop();
return call Timer1.stop();
}
//fuction:发送一串长度为Lengh的数据
result_t putMsg(uint8_t* msg,uint8_t Lengh) {
call HPLUART.put(msgPtr[txCount++]);
return SUCCESS;
}
//fuction:比较得到的两个ADC结果,将差值发送至串口
task void dataTask() {
//uint16_t temp;
atomic{
if(refData > resultData) {
temp = refData - resultData;
dataArray[0] = (temp>>8) & 0xFF;
dataArray[1] = (temp) & 0xFF;
//txLength = strlen(msgPtr);
}
}
putMsg(msgPtr,txLength);
call Leds.redToggle();
}
event result_t Timer0.fired() {
return call GasCH0.getData();
}
event result_t Timer1.fired() {
return call GasCH1.getData();
}
// ADC data ready event handler
//function:得到ADC0的数据
async event result_t GasCH0.dataReady(uint16_t data) {
atomic{
refData = data;
}
return SUCCESS;
}
//得到ADC1的数据
async event result_t GasCH1.dataReady(uint16_t data) {
atomic{
resultData = data;
}
post dataTask();
return SUCCESS;
}
//
result_t sendComplete(result_t success) {
if(success)
txCount = 0;
else
putMsg(msgPtr,txLength);
return SUCCESS;
}
async event result_t HPLUART.get(uint8_t data)
{
uint8_t tmp;
atomic tmp = data;
if(1 == tmp) {
call Leds.redToggle();
}
else if(2 == tmp){
call Leds.greenToggle();
}
else if(3 == tmp){
call Leds.yellowToggle();
}
return SUCCESS;
}
async event result_t HPLUART.putDone() {
if (txCount == txLength)
sendComplete(TRUE);
else
sendComplete(FALSE);
return SUCCESS;
}
}