《TinyOS操作系統(tǒng)開發(fā)技術(shù)及實(shí)踐》課件第5章_第1頁(yè)
《TinyOS操作系統(tǒng)開發(fā)技術(shù)及實(shí)踐》課件第5章_第2頁(yè)
《TinyOS操作系統(tǒng)開發(fā)技術(shù)及實(shí)踐》課件第5章_第3頁(yè)
《TinyOS操作系統(tǒng)開發(fā)技術(shù)及實(shí)踐》課件第5章_第4頁(yè)
《TinyOS操作系統(tǒng)開發(fā)技術(shù)及實(shí)踐》課件第5章_第5頁(yè)
已閱讀5頁(yè),還剩120頁(yè)未讀, 繼續(xù)免費(fèi)閱讀

下載本文檔

版權(quán)說明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請(qǐng)進(jìn)行舉報(bào)或認(rèn)領(lǐng)

文檔簡(jiǎn)介

第5章TinyOS應(yīng)用開發(fā)5.1概述5.2TinyOS編程方法5.3串口通信5.4射頻通信5.5ADC信息采集小結(jié)

5.1概述

TinyOS應(yīng)用開發(fā)是學(xué)習(xí)TinyOS的核心,是直接面向用戶的,本章將從以下兩個(gè)方面講解TinyOS的開發(fā)技術(shù):

TinyOS的編程方法:包括在TinyOS開發(fā)過程中所使用的與平臺(tái)相關(guān)的硬件資源的編程方法以及與平臺(tái)相關(guān)的應(yīng)用編程方法。

TinyOS特殊的實(shí)例編程:包括基于CC2530的串口通信、無(wú)線射頻的點(diǎn)對(duì)點(diǎn)通信和CC2530芯片ADC的信息采集。

5.2TinyOS編程方法

由于TinyOS的體系結(jié)構(gòu)采用分層式結(jié)構(gòu),因此TinyOS的編程的基本思想也基于分層結(jié)構(gòu),即上層調(diào)用下層,其分層結(jié)構(gòu)大致可以分為底層驅(qū)動(dòng)層、中間層和應(yīng)用層,其結(jié)構(gòu)如圖5-1所示。圖5-1TinyOS編程分層結(jié)構(gòu)

5.3串口通信

本節(jié)將講解TinyOS操作系統(tǒng)的CC2530與PC機(jī)串口通信,包括CC2530串口的配置、串口通信相關(guān)組件及接口的使用以及TinyOS操作系統(tǒng)下串口通信協(xié)議的分析。另外本節(jié)還通過兩個(gè)串口的實(shí)例講解串口的用法。

5.3.1串口配置

在TinyOS操作系統(tǒng)中,平臺(tái)采用的芯片配置同樣由組件和接口來(lái)完成。本書中采用CC2530的串口0進(jìn)行傳輸,完成CC2530串口相關(guān)配置的組件為底層組件HplCC2530UartP組件。HplCC2530UartP組件位于“cygwin\opt\mytinyos\tos\chips\cc2530\uart\”目錄中,其主要代碼如代碼5-1所示?!敬a5-1】HplCC2530UartP.nc

moduleHplCC2530UartP

{

//串口初始化接口

providesinterfaceInitasUart0Init;

//TX控制接口

providesinterfaceStdControlasUart0TxControl;

//RX控制接口

providesinterfaceStdControlasUart0RxControl;

//串口發(fā)送接收設(shè)置接口

providesinterfaceHplCC2530UartasHplUart0;

usesinterfaceMcuPowerState;

}在HplCC2530UartP文件中對(duì)串口進(jìn)行初始化,并且設(shè)置了用戶所需要的波特率。在本節(jié)內(nèi)容中,將波特率設(shè)置為57600,具體代碼如代碼5-2所示?!敬a5-2】HplCC2530UartP.nc

/*串口的初始化*/

commanderror_tUart0Init.init()

{

//采用串口備用位置1

PERCFG&=~0x01;

//選擇P0口作為串口

P0SEL=0x3c;//00111100

//采用UART模式,接收使能

U0CSR|=0x80|0x40;

/*串口波特率的設(shè)置采用57600*/

U0GCR=0x0b;

U0BAUD=216;

returnSUCCESS;

}5.3.2通信幀格式

TinyOS2.x為串口通信提供了專用通信協(xié)議,即HDLC協(xié)議幀,其以0x7e作為幀分隔字符,0x7d作為轉(zhuǎn)義字符。在TinyOS2.x的串口通信組件中維護(hù)了10個(gè)狀態(tài)位,接收路徑和發(fā)送路徑各有一個(gè)狀態(tài)位,用于表示是否使用轉(zhuǎn)義符(有關(guān)HDLC幀格式以及相關(guān)內(nèi)容請(qǐng)參照實(shí)踐4的知識(shí)拓展)。

TinyOS2.x串口協(xié)議數(shù)據(jù)幀具體格式如圖5-2所示。圖5-2串口協(xié)議數(shù)據(jù)幀格式5.3.3相關(guān)組件及接口

TinyOS2.x版本的串口協(xié)議??梢詣澐譃?個(gè)功能組件,自底層至上層分別是原始串口組件、編碼/裝幀組件、協(xié)議組件、分派組件和用戶接口組件。其組件關(guān)系如圖5-3所示。圖5-3串口組件關(guān)系

1.原始串口組件

在TinyOS2.x版本中原始串口組件為串口的硬件接口層組件,位于平臺(tái)目錄tos/platforms下。一般情況此組件的命名與平臺(tái)相關(guān),不同的平臺(tái)命名方式不同。本書以mytinyos平臺(tái)為例講解。

原始串口組件在mytinyos平臺(tái)中名為PlatformSerialC,其位于“mytinyos\tos\platforms\cc2530”目錄下。在項(xiàng)目的開發(fā)過程中,可以調(diào)用此組件通過串口直接將硬件平臺(tái)的數(shù)據(jù)輸出至PC機(jī),即數(shù)據(jù)并沒有被TinyOS封裝成串口數(shù)據(jù)幀格式。此組件提供的接口如代碼5-3所示。【代碼5-3】PlatformSerialC.nc

configurationPlatformSerialC

{

providesinterfaceStdControl;

providesinterfaceUartStream;

providesinterfaceUartByte;

}其中各個(gè)接口的作用如下:

StdControl:開啟串口。

UartStream:控制發(fā)送接收字節(jié)。

UartStream:發(fā)送和接收字節(jié)流。

