zigbee学习心得——实例分析(温湿度采集及控制).docx_第1页
zigbee学习心得——实例分析(温湿度采集及控制).docx_第2页
zigbee学习心得——实例分析(温湿度采集及控制).docx_第3页
zigbee学习心得——实例分析(温湿度采集及控制).docx_第4页
zigbee学习心得——实例分析(温湿度采集及控制).docx_第5页
已阅读5页,还剩11页未读 继续免费阅读

下载本文档

版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领

文档简介

网易 新闻 微博 邮箱 相册 阅读 有道 摄影 爱拍 优惠券 云笔记 闪电邮 手机邮 印像派 网易识字 更多 博客 手机博客 博客搬家 博客VIP服务 LiveWriter写博 word写博 邮件写博 短信写博 群博客 博客油菜地 博客话题 博客热点 博客圈子 找朋友 发现小组风格 网易真人搭配社区iStyle网易真人搭配社区iStyle网易真人搭配社区iStyle玩摄影,玩LOFTER玩胶片,玩LOFTER玩绘画,玩LOFTER创建博客 登录 加关注显示下一条|关闭 温馨提示!由于新浪微博认证机制调整,您的新浪微博帐号绑定已过期,请重新绑定!立即重新绑定新浪微博|关闭 豪醒的博客不只是一个人的旅程导航首页 日志 相册 博友 关于我 日志 zigbee学习心得2协议栈任务 Fork - VFork 一张图说明区别zigbee学习心得实例分析(温湿度采集及控制)2012-08-05 16:58:58|分类: zigbee |标签:cc2430zigbee温湿度cc2430 |字号大中小订阅 就像这样,先添加于温湿度传感器相关的.c和.h文件,还有串口相关的,c和.h也就是写好可以给另外的文件调用的函数了。我这里面只用到了voidwenshi_receive( void );一个函数,然后将函数和其中所用到的两个变量TH,RH,分别代表温度和湿度设为全局变量。先打开SimpleSensor.c这个小工程,用官方程序调试的时候可以看出,也就是不断地发数据到协调器,自然就要找到与发数据相关的函数:那其实发送之前要先与协调器绑定吧,好比打电话也要先拨通电话吧。找到与绑定相关的函数:void zb_BindConfirm( uint16 commandId,uint8 status ) if( ( status = ZB_SUCCESS ) & ( myAppState = APP_START ) ) myAppState = APP_BOUND;/Start reporting sensor valuesmyApp_StartReporting(); else / Continue to discover a collectorosal_start_timerEx( sapi_TaskID, MY_FIND_COLLECTOR_EVT, myBindRetryDelay); 直接点,若绑定成功,就会返回一个ZB_SUCCESS的状态,此时方会调用myApp_StartReporting();函数,否则就继续搜索节点。对于myApp_StartReporting();:void myApp_StartReporting( void )osal_start_timerEx( sapi_TaskID, MY_REPORT_TEMP_EVT, myTempReportPeriod);osal_start_timerEx( sapi_TaskID, MY_REPORT_BATT_EVT,myBatteryCheckPeriod );HalLedSet( HAL_LED_1, HAL_LED_MODE_ON );直观地从函数看上去也就相当于添加一个周期性的任务;从上一篇文章讲过这个TaskID的问题,也就添加一个任务嘛,回到整个工程的主函数,看看怎么回事,这里面就不详细地列出来了,有需要的读者可以一探究竟。过程是这样的:主函数:ZSEG intmain( void ) /*系统初始化*/osal_init_system();osalInitTasks(); /*任务初始化*/ SAPI_Init( taskID ); /*用户自定义任务函数,他的任务ID为taskID*/ ?/*其中的一个等式*/s api_TaskID = task_id;也就是说可以通过osal_start_timerEx添加一个周期性的任务,其周期为XXXPeriod,比如片内温度采集:myTempReportPeriod,电压测量myBatteryCheckPeriod,那XXXEVT,也就相当于一个任务Task里面一个独立的事件Event了。那么我们也可以这么添加自己的事件:再看看XXXEVT 和 XXXPeriod 的定义:/ Application osal event identifiers/ Bit mask of events ( from 0x0000 to0x00FF )#define MY_START_EVT 0x0001#define MY_REPORT_TEMP_EVT 0x0002#define MY_REPORT_BATT_EVT 0x0004#define MY_FIND_COLLECTOR_EVT 0x0008自己跟着做:#define MY_REPORT_WENDU_EVT 0x0010#define MY_REPORT_SHIDU_EVT 0x0020这里说一下为什么要这么做因为等下调用任务处理函数zb_HandleOsalEvent();的时候判断语句是这种形式的: if( event & MY_REPORT_TEMP_EVT )按位与,所以.顺便说一下,我最初做这个东西看漏了这条语句,传输过程会突然断开连接,这个bug搞了我十多天。周期时间:(对照范例)static uint16 myStartRetryDelay =10000; / millisecondsstatic uint16 myTempReportPeriod = 5000; / milliseconds添加:static uint16 myWENDUReportPeriod =6000; / millisecondsstatic uint16 mySHIDUReportPeriod =7000; / milliseconds这样子(这里的周期是毫秒级的,比如5000代表的就是5秒传一次MCU的温度)再回到刚才的myApp_StartReporting(void )添加:osal_start_timerEx( sapi_TaskID, MY_WENDU_BATT_EVT, myWENDUReportPeriod);osal_start_timerEx( sapi_TaskID, MY_SHIDU_BATT_EVT, mySHIDUReportPeriod);这样就添加好了自己读取温湿度信息的任务了,然后具体怎么实现这两个任务:接下来:而Sensor.c里面有一个Handle函数用于处理时间的:见介绍和实体:/*fn zb_HandleOsalEvent*brief The zb_HandleOsalEventfunction is called by the operating*system when a task event is set*param event - Bitmask containingthe events that have been set*return none*/void zb_HandleOsalEvent( uint16 event )uint8 pData2;/用于存放数据和分类信息的 if( event & MY_START_EVT ) zb_StartRequest(); if( event & MY_REPORT_TEMP_EVT )/这不就是从上面介绍的osal_start_timerEx();函数set的事件么?! / Read and report temperature valuepData0 =TEMP_REPORT;/类型存放在pData0里面pData1 = myApp_ReadTemperature();/读出来的温度值存到pData1,myApp_ReadTemperature();是读取温度值的函数zb_SendDataRequest(0xFFFE, SENSOR_REPORT_CMD_ID, 2, pData, 0, AF_ACK_REQUEST, 0 );/发送出去osal_start_timerEx(sapi_TaskID, MY_REPORT_TEMP_EVT, myTempReportPeriod );/再设这样一个时间,无限循环 -这里再说一下发送的过程,首先从刚才osal_start_timerEx();设一个发送温度值的系统事件,在一个myTempReportPeriod的周期之后,通过zb_HandleOsalEvent的调用,再通过if ( event & MY_REPORT_TEMP_EVT )的条件判断执行温度值发送的事件pData0用于告诉协调器是温度报告,pData1用于告诉协调器节点报告出来的温度值是多少,再通过zb_SendDataRequest函数发送出去,而发送的形式是通过0xFFFE,绑定的形式发送(这个下面有讲)字长为2个unsigned char类型,发送完毕后再继续调用osal_start_timerEx添加一个相同的温度采集系统事件,不断地重复这个过程。- if( event & MY_REPORT_BATT_EVT ) /道理和上面一样 / Read battery value/ If battery level low, report battery valuepData0 = BATTERY_REPORT;pData1 = myApp_ReadBattery();zb_SendDataRequest( 0xFFFE, SENSOR_REPORT_CMD_ID, 2, pData, 0,AF_ACK_REQUEST, 0 );osal_start_timerEx( sapi_TaskID, MY_REPORT_BATT_EVT,myBatteryCheckPeriod ); if( event & MY_FIND_COLLECTOR_EVT ) / Find and bind to a collector devicezb_BindDevice( TRUE, SENSOR_REPORT_CMD_ID, (uint8 *)NULL ); 先添加自己刚设的事件:if ( event & MY_REPORT_WENDU_EVT ) / Read and report temperature valuepData0 =WENDU_REPORT;/相当于添加一个可以让协调器识别你发过去的是什么的标签 receive();/调用wenshi.c里面的全局函数receive(); wenshi.c是我自己写的一个C pData1 = TH; /代表温度 zb_SendDataRequest( 0xFFFE, SENSOR_REPORT_CMD_ID, 2, pData, 0,AF_ACK_REQUEST, 0 );osal_start_timerEx(sapi_TaskID, MY_REPORT_WENDU_EVT, myWENDUReportPeriod );/回调 这样子额,pData0 = WENDU_REPORT;,既然说这个是要让协调器识别的,那么协调器(SimpleCollectorEB.c)里面也要有相同的参数。#define TEMP_REPORT 0x01#define BATTERY_REPORT 0x02#define WENDU_REPORT 0x04#define SHIDU_REPORT 0x08再分析回原来的事件处理部分:都有调用zb_SendDataRequest();函数zb_SendDataRequest ( uint16 destination,uint16 commandId, uint8 len,uint8 *pData, uint8 handle, uint8 txOptions, uint8radius )其中status = AF_DataRequest(&dstAddr,&sapi_epDesc, commandId, len, pData, &handle, txOptions, radius);最终调用AF_DataRequest函数;afStatus_t AF_DataRequest( afAddrType_t*dstAddr, endPointDesc_t *srcEP, uint16 cID, uint16 len, uint8 *buf, uint8*transID, uint8 options, uint8 radius )/*fn AF_DataRequest*brief Common functionality forinvoking APSDE_DataReq() for both*SendMulti and MSG-Send.*input parameters*param *dstAddr - Full ZB destinationaddress: Nwk Addr + End Point./0xFFFF -这个一个对全网络中设备进行广播的广播地址/0xFFFD -如果在命令中将目标地址设为这个地址的话那么只对打开了接收的设备进行广播/0xFFFC -广播到协调器和路由器/0xFFFE -如果目的地址为这个地址的话,那么应用层将不指定目标设备,而是通过协议栈读取绑定表来获得相应目标设备的短地址-我们这里协调器发送用的是0xFFFF,而节点发送用的是0xFFFE,这是因为我做的这个项目是多对一的网络结构,因此作为协调器的角色是通过广播式发送的;而用0xFFFE,看上面介绍是:(应用层将不指定目标设备,而是通过协议栈读取绑定表来获得相应目标设备的短地址)也就是,如果协调器之前已经跟节点绑定了,也就可以很顺利地直接发送,也就是这个意思,当然,你也可以用广播式发送,但你要处理好节点与协调器对广播信息的处理问题-*param *srcEP - Origination (i.e.respond to or ack to) End Point Descr./端点描述符指针,就好像你发短信,但别人手机不知道你发的东西是短信还是打电话,因此需要用这类型的信息用以区分*param cID - A valid cluster ID asspecified by the Profile.*param len - Number of bytes of datapointed to by next param./长度*param *buf - A pointer to the databytes to send./要发的数据*param *transID - A pointer to a bytewhich can be modified and which will* be used as the transactionsequence number of the msg.*param options - Valid bit mask of Txoptions.*param radius - Normally set toAF_DEFAULT_RADIUS.*output parameters*param *transID - Incremented by one ifthe return value is success.*return afStatus_t - See previousdefinition of afStatus_. types.就这么个道理,就这么发送数据的了。-这里说一下cID的概念,cID - A valid cluster ID asspecified by the Profile.,网上的人叫“簇”,看上去好像就是一捆东西,有一种物以类聚的意思,上面分析可知发送数据函数zb_SendDataRequest ();最近调用AF_DataRequest(),在AF_DataRequest(),簇cID被命名为commandId,被定义为命令ID,顾名思义,也就是一类命令的集合。将不同命令分入不同的cID中,这显得zigbee协议栈的控制的高效,又保证了数据的安全性和通信可靠性。举个例子,如果你用zigbee一方面要收集温湿度信息,一方面要控制灯光、电扇,还有控制温湿度信息的时间间隔之类,这样子你就需要将这些任务分类,这就是cID的意义-然后再看接收数据。Workspace那里打开SimpleCollector,可以找到介绍函数的原型:(底层不分析了,直接看应用层了)void zb_ReceiveDataIndication( uint16source, uint16 command, uint16 len, uint8 *pData )uint8 buf32;/用于存放串口发送数据uint8 *pBuf;/指向buf 的uint8 tmpLen;/长度uint8 sensorReading;/传感器读到的东西,也就是从节点传回来的东西 if(command = SENSOR_REPORT_CMD_ID) / Received report from a sensorsensorReading = pData1;/ If tool available, write to serial porttmpLen =(uint8)osal_strlen( (char*)strDevice );/CONST uint8strDevice = Device:0x;pBuf =osal_memcpy( buf, strDevice, tmpLen );/将strDevice的内容复制到buf里面,返回指向buf的指针赋给pBuf_ltoa( source,pBuf, 16 );/这个函数用于将long型转化为asii码,source记录的是节点的段地址,long型pBuf += 4;/long型4个字节*pBuf+ = ;if ( pData0 = BATTERY_REPORT ) tmpLen = (uint8)osal_strlen( (char*)strBattery );pBuf = osal_memcpy( pBuf, strBattery, tmpLen );/pBuf指向复制了strBattery内容的pBuf指针,也就相当于复制内容到pBuf指针指向的内存空间*pBuf+ = (sensorReading / 10 ) + 0;/ convent msb to ascii*pBuf+ = .;/ decimal point ( battery reading is in units of 0.1 V*pBuf+ = (sensorReading % 10 ) + 0;/ convert lsb to ascii*pBuf+ = ;*pBuf+ = V;那按照协议栈写的添加: else if( pData0 = WENDU_REPORT ) tmpLen = (uint8)osal_strlen(char*)strWENDU ); pBuf = osal_memcpy( pBuf, strWENDU,tmpLen ); *pBuf+ = sensorReading/10+0x30; *pBuf+ = sensorReading%10+0x30;/转askii码 *pBuf+ = ; *pBuf+ = C; 最后官方协议栈是通过调用#if defined(MT_TASK ) debug_str( (uint8 *)buf );#endif也就是debug_str();函数发送到串口的,测试过发现有乱码,然后我有一篇文章是将乱码的原因和如何解决这种乱码现象的,大家可以留意一下。做完了这一part以后我们来试试做控制部分的。要知道只能看不能操作是很无聊的!呵呵首先控制部分都是与串口挂钩的了。串口怎么写额这个得看回我写的第一篇文章里面有介绍的一些小实验,其中就是涉及到串口部分的,现在想来是非常有用的。/Uart0 初始化voidUart0Init(uint8 StopBits,uint8 Parity) PERCFG &= 0x01; /选择UART0可选位置1,TXD-P0_3 RXD-P0_2 P0SEL |= 0X0C; /设置02 03为外设IO U0CSR = 0XC0; / 1100 0000 UART模式(异步)能接收使能 U0GCR = 11; U0BAUD = 216; / 波特率为115200bps U0UCR |= StopBits|Parity;/Uart0 接收数据unsigned charUart0Receive(void) unsigned char data; uint8 status; if(URX0IF = TRUE) data = U0DBUF; URX0IF = FALSE; / Restoring old state U0CSR = status; /提取接收到的数据 return data; 就这么了。先理清一下思路吧!PC协调器处理任务那么协调器怎么接受来之PC的信息呢,什么时候接收呢,这个其实跟sensor路由器一样道理,从绑定开始调用接受字符函数Uart0Receive();,但是我们不能直接拿那个函数吖,这只是一个最直接的函数,我们还需要一个函数去分析PC发过来的是什么吧。voidmy_Uart(void) uint8 c=0; c = Uart0Receive();好,先就这么写着。C for control.找到void zb_HandleOsalEvent( uint16 event )添加: if ( event & MY_UART_EVT ) my_Uart(); osal_start_timerEx( sapi_TaskID,MY_UART_EVT, myUartPeriod ); 跟路由器一个道理,添加系统时间,不断地执行读取串口数据的命令,记得帮MY_UART_EVT define一个16进制的代码。然后写处理命令了:voidmy_Uart(void) uint8 c=0; uint8 pData1; c = Uart0Receive(); asm(NOP); switch(c) case A:/开始采集 HalLedSet( HAL_LED_1, HAL_LED_MODE_ON ); pData0 = Collect_start; zb_SendDataRequest( 0xFFFF,SENSOR_CONTROL_CMD_ID, 1, pData, 0, 0, 0 ); break; case B:/停止采集 HalLedSet( HAL_LED_1, HAL_LED_MODE_OFF ); pData0 = Collect_stop; zb_SendDataRequest( 0xFFFF, SENSOR_CONTROL_CMD_ID,1, pData, 0, 0, 0 ); break; case C: /开始MCU片内温度采集 HalLedSet( HAL_LED_1, HAL_LED_MODE_ON ); pData0 = MCUTemp_start; zb_SendDataRequest( 0xFFFF,SENSOR_CONTROL_CMD_ID, 1, pData, 0, 0, 0 ); break; case D:/停止MCU片内温度采集 HalLedSet( HAL_LED_1, HAL_LED_MODE_OFF ); pData0 = MCUTemp_stop; zb_SendDataRequest( 0xFFFF,SENSOR_CONTROL_CMD_ID, 1, pData, 0, 0, 0 ); break; case E:/开始MCU 电压采集 HalLedSet( HAL_LED_1, HAL_LED_MODE_ON ); pData0 = MCUBat_start; zb_SendDataRequest( 0xFFFF,SENSOR_CONTROL_CMD_ID, 1, pData, 0, 0, 0 ); break; case F:/停止MCU 电压采集 HalLedSet( HAL_LED_1, HAL_LED_MODE_OFF ); pData0 = MCUBat_stop; zb_SendDataRequest( 0xFFFF,SENSOR_CONTROL_CMD_ID, 1, pData, 0, 0, 0 ); break;.就想这么写,代码长不一一列出来这里面发送和sensor发送温湿度信息时一样的。HalLedSet(HAL_LED_1, HAL_LED_MODE_OFF );这是一个成功的标志,如果关闭什么成功了后,比如用户想关掉MCU 的温度采集,通过LED1灯灭的情况反馈给用户。pData0 =Collect_stop; zb_SendDataRequest( 0xFFFF, SENSOR_CONTROL_CMD_ID,1, pData, 0, 0, 0 );当然,这里面的命令只有一个unsigned char的长度,命令形式是广播式的然后Collect_stop这样子的命令必须编码,而且协调器跟节点应保持一致。如#defineCollect_start 0x40#define Collect_stop 0x80#defineMCUTemp_stop 0x30#defineMCUTemp_start 0xD0#defineMCUBat_stop 0x50#defineMCUBat_start 0x60#defineTemp_stop 0x70#defineTemp_start 0xE0#defineHUM_start 0x90#defineHUM_stop 0xA0我乱写的,就好像这样子。那么sensor那边负责接收的函数:void zb_ReceiveDataIndication(uint16 source, uint16 command, uint16 len, uint8 *pData ) if ( command = SENSOR_CONTROL_CMD_ID ) if ( pData0 = Collect_start ) /开始采集温度和电池电压 myApp_StartReporting(); if ( LED1_SBIT = LED1_POLARITY (1) /LED1 是标志,成功后反馈到协调器 pData0 = Collect_start; zb_SendDataRequest( 0xFFFE,SENSOR_REPORT_CMD_ID, 1, pData, 0,AF_ACK_REQUEST, 0 ); if ( pData0 = Collect_stop ) /停止采集温度和电池电压 myApp_StopReporting(); if ( LED1_SBIT = LED1_POLARITY (0) ) pData0 = Collect_stop; zb_SendDataRequest( 0xFFFE,SENSOR_REPORT_CMD_ID, 1, pData, 0,AF_ACK_REQUEST, 0 ); if ( pData0 = MCUTemp_stop ) /停止采集片内温度 myApp_StopMCUTempReporting(); pData0 = MCUTemp_stop; zb_SendDataRequest( 0xFFFE,SENSOR_REPORT_CMD_ID, 1, pData, 0, AF_ACK_REQUEST, 0 ); if ( pData0 = MCUTemp_start ) /开始采集片内温度 myApp_StopMCUTempReporting(); myApp_StartMCUTempReporting(); zb_SendDataRequest( 0xFFFE,SENSOR_REPORT_CMD_ID, 1, pData, 0,AF_ACK_REQUEST, 0 ); 就像这样从if ( command = SENSOR_CONTROL_CMD_ID )这个判断语句读者应该能理解cID的用意吧这里面没什么好说的,不过要看看处理函数voidmyApp_StartReporting( void ) unsigned char a,b,c,d; a = osal_start_timerEx( sapi_TaskID,MY_REPORT_TEMP_EVT, myTempReportPeriod ); b = osal_start_timerEx( sapi_TaskID,MY_REPORT_BATT_EVT, myBatteryCheckPeriod ); c = osal_start_timerEx( sapi_TaskID,MY_REPORT_WENDU_EVT, myWENDUReportPeriod ); d = osal_start_timerEx( sapi_TaskID,MY_REPORT_SHIDU_EVT, mySHIDUReportPeriod ); HalLedSet( HAL_LED_1, HAL_LED_MODE_ON ); /Uart0SendString(Start ssecess!); /Uart0Send( a );Uart0Send( b );Uart0Send( c);Uart0Send( a ); /测试用上面的一些赋值可以忽略,这是我用于测试的。道理也很简单,再看看停止的:voidmyApp_StopReporting( void ) /unsigned char i,j,k,z; osal_stop_timerEx( sapi_TaskID, MY_REPORT_TEMP_EVT); osal_stop_timerEx( sapi_TaskID,MY_REPORT_BATT_EVT ); osal_stop_timerEx( sapi_TaskID,MY_REPORT_WENDU_EVT ); osal_stop_timerEx( sapi_TaskID,MY_REPORT_SHIDU_EVT ); HalLedSet( HAL_LED_1, HAL_LED_MODE_OFF ); /Uart0SendString(CStop s sucess!);/Uart0Send(i);Uart0Send(j);Uart0Send(k);Uart0Send(z);道理也很简单,直接调用就OK,意思是将自己想要停止的时间从系统timer中删除掉。删除单个道理一样:voidmyApp_StopMCUTempReporting( void ) osal_stop_timerEx( sapi_TaskID,MY_REPORT_TEMP_EVT ); HalLedSet( HAL_LED_1, HAL_LED_MODE_OFF );voidmyApp_StopMCUBatReporting( void ) osal_stop_timerEx( sapi_TaskID,MY_REPORT_BATT_EVT ); HalLedSet( HAL_LED_1, HAL_LED_MODE_OFF ); .最后是反馈信息,因为命令是从协调器发出去的,因此协调器必须受到反馈信息才好确认是否准确操作了该条命令。 if ( LED1_SBIT = LED1_POLARITY (1) /LED1 是标志,成功后反馈到协调器 pData0 = Collect_start; zb_SendDataRequest( 0xFFFE,SENSOR_REPORT_CMD_ID, 1, pData, 0,AF_ACK_REQUEST, 0 ); LED1灯亮了之后,代表成功开启,然后发送pData0 =Collect_start;的信息到节点,这就是为什么协调器和节点要保持发送接收命令信息(如Collect_start = 0x40 )一致的原因。这里面提一下LED1_POLARITY (1)这个函数它最终的原型是一个#define ACTIVE_LOW !也就是非,应该就是为了符合个人操作习惯而设的。再看看协调器怎么处理这些反馈回来的信息 if ( pData0 = Collect_start ) zb_AllowBind( 0xFF ); HalLedSet( HAL_LED_1, HAL_LED_MODE_ON ); tmpLen = (uint8)osal_strlen(char*)strCollect ); pBuf = osal_memcpy( buf, strCollect,tmpLen ); if ( pData0 = Collect_stop ) zb_AllowBind( 0x00 ); HalLedSet( HAL_LED_1, HAL_LED_MODE_OFF ); tmpLen = (uint8)osal_strlen(char*)strCollect2 ); pBuf = osal_memcpy( buf, strCollect2,tmpLen ); if ( pData0 = MCUTemp_start ) tmpLen = (uint8)osal_strlen(char*)strMCUTEMP ); pBuf = osal_memcpy( buf, strMCUTEMP,tmpLen ); if ( pData0 = MCUTemp_stop ) tmpLen = (uint8)osal_strlen(char*)strMCUTEMP2 ); pBu

温馨提示

  • 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
  • 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
  • 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
  • 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
  • 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
  • 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
  • 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。

评论

0/150

提交评论