以下內(nèi)容將實(shí)現(xiàn)任務(wù)描述5.D.1,使用PlatformSerialC組件實(shí)現(xiàn)CC2530與PC機(jī)的串口通信。按照TinyOS的編程方法,首先要編寫主組件與頂層配件,其次編寫其他組件與Makefile文件。此任務(wù)中需要完成以下工作:

首先在“mytinyos/apps”目錄下新建一個(gè)名為DhSerial的文件夾。

其次,在DhSerial文件夾創(chuàng)建頂層配件DhSerialAppC,核心應(yīng)用模塊命名為DhSerialC.nc,在核心應(yīng)用模塊組件中使用PlatformSerialC中的接口進(jìn)行串口傳輸。

最后編寫Makefile文件。

編譯程序,下載至設(shè)備中,連接串口,觀察現(xiàn)象。

(1)創(chuàng)建DhSerial文件夾。

打開Cygwin,在“mytinyos/apps”目錄下,輸入mkdirDhSerial,創(chuàng)建文件夾,具體操作如圖5-4所示。圖5-4創(chuàng)建DhSerial文件夾

(2)創(chuàng)建DhSerialAppC.nc。

DhSerialAppC.nc為整個(gè)任務(wù)的頂層配件組件,在此組件中實(shí)現(xiàn)了組件之間的綁定關(guān)系。其具體代碼如描述5.D.1DhSerialAppC.nc所示?!久枋?.D.1】DhSerialAppC.nc

configurationDhSerialAppC

{

}

implementation

{

componentsDhSerialC;

componentsMainC;

DhSerialC.Boot->MainC.Boot;

componentsPlatformSerialC;

DhSerialC.StdControl->PlatformSerialC.StdControl;

DhSerialC.UartStream->PlatformSerialC.UartStream;

}在此組件中主要做了以下兩個(gè)工作:

在此組件中將DhSerialC組件的啟動(dòng)接口與系統(tǒng)的系統(tǒng)的啟動(dòng)接口綁定在一起,當(dāng)系統(tǒng)啟動(dòng)時(shí)將調(diào)用DhSerialC組件的啟動(dòng)接口,使整個(gè)程序啟動(dòng)起來(lái)。

將DhSerialC組件的與串口相關(guān)的接口綁定到PlatformSerialC組件上,以便于進(jìn)行串口的傳輸。

(3)創(chuàng)建DhSerialC.nc。

DhSerialC.nc組件是整個(gè)任務(wù)的核心應(yīng)用模塊,在此組件中通過UartStream接口實(shí)現(xiàn)了CC2530與PC機(jī)的串口通信,具體代碼如描述5.D.1DhSerialC.nc所示?!久枋?.D.1】DhSerialC.nc

moduleDhSerialC

{ uses

{ interfaceBoot;

interfaceStdControl;

interfaceUartStream;

}

}

implementation

{ uint8_tm_send_buf[100];

voidshowMenu()

{ strcpy(m_send_buf,"qingdaodonghexinxi");

//通過UartStream.send可以發(fā)送字節(jié)數(shù)據(jù)

callUartStream.send(m_send_buf,strlen(m_send_buf));

} /*啟動(dòng)事件處理函數(shù)*/

eventvoidBoot.booted()

{ callStdControl.start();

showMenu();

}

asynceventvoidUartStream.sendDone(uint8_t*buf,uint16_tlen,error_terror)

{

}

/**重新發(fā)送剛才接收的字符進(jìn)行回顯*/

taskvoidshowMenuTask()

{ showMenu();

} /**如果沒有調(diào)用receive接收,則每接收到一個(gè)數(shù)據(jù)就會(huì)觸發(fā)此事件*/

asynceventvoidUartStream.receivedByte(uint8_tbyte)

{

}

/*在接收完receive命令欲接收的長(zhǎng)度后會(huì)調(diào)用此事件*/

asynceventvoidUartStream.receiveDone(uint8_t*buf,uint16_tlen,error_terror)

{

}

}

(4)編寫Makefile文件。

在Makefile文件中指明任務(wù)的頂層配件,并規(guī)定編譯規(guī)則,其具體代碼如描述5.D.1Makefile文件所示。

【描述5.D.1】Makefile文件

COMPONENT=DhSerialAppC

CFLAGS+=-I$(TOSDIR)/lib/T2Hack

include$(MAKERULES)

(5)實(shí)驗(yàn)結(jié)果。

將設(shè)備通過串口線連接至PC機(jī),將程序編譯下載至設(shè)備中,打開串口,將波特率配置為57600,按下復(fù)位按鍵,可以觀察到CC2530向PC機(jī)通過串口傳送“qingdaodonghexinxi”的字符串。實(shí)驗(yàn)結(jié)果如圖5-5所示。圖5-5任務(wù)描述5.D.1實(shí)驗(yàn)結(jié)果

2.編碼/裝幀組件

編碼裝幀組件是通過HdlcTranslateC組件來(lái)實(shí)現(xiàn)的,此組件主要負(fù)責(zé)串口協(xié)議的中的起始和結(jié)束幀字節(jié)F。HdlcTranslateC組件位于“cygwin\opt\mytinyos\tos\lib\serial”目錄下,其主要代碼如代碼5-4所示。【代碼5-4】HdlcTranslateC.nc

moduleHdlcTranslateC

{

providesinterfaceSerialFrameComm;

uses{

interfaceUartStream;

interfaceLeds;

}

}在HdlcTranslateC組件中向上層提供了SerialFrameComm接口,在SerialFrameComm接口完成了一個(gè)串口數(shù)據(jù)幀的裝幀任務(wù),即在數(shù)據(jù)幀頭和幀尾添加開始和結(jié)束幀字節(jié)F(0x7e)。

向下層調(diào)用PlatformSerialC組件提供的UartStream接口完成串口傳輸。

其組件關(guān)系圖如圖5-6所示。

SerialFrameComm接口用于分隔協(xié)議數(shù)據(jù)幀,其中SerialFrameComm接口的具體代碼如代碼5-5所示。圖5-6HdlcTranslateC組件關(guān)系圖【代碼5-5】SerialFrameComm.nc

interfaceSerialFrameComm

{ asynccommanderror_tputDelimiter();

asynccommanderror_tputData(uint8_tdata);

asynccommandvoidresetSend();

asynccommandvoidresetReceive();

asynceventvoiddelimiterReceived();

asynceventvoiddataReceived(uint8_tdata);

asynceventvoidputDone();

}

3.協(xié)議組件

協(xié)議組件是通過SerialP組件來(lái)實(shí)現(xiàn)的,此組件主要用來(lái)實(shí)現(xiàn)串口通信協(xié)議的協(xié)議字節(jié)和P和序號(hào)字節(jié)S,本書中的協(xié)議字節(jié)取值為Serial.h文件中的SERIAL_PROTO_PACKET_NOACK。

SerialP組件位于“mytinyos\tos\lib\serial”目錄下,其主要代碼如代碼5-6所示?!敬a5-6】SerialP.nc

moduleSerialP{

provides

{ interfaceInit;

interfaceSplitControl;

interfaceSendBytePacket;

interfaceReceiveBytePacket;

}

uses

{ interfaceSerialFrameComm;

interfaceLeds;

interfaceStdControlasSerialControl;

interfaceSerialFlush;

}

}

SerialP組件提供兩個(gè)面向字節(jié)的接口,即SendBytePacket接口和ReceiveBytePacket接口,分別用于數(shù)據(jù)的發(fā)送和接收。

從節(jié)點(diǎn)發(fā)送到主機(jī)時(shí),SerialP組件負(fù)責(zé)封裝上層組件(分派組件)的數(shù)據(jù)包。上層組件通過調(diào)用SendBytePacket接口的startSend命令來(lái)初始化數(shù)據(jù)包的發(fā)送工作。

從主機(jī)發(fā)送到節(jié)點(diǎn)時(shí),即節(jié)點(diǎn)處于接收狀態(tài),上層組件通過調(diào)用ReceiveBytePacket接口接收數(shù)據(jù)。

4.分派組件

分派組件是通過SerialDispatcherC組件來(lái)實(shí)現(xiàn)的,SerialDispatcherC組件負(fù)責(zé)處理協(xié)議組件接收到的數(shù)據(jù)包,它通過SerialDispatcherP組件使用SerialP組件提供的SendBytePacket接口和ReceiveBytePacket接口,并提供帶參數(shù)的Send接口和Receive接口。這兩個(gè)接口的參數(shù)為串口協(xié)議的包格式分派字節(jié)D,它決定了message_t中的數(shù)據(jù)包格式。SerialDispatcherC組件位于“mytinyos/tos/lib/serial”目錄下,代碼如代碼5-7所示。【代碼5-7】SerialDispatcherC.nc

configurationSerialDispatcherC

{ provides

{ interfaceInit;

interfaceSplitControl;

interfaceReceive[uart_id_t];

interfaceSend[uart_id_t];

}

uses

{ interfaceSerialPacketInfo[uart_id_t];

interfaceLeds;

}

}implementation

{

componentsSerialP,newSerialDispatcherP(),

HdlcTranslateC,

PlatformSerialC;

Send=SerialDispatcherP;

Receive=SerialDispatcherP;

SerialPacketInfo=SerialDispatcherP.PacketInfo;

SplitControl=SerialP;

Init=SerialP;

Leds=SerialP;

Leds=SerialDispatcherP;

Leds=HdlcTranslateC;

SerialDispatcherP.ReceiveBytePacket->SerialP;

SerialDispatcherP.SendBytePacket->SerialP;

SerialP.SerialFrameComm->HdlcTranslateC;

SerialP.SerialControl->PlatformSerialC;

HdlcTranslateC.UartStream->PlatformSerialC;

}通過上述代碼可以看出,SerialDispatcherC組件連接到了前述原始串口組件PlatformSerialC。另外SerialDispatcherC組件經(jīng)過SerialP組件收發(fā)的數(shù)據(jù)包中放置了一個(gè)字節(jié)的包頭,即包格式標(biāo)識(shí)符。其具體值采用SerialDispacherC組件的uart_id_t參數(shù)值TOS_SERIAL_ACTIVE_MESSAGE_ID。

通過帶參數(shù)的SerialPacketInfo接口、SerialDispatcherC組件能夠處理各種各樣的數(shù)據(jù)包格式,SerialPacketInfo接口具體代碼如代碼5-8所示。

【代碼5-8】SerialPacketInfo.nc

interfaceSerialPacketInfo

{

asynccommanduint8_toffset();

asynccommanduint8_tdataLinkLength(message_t*msg,uint8_tupperLen);

asynccommanduint8_tupperLength(message_t*msg,uint8_tdataLinkLen);

}

其中此命令的各個(gè)接口的功能描述如下:

offset():獲得包頭在message_t中的偏移量。發(fā)送數(shù)據(jù)時(shí):SerialDispatcherC組件先發(fā)送數(shù)據(jù)包類型,然后再導(dǎo)出數(shù)據(jù)字節(jié),起始位置由調(diào)用offest()函數(shù)獲得的索引值確定。

接收數(shù)據(jù)時(shí):當(dāng)SerialDisPatcherC組件收到由SerialP組件發(fā)出第一個(gè)字節(jié)時(shí),先將其保存為數(shù)據(jù)包類型,同時(shí)調(diào)用offSet()命令以便在message_t中確定偏移量,然后將數(shù)據(jù)字節(jié)導(dǎo)入并填充到message_t的緩沖區(qū)。

dataLinkLength():根據(jù)已知upperLen,獲得下層傳輸?shù)膁ataLinkLen,等于upperLen+包頭大小。

upperLength():根據(jù)已知upperLen,獲得下層傳輸?shù)膁ataLinkLen,等于upperLen+包頭大小。

5.用戶接口組件

在實(shí)際編程時(shí),官方推薦使用SerialActiveMessageC組件進(jìn)行串口編程。SerialActiveMessageC組件是一個(gè)平臺(tái)無(wú)關(guān)的主動(dòng)消息組件,工作在串口通信協(xié)議棧之上,它是一個(gè)配件,將SerialActiveMessageP組件連接到SerialDispatcherC組件(最終再連接到原始串口組件PlatformSerialC)。

SerialActiveMessageP組件是一個(gè)通用組件,因此可用于各種數(shù)據(jù)包級(jí)的通信層之上,在此組件中可以根據(jù)需要是否設(shè)定發(fā)送信息的源地址、目的地址及組號(hào)。

(1)?SerialActiveMessageC.nc。

SerialActiveMessageC組件位于“mytinyos\tos\lib\serial”目錄下,其具體代碼如代碼5-9所示?!敬a5-9】SerialActiveMessageC.nc

#include"Serial.h"

configurationSerialActiveMessageC

{ provides

{ interfaceSplitControl;

interfaceAMSend[am_id_tid];

interfaceReceive[am_id_tid];

interfacePacket;

interfaceAMPacket;

interfacePacketAcknowledgements;

}

usesinterfaceLeds;

}implementation

{ componentsnewSerialActiveMessageP()asAM,SerialDispatcherC;

componentsSerialPacketInfoActiveMessagePasInfo,MainC;

MainC.SoftwareInit->SerialDispatcherC;

Leds=SerialDispatcherC;

SplitControl=SerialDispatcherC;

AMSend=AM;

Receive=AM;

Packet=AM;

AMPacket=AM; PacketAcknowledgements=AM;

AM.SubSend->SerialDispatcherC.Send[TOS_SERIAL_ACTIVE_MESSAGE_ID];

AM.SubReceive->SerialDispatcherC.Receive[TOS_SERIAL_ACTIVE_MESSAGE_ID];

SerialDispatcherC.SerialPacketInfo[TOS_SERIAL_ACTIVE_MESSAGE_ID]->Info;

}

此組件將SerialPackerInfoActiveMessageP組件連接到SerialDispatcherC組件,其中SerialDispatcherC組件的uart_id_t參數(shù)是TOS_SERIAL_ACTIVE_MESSAGE_ID,其定義在serial.h文件中,定義如代碼5-10所示。【代碼5-10】serial.h

#ifndefSERIAL_H

#defineSERIAL_H

#include"AM.h"

typedefuint8_tuart_id_t;

enum

{ //包格式分派字節(jié)

TOS_SERIAL_ACTIVE_MESSAGE_ID=0,

TOS_SERIAL_CC1000_ID=1,

TOS_SERIAL_802_15_4_ID=3,

TOS_SERIAL_UNKNOWN_ID=255,

};

(2)?SerialActiveMessageP.nc。

SerialActiveMessageP組件位于“mytinyos\tos\lib\serial”目錄下,其具體代碼如代碼5-11所示。【代碼5-11】SerialActiveMessageP.nc

#include<Serial.h>

genericmoduleSerialActiveMessageP()

{ provides

{ interfaceAMSend[am_id_tid];

interfaceReceive[am_id_tid];

interfaceAMPacket;

interfacePacket;

interfacePacketAcknowledgements;

} uses

{ interfaceSendasSubSend;

interfaceReceiveasSubReceive;

}

}

implementation

{

serial_header_t*ONEgetHeader(message_t*ONEmsg)

{

returnTCAST(serial_header_t*ONE,(uint8_t*)msg+offsetof(message_t,data)-sizeof(serial_header_t));

} serial_metadata_t*getMetadata(message_t*msg)

{

return(serial_metadata_t*)(msg->metadata);

}

commanderror_tAMSend.send[am_id_tid](am_addr_tdest,

message_t*msg,

uint8_tlen)

{ serial_header_t*header=getHeader(msg);

if(len>callPacket.maxPayloadLength())

{ returnESIZE;

} header->dest=dest;

/*為了防止通信有問題,找到更好的解決辦法,暫時(shí)不設(shè)定源地址和組ID*/

//header->src=callAMPacket.address();

//header->group=TOS_AM_GROUP;

header->type=id;

header->length=len;

returncallSubSend.send(msg,len);

}

在此組件中設(shè)定了串口通信消息的頭部格式,即目的地址、源地址、組ID、長(zhǎng)度、消息類型。但是由于串口傳輸還不是很完善,因此TinyOS開發(fā)組為了找到較好的通信方案,可以先不賦予消息的源地址和組ID號(hào)。5.3.4串口編程

以下內(nèi)容將實(shí)現(xiàn)任務(wù)描述5.D.2,使用TinyOS串口協(xié)議實(shí)現(xiàn)CC2530與PC機(jī)的串口通信,并分析其數(shù)據(jù)。完成此任務(wù)中需要完成以下工作:

首先在mytinyos/apps目錄下新建一個(gè)名為TestSerial的文件夾(參照任務(wù)5.D.1)。

其次在TestSerial文件夾創(chuàng)建頂層配件TestSerialAppC,主組件命名為TestSerialC.nc,并編寫程序。在TestSerialC組件中主要使用SerialActiveMessageC組件的接口來(lái)實(shí)現(xiàn)串口通信。

編寫Makefile文件。

編譯程序,下載至設(shè)備中,連接串口,觀察現(xiàn)象并分析數(shù)據(jù)。

1.?TestSerialAppC.nc

TestSerialAppC.nc為整個(gè)任務(wù)的頂層配件組件,在此組件中實(shí)現(xiàn)了組件之間的綁定關(guān)系。其具體代碼如描述5.D.2TestSerialAppC.nc所示。【描述5.D.2】TestSerialAppC.nc

#include"TestSerial.h"

configurationTestSerialAppC{}

implementation{

componentsTestSerialCasApp,LedsC,MainC;

componentsSerialActiveMessageCasAM;

componentsnewTimerMilliC();

App.Boot->MainC.Boot;

App.Control->AM;

App.Receive->AM.Receive[AM_TEST_SERIAL_MSG];

App.AMSend->AM.AMSend[AM_TEST_SERIAL_MSG];

App.Leds->LedsC;

App.MilliTimer->TimerMilliC;

App.Packet->AM;

}在此組件中使用了MainC組件、LedsC組件、SerialActiveMessageC組件和TimerMillic組件,其中綁定關(guān)系如下:

TestSerialC組件的Boot接口綁定到MainC組件上。

TestSerialC組件的Control接口、Receive接口、AMSend接口綁定到SerialActiveMessageC組件上。

TestSerialC組件的Leds接口綁定到LedsC組件上,定時(shí)器MilliTimer接口綁定到TimerMilliC組件上。

2.?TestSerialC.nc

TestSerialC組件是整個(gè)任務(wù)的主組件,在此組件中通過串口數(shù)據(jù)包負(fù)載部分的封裝以及發(fā)送,具體代碼如描述5.D.2TestSerialC.nc所示?!久枋?.D.2】TestSerialC.nc

#include"Timer.h"

#include"TestSerial.h"

moduleTestSerialC

{

uses

{

interfaceSplitControlasControl;

interfaceLeds;

interfaceBoot;

interfaceReceive;

interfaceAMSend;

interfaceTimer<TMilli>asMilliTimer;

interfacePacket;

}

}implementation

{

message_tpacket;

boollocked=FALSE;

uint16_tcounter=0;

eventvoidBoot.booted()

{

callControl.start();

}

eventvoidMilliTimer.fired()

{

counter++;

if(locked)

{

return;

} else

{

//在要發(fā)送的數(shù)據(jù)前面添加數(shù)據(jù)幀頭

test_serial_msg_t*rcm=(test_serial_msg_t*)call Packet.getPayload(&packet,sizeof(test_serial_msg_t));

if(rcm==NULL)

{

return;

}

if(callPacket.maxPayloadLength()<sizeof(test_serial_msg_t))

{ return;

}

//要發(fā)送的數(shù)據(jù)

rcm->counter=counter;

//調(diào)用發(fā)送函數(shù)將數(shù)據(jù)發(fā)送至PC機(jī)

if(callAMSend.send(AM_BROADCAST_ADDR,&packet, sizeof(test_serial_msg_t))==SUCCESS)

{

callLeds.led0On();

locked=TRUE;

}

}

} eventmessage_t*Receive.receive(message_t*bufPtr,

void*payload,uint8_tlen)

{

}

//發(fā)送數(shù)據(jù)完成之后,觸發(fā)AMSend.sendDone事件

eventvoidAMSend.sendDone(message_t*bufPtr,error_terror)

{

if(&packet==bufPtr)

{

//點(diǎn)亮LED2

callLeds.led1On();

locked=FALSE;

}

} eventvoidControl.startDone(error_terr)

{

if(err==SUCCESS)

{

callMilliTimer.startPeriodic(1000);

}

}

eventvoidControl.stopDone(error_terr)

{

}

}

3.?TestSerial.h

除了TestSerialAppC組件和TestSerialC組件之外,還需要編寫TestSerial.h。在TestSerial.h文件中定義了串口傳送消息的AM類型以及要傳送數(shù)據(jù)的結(jié)構(gòu)體,其具體代碼如描述5.D.2TestSerial.h所示?!久枋?.D.2】TestSerial.h

#ifndefTEST_SERIAL_H

#defineTEST_SERIAL_H

typedefnx_structtest_serial_msg{

nx_uint16_tcounter;

}test_serial_msg_t;

enum{

AM_TEST_SERIAL_MSG=0x89,//AM類型

};

#endif

4.?Makefile文件

在Makefile文件中指明任務(wù)的頂層配件,并規(guī)定編譯規(guī)則,其具體代碼如描述5.D.2Makefile文件所示。

【描述5.D.2】Makefile文件

COMPONENT=TestSerialAppC

include$(MAKERULES)

5.實(shí)驗(yàn)結(jié)果

將程序編譯下載至設(shè)備中,并將設(shè)備通過串口連接線與PC機(jī)相連,,打開串口,將波特率配置為57600,按下復(fù)位按鍵,可以觀察到CC2530向PC機(jī)通過串口傳送數(shù)據(jù)。實(shí)驗(yàn)結(jié)果如圖5-7所示。圖5-7串口通信結(jié)果其中,接收到15個(gè)字節(jié)的數(shù)據(jù),按照串口協(xié)議包的格式分析如下:

第1個(gè)字節(jié)0x7E為幀字節(jié)。

第2個(gè)字節(jié)0x45為協(xié)議字節(jié)。

第3個(gè)字節(jié)0x00為包格式分派字節(jié),之后從0xFF~0x01為Payload載荷區(qū),其中:

第4~5字節(jié)0xFFFF為目的地址。

第6~7字節(jié)0x0000為源地址,因?yàn)樵诔绦蛑蝎@得的源地址返回值為“0”,所以源地址為0x0000。第8個(gè)字節(jié)0x02為傳輸數(shù)據(jù)的長(zhǎng)度。

第9個(gè)字節(jié)0x00為組ID,因?yàn)楸纠虥]有規(guī)定確切的組ID,因此返回值為0x00。

第10個(gè)字節(jié)0x89為串口數(shù)據(jù)包的AM類型。

第11~12個(gè)字節(jié)為傳輸?shù)臄?shù)據(jù)。

第13~14個(gè)字節(jié)為CRC的校驗(yàn)值。

第15個(gè)字節(jié)為數(shù)據(jù)包的結(jié)束字節(jié),一般為0x7E。

5.4射頻通信

在TinyOS系統(tǒng)中,無(wú)線通信模型是基于主動(dòng)消息模式的通信模型。主動(dòng)消息模式是一個(gè)面向消息通信的高性能通信模式。在無(wú)線傳感器網(wǎng)絡(luò)中采用主動(dòng)消息機(jī)制的主要目的是使無(wú)線傳感器節(jié)點(diǎn)的計(jì)算和通信重疊,讓軟件層的通信原語(yǔ)能夠與節(jié)點(diǎn)的硬件能力匹配,充分節(jié)省無(wú)線傳感器節(jié)點(diǎn)的有限存儲(chǔ)空間。

本節(jié)內(nèi)容將介紹主動(dòng)消息機(jī)制、無(wú)線射頻通信的相關(guān)接口和組件以及點(diǎn)對(duì)點(diǎn)無(wú)線傳輸程序的編寫。5.4.1主動(dòng)消息概述

在主動(dòng)消息通信方式中,每個(gè)消息都維護(hù)一個(gè)應(yīng)用層的子程序。當(dāng)目標(biāo)節(jié)點(diǎn)接收到這個(gè)消息后,就會(huì)把消息中的數(shù)據(jù)作為參數(shù),并傳遞給應(yīng)用層的子程序進(jìn)行處理,應(yīng)用層的子程序一般完成消息數(shù)據(jù)包的解包操作、計(jì)算處理或發(fā)送響應(yīng)消息等工作。

為了讓主動(dòng)消息更適合無(wú)線傳感器網(wǎng)絡(luò)的需求,主動(dòng)消息需要至少提供兩個(gè)最基本的通信機(jī)制:

帶確認(rèn)信息的消息傳遞:當(dāng)消息發(fā)送成功后,接收方會(huì)發(fā)送一個(gè)確認(rèn)幀進(jìn)行數(shù)據(jù)接收確認(rèn)。有明確的消息地址和消息分發(fā):發(fā)送一條消息必須有明確的消息接收者和消息發(fā)送者。

在TinyOS系統(tǒng)中主動(dòng)消息通信機(jī)制的實(shí)現(xiàn)可以通過系統(tǒng)通信組件來(lái)實(shí)現(xiàn),用戶可以通過調(diào)用系統(tǒng)組件實(shí)現(xiàn)高層的通信組件。5.4.2相關(guān)組件及接口

TinyOS系統(tǒng)提供了很多與底層通信相關(guān)接口,并提供了實(shí)現(xiàn)這些接口的組件,其中最常用的組件有AMSenderC組件、AMReceiverC組件、ActiveMessageC組件等。這些接口組件都使用一個(gè)共同的消息緩存區(qū),稱為message_t。

1.?message_t

message_t是一個(gè)抽象的數(shù)據(jù)類型,通常被作為通信底層的數(shù)據(jù)結(jié)構(gòu),其定義在C:\cygwin\opt\mytinyos\tos\chips\cc2530\net\types目錄下的message.h文件中,其具體代碼如代碼5-12所示?!敬a5-12】message.h

typedefnx_structmessage_t

{

nx_uint8_theader[sizeof(message_header_t)];

nx_uint8_tdata[TOSH_DATA_LENGTH];

nx_uint8_tfooter[sizeof(message_footer_t)];

nx_uint8_tmetadata[sizeof(message_metadata_t)];

}message_t;其中,message_t中有四個(gè)元素,每個(gè)元素的說明如下:

header:為消息的頭部。

data:為有效載荷去,即數(shù)據(jù)。

footer:為消息的尾部。

metadata:為元數(shù)據(jù)。

其中header、footer和metadata都是不透明的,不能直接訪問,而data字段的訪問必須通過Packet接口、AMPacket接口或其他一些接口。

2.?AMSenderC.nc

AMSenderC組件用于數(shù)據(jù)的發(fā)送,此組件所在目錄為“cygwin\opt\tinyos-2.x\tos\system”,其代碼如代碼5-13所示。【代碼5-13】AMSenderC.nc

genericconfigurationAMSenderC(am_id_tAMId)

{

provides

{

interfaceAMSend;

interfacePacket;

interfaceAMPacket;

interfacePacketAcknowledgementsasAcks;

}

}

implementation

{

……

}其中:

AMSend接口:是基本主動(dòng)消息的發(fā)送接口,AMSend接口在發(fā)送命令里指定了AM目標(biāo)地址。

Packet接口:提供對(duì)message_t抽象數(shù)據(jù)類型的基本訪問。

AMPacket接口:類似與Packet接口,提供對(duì)message_t抽象數(shù)據(jù)類型的AM訪問。

PacketAknowledgements接口:提供信息確認(rèn)機(jī)制接口,提供確認(rèn)幀請(qǐng)求和發(fā)送。

在實(shí)際編寫程序中,應(yīng)用層可以直接調(diào)用AMSenderC組件進(jìn)行數(shù)據(jù)的發(fā)送,其發(fā)送數(shù)據(jù)過程示例如示例5-1所示。

【示例5-1】發(fā)送示例

//要發(fā)送數(shù)據(jù)的結(jié)構(gòu)體

typedefnx_structBlinkToRadioMsg

{

nx_uint16_tnodeid;

nx_uint16_tcounter;

}BlinkToRadioMsg;

message_tpkt;BlinkToRadioMsg*btrpkt;

//調(diào)用Packet獲得發(fā)送數(shù)據(jù)的載荷部分

btrpkt=(BlinkToRadioMsg*)callPacket.getPayload(&pkt,sizeof(BlinkToRadioMsg));

btrpkt->nodeid=TOS_NODE_ID;

btrpkt->counter=counter++;

//調(diào)用AMSend接口將數(shù)據(jù)發(fā)送出去

if(callAMSend.send(AM_BROADCAST_ADDR,&pkt,sizeof(BlinkToRadioMsg))==SUCCESS)

{

callLeds.led0Toggle();

}

3.?AMReceiverC.nc

AMReceiverC組件用于數(shù)據(jù)的接收,此組件所在目錄為cygwin\opt\tinyos-2.x\tos\system,具體代碼如代碼5-14所示。

【代碼5-14】AMReceiverC.nc

genericconfigurationAMReceiverC(am_id_tamId)

{

provides

{

interfaceReceive;

interfacePacket;

interfaceAMPacket;

}

}其中:

Receive接口:最基本的消息接收接口,提供了接收消息時(shí)觸發(fā)的事件函數(shù)。

Packet接口:同AMSender.Packet接口,提供message_t抽象類型的基本訪問。

AMPacket接口:同AMSender.AMPacket接口。

針對(duì)于示例5-1中的發(fā)送示例的接收部分如示例5-2所示。【示例5-2】

接收示例

/*當(dāng)有數(shù)據(jù)需要接收時(shí),將會(huì)觸發(fā)接收事件*/

eventmessage_t*Receive.receive(message_t*msg,void*payload,uint8_tlen)

{

//如果接收到數(shù)據(jù)長(zhǎng)度與要發(fā)送的數(shù)據(jù)長(zhǎng)度相同將執(zhí)行LED閃爍命令

if(len==sizeof(BlinkToRadioMsg))

{

callLeds.led2Toggle();

}

returnmsg;

}

4.?ActiveMessageAddressC.nc

ActiveMessageAddressC組件提供獲得和設(shè)定節(jié)點(diǎn)的地址,位于cygwin\opt\tinyos-2.x\tos\system,具體代碼如代碼5-15所示?!敬a5-15】ActiveMessageAddressC.nc

moduleActiveMessageAddressC@safe()

{

provides

{

interfaceActiveMessageAddress;

asynccommandam_addr_tamAddress();

asynccommandvoidsetAmAddress(am_addr_ta);

}

}其中,ActiveMessageAddress:提供獲得和設(shè)定節(jié)點(diǎn)AM地址的命令,但是通常情況下不建議使用此接口,因?yàn)樾薷腁M地址可能會(huì)破壞網(wǎng)絡(luò)堆棧。

5.?ActiveMessageC.nc

ActiveMessageC組件是一個(gè)與平臺(tái)相關(guān)的組件,該組件提供了發(fā)送接收接口。以上講述的AMSenderC組件、AMReceiverC組件等都是TinyOS系統(tǒng)自帶的組件。而ActiveMessageC組件將通信相關(guān)接口綁定到底層的相關(guān)硬件驅(qū)動(dòng),不同的平臺(tái)其實(shí)現(xiàn)形式不同。在mytinyos平臺(tái)中此組件位于cygwin\opt\mytinyos\tos\platforms\cc2530目錄下,具體代碼如代碼5-16所示?!敬a5-16】ActiveMessageC.nc

configurationActiveMessageC

{

provides

{

interfaceSplitControl;

interfaceAMSend[uint8_tid];

interfaceReceive[uint8_tid];

interfaceReceiveasSnoop[uint8_tid];

interfaceSendNotifier[am_id_tid];

interfacePacket;

interfaceAMPacket;

interfacePacketAcknowledgements;

interfaceLowPowerListening;

interfacePacketLink;

interfacePacketTimeStamp<TRadio,uint32_t>asPacketTimeStampRadio;

interfacePacketTimeStamp<TMilli,uint32_t>asPacketTimeStampMilli;

}

}

ActiveMessageC組件集AMSenderC組件和AMReceiveC組件的功能于一體,既能實(shí)現(xiàn)數(shù)據(jù)的發(fā)送又能實(shí)現(xiàn)數(shù)據(jù)的接收,因此一般在實(shí)際的開發(fā)過程中建議使用ActiveMessageC組件進(jìn)行編程。其中以下的任務(wù)描述5.D.3就使用ActiveMessageC組件進(jìn)行數(shù)據(jù)的發(fā)送與接收。5.4.3點(diǎn)對(duì)點(diǎn)傳輸

以下內(nèi)容將實(shí)現(xiàn)任務(wù)描述5.D.3,使用兩個(gè)CC2530節(jié)點(diǎn)進(jìn)行點(diǎn)對(duì)點(diǎn)通信,并通過數(shù)據(jù)的發(fā)送和接收控制LED閃爍。完成此任務(wù)中需要完成以下工作:

首先在mytinyos/apps目錄下新建一個(gè)名為BlinkToRadio的文件夾(參照任務(wù)5.D.1)。

其次在BlinkToRadio的文件夾創(chuàng)建頂層配件BlinkToRadioAppC,主組件命名為BlinkToRadioC.nc,在BlinkToRadioC.nc組件中使用ActiveMessageC組件提供的發(fā)送和接收等接口實(shí)現(xiàn)數(shù)據(jù)的通信。

編寫Makefile文件。

編譯程序,下載至設(shè)備中,連接串口,觀察現(xiàn)象并分析數(shù)據(jù)。

1.?BlinkToRadioAppC.nc

BlinkToRadioAppC.nc為整個(gè)任務(wù)的頂層配件組件,在此組件中實(shí)現(xiàn)了組件之間的綁定關(guān)系。其具體代碼如描述5.D.3BlinkToRadioAppC.nc所示?!久枋?.D.3】BlinkToRadioAppC.nc

#include<Timer.h>

#include“BlinkToRadio.h”

configurationBlinkToRadioAppC

{

}

implementation

{

componentsMainC;

componentsLedsC;

componentsBlinkToRadioCasApp;

componentsnewTimerMilliC()asTimer0;

componentsActiveMessageC; App.Boot->MainC.Boot;

App.Leds->LedsC.Leds;

App.Timer0->Timer0;

App.Packet->ActiveMessageC;

App.AMPacket->ActiveMessageC;

App.AMSend->ActiveMessageC.AMSend[uniqueCount("BlinkToRadio")];

App.AMControl->ActiveMessageC;

App.Receive->ActiveMessageC.Receive[uniqueCount("BlinkToRadio")];

App.PacketAcknowledgements->ActiveMessageC;

}在此組件中使用了MainC組件、LedsC組件、ActiveMessageC組件、TimerMillic組件、AMSenderC組件和AMReceiverC組件,其中綁定關(guān)系如下:

BlinkToRadioC組件的Boot接口綁定到MainC組件上。

BlinkToRadioC組件的Leds接口綁定到LedsC組件上。

定時(shí)器MilliTimer接口綁定到TimerMilliC組件上。

BlinkToRadioC組件的Packet接口、AMPacket接口、AMSend接口、AMControl接口、Receive接口和PacketAckhnowledgements接口綁定到ActiveMessageC組件上。

2.?BlinkToRadioC.nc

BlinkToRadioC組件是整個(gè)任務(wù)的主組件,在此組件中通過串口數(shù)據(jù)包負(fù)載部分的封裝以及發(fā)送,具體代碼如描述5.D.3BlinkToRadioC.nc所示?!久枋?.D.3】BlinkToRadioC.nc

#include<Timer.h>

#include"BlinkToRadio.h"

moduleBlinkToRadioC

{

uses

{

interfaceBoot;

interfaceLeds;

interfaceTimer<TMilli>asTimer0; interfacePacket;

interfaceAMPacket;

interfaceAMSend;

interfaceSplitControlasAMControl;

interfaceReceive;

interfacePacketAcknowledgements;

}

}

implementation

{

boolbusy=FALSE;

message_tpkt;

uint16_tcounter=0; /*程序啟動(dòng)*/

eventvoidBoot.booted()

{

busy=FALSE;

callAMControl.start();

}

/*開啟無(wú)線后開啟定時(shí)任務(wù)*/

eventvoidAMControl.startDone(error_terr)

{

if(err==SUCCESS)

{

callTimer0.startPeriodic(TIMER_PERIOD_MILLI);

}

else

{

callAMControl.start();

}

} eventvoidAMControl.stopDone(error_terr)

{

}

/*定時(shí)事件處理,發(fā)送數(shù)據(jù)*/

eventvoidTimer0.fired()

{

if(!busy)

{

BlinkToRadioMsg*btrpkt;

btrpkt=(BlinkToRadioMsg*)call Packet.getPayload(&pkt,sizeof(BlinkToRadioMsg));

btrpkt->nodeid=TOS_NODE_ID;

btrpkt->counter=counter++;

if(call AMSend.send(AM_BROADCAST_ADDR,&pkt,sizeof(BlinkToRadioMsg))==SUCCESS) {

busy=TRUE;

}

callLeds.led0Toggle();

}

}

/*發(fā)送完成后調(diào)用確認(rèn)幀回復(fù)命令,并開啟LED閃爍命令*/

eventvoidAMSend.sendDone(message_t*msg,error_terror)

{

if(&pkt==msg)

{

callPacketAcknowledgements.requestAck(msg);

callLeds.led1Toggle();

busy=FALSE;

}

} /*接收到數(shù)據(jù)后執(zhí)行LED閃爍命令*/

eventmessage_t*Receive.receive(message_t*msg,void*payload,uint8_tlen)

{

if(len==sizeof(BlinkToRadioMsg))

{

BlinkToRadioMsg*btrpkt=(BlinkToRadioMsg*)payload;

callLeds.led2Toggle();

}

returnmsg;

}

}

3.?BlinkToRadio.h

除了BlinkToRadioAppC組件和BlinkToRadioC組件之外,還需要編寫B(tài)linkToRadio.h。在BlinkToRadio.h文件中定義了串口傳送的周期以及要傳送消息的結(jié)構(gòu)體,其具體代碼如描述5.D.3BlinkToRadio.h所示?!久枋?.D.3】BlinkToRadio.h

#ifndef_BLINKTORADIO_H

#define_BLINKTORADIO_H

enum

{

//傳送消息的周期

TIMER_PERIOD_MILLI=2000

};

/*傳送消息的結(jié)構(gòu)體*/

typedefnx_structBlinkToRadioMsg

{

nx_uint16_tnodeid;

nx_uint16_tcounter;

}BlinkToRadioMsg;

#endif

4.?Makefile文件

在Makefile文件中指明任務(wù)的頂層配件,并規(guī)定編譯規(guī)則,其具體代碼如描述5.D.3Makefile所示。

【描述5.D.3】Makefile

COMPONENT=BlinkToRadioAppC

include$(MAKERULES)

5.實(shí)驗(yàn)結(jié)果

將程序編譯下載至兩個(gè)設(shè)備中,設(shè)備的LED1和LED2同時(shí)閃爍,表明數(shù)據(jù)發(fā)送成功;設(shè)備的LED3閃爍表明數(shù)據(jù)接收成功。如果關(guān)閉一臺(tái)設(shè)備,會(huì)發(fā)現(xiàn)另外一臺(tái)設(shè)備的LED3將不閃爍,這是因?yàn)榻邮詹坏綌?shù)據(jù)。在通信過程中,每成功發(fā)送一條數(shù)據(jù),都會(huì)有確認(rèn)幀確認(rèn)發(fā)送成功。使用ZigbeeSniffer捕獲數(shù)據(jù)幀如圖5-8所示。圖5-8捕獲的數(shù)據(jù)幀

5.5ADC信息采集

5.5.1相關(guān)組件及接口

在mytinyos平臺(tái)中,ADC的實(shí)現(xiàn)是通過一些ADC相關(guān)的組件來(lái)實(shí)現(xiàn)的,最主要的有兩個(gè)組件AdcC組件和AdcP組件。

1.?AdcC.nc

Adcc.nc組件位于cygwin\opt\mytinyos\tos\chips\cc2530\adc目錄下,在Adc組件中提供了兩個(gè)接口:AdcControl接口和Read接口。具體代碼如代碼5-17所示?!敬a5-17】AdcC.nc

genericconfigurationAdcC()

{

providesinterfaceAdcControl;

providesinterfaceRead<int16_t>;

}

implementation

{

componentsMainC,AdcP;

MainC.SoftwareInit->AdcP.Init;

enum{ID=unique("UNIQUE_ADC_PORT"),};

AdcControl=AdcP.AdcControl[ID];

Read=AdcP.Read[ID];

}

AdcControl接口:AdcC組件將AdcControl接口的實(shí)現(xiàn)綁定在AdcP組件上,由AdcP組件具體實(shí)現(xiàn)。

Read接口:此接口用于ADC信息的讀取,AdcC組件同樣將此組件綁定到AdcP組件,由AdcP組件具體實(shí)現(xiàn)。

2.?AdcP.nc

AdcP.nc組件位于cygwin\opt\mytinyos\tos\chips\cc2530\adc目錄下,此組件是一個(gè)硬件表示層組件,它的主要功能是實(shí)現(xiàn)了ADC的配置以及ADC采集信息的讀取,其主要代碼如代碼5-18所示。【代碼5-18】

moduleAdcP{

providesinterfaceInit;

providesinterfaceAdcControl[uint8_tid];

providesinterfaceRead<int16_t>[uint8_tid];

}

AdcControl接口有兩個(gè)命令,enable命令和disable命令。

enable命令:ADC相關(guān)的寄存器使能開始采集數(shù)據(jù)。

disable命令:關(guān)閉ADC相關(guān)寄存器,停止采集數(shù)據(jù)。

Read接口用于讀取ADC數(shù)據(jù),當(dāng)讀取完成之后將觸發(fā)ReadDone命令。5.5.2光敏信息采集

以下內(nèi)容將實(shí)現(xiàn)任務(wù)描述5.D.4,通過控制CC2530的ADC進(jìn)行光敏的采集,并通過串口傳輸?shù)絇C機(jī),需要完成以下工作:

首先在mytinyos/apps目錄下新建一個(gè)名為AdSensor的文件夾(參照任務(wù)5.D.1)。

其次在AdSensor文件夾創(chuàng)建頂層配件ADSensorAppC,主組件命名為ADSensorC.nc,并編寫程序。

編寫Makefile文件。

編譯程序,下載至設(shè)備中,連接串口,觀察現(xiàn)象并分析數(shù)據(jù)。

1.?ADSensorAppC.nc

ADSensorAppC.nc為整個(gè)任務(wù)的頂層配件組件,在此組件中實(shí)現(xiàn)了組件之間的綁定關(guān)系。其具體代碼如描述5.D.4ADSensorAppC.nc所示。【描述5.D.4】ADSensorAppC.nc

溫馨提示

  • 1. 本站所有資源如無(wú)特殊說明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請(qǐng)下載最新的WinRAR軟件解壓。
  • 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請(qǐng)聯(lián)系上傳者。文件的所有權(quán)益歸上傳用戶所有。
  • 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁(yè)內(nèi)容里面會(huì)有圖紙預(yù)覽,若沒有圖紙預(yù)覽就沒有圖紙。
  • 4. 未經(jīng)權(quán)益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
  • 5. 人人文庫(kù)網(wǎng)僅提供信息存儲(chǔ)空間,僅對(duì)用戶上傳內(nèi)容的表現(xiàn)方式做保護(hù)處理,對(duì)用戶上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對(duì)任何下載內(nèi)容負(fù)責(zé)。
  • 6. 下載文件中如有侵權(quán)或不適當(dāng)內(nèi)容,請(qǐng)與我們聯(lián)系,我們立即糾正。
  • 7. 本站不保證下載資源的準(zhǔn)確性、安全性和完整性, 同時(shí)也不承擔(dān)用戶因使用這些下載資源對(duì)自己和他人造成任何形式的傷害或損失。

評(píng)論

0/150

提交評(píng)論