透传的基本概念: 透传就是透明传输的简称。那么什么是透明传输呢?顾名思义,透明传输就是指在传输过程中,对外界完全透明,不需要关系传输过程以及传输协议,终目的是要把传输的内容原封不动的传递给被接收端,发送和接收的内容完全一致。这就相当于把信息直接扔给你想要传输的人,只需要扔(也就是传输)这一个步骤,不需要其他的内容安排。 串口无线透传编程流程: 程序需要实现的功能: 1、 ZigBee 模块接收到从 PC 机发来的消息,然后无线发送出去 2、 ZigBee 模块接收到其他 ZigBee 模块发来的消息,然后发送给 PC 机 发送和接收数据的流程: 发送数据: 填充并注册端点描述符 配置发送模式及目的地址AF_DataRe quest()发送数据 接收数据: 填充并注册端点描述符处理系统事件 SYS_EVENT_MSG 中的AF_INCOMING _MSG_CMD 消息获得消息包中的无线数据 相关的API函数或结构体的介绍: 串口无线透传我们需要掌握以下重点: 端点描述符 简单描述符 如何发送数据 如何接收数据 我们重点分析四个函数: 任务的初始化函数 任务的事件处理函数 无线消息接收回调函数 无线消息发送函数 端口描述符的定义: 端点(Endpoint)是协议栈应用层入口,它通常为节点的一个通信部件或设备(如各种类型的传感器、开关、 LED 灯等)也是用户定义的应用对象驻留的地方。端点类似于在计算机 TCP/IP 网络通信中,为方便计算机中不同的进程进行通信,在传输层设置的端口(Port)概念。端点和 IEEE64 位扩展地址、16 位网络短地址一样,是 ZigBee 无线通信的一个重要地址参数,能够为多个应用对象提供逻辑子通道以进行通信。每个 ZigBee 设备支持多达 240 个端点,也就是说,每个设备多可以定义 240 个应用对象。端点 0 必须在ZigBee 设备中具有,它分配给 ZigBee 设备对象(ZD0)使用,端点 255 是端点广播地址,端点 241~254 保留,为以后扩展使用。端点描述符用来描述一个端点,Z-Stack 中的 AF.h 中有关于端点描述符的定义如下: typedef struct { uint8 endPoint; //端口号 uint8 *task_id; // 指向任务ID号 Pointer to location of the Application task ID. // 简单设备描述符 可以通过go to…的方式查看结构体变量的类型 SimpleDescriptionFormat_t *simpleDesc; afNetworkLatencyReq_t latencyReq; // 延时,采用默认值初始化即可 } endPointDesc_t; 端点描述符的初始化: 端点描述符需要在应用层 SampleApp.c 文件中的 SampleApp_Init()函数中进行端点填充,并向 AF 层注册端点描述符。第一次对话实验中填充端点描述符的过程如下,该部分代码比较固定。 void SampleApp_Init( uint8 task_id ) { // Fill out the endpoint description. // 以下四行是对节点描述符进行初始化 // 我们需要手动指定端口号,程序中 SAMPLEAPP_ENDPOINT 的宏值为20, // 可以使用的端口号范围:1~240,用户可根据需要进行修改。 SampleApp_epDesc.endPoint = SAMPLEAPP_ENDPOINT; //指定任务 ID,这里我们指向的是当前任务的 ID。 SampleApp_epDesc.task_id = &SampleApp_TaskID; // 指向简单描述符。我们下边会分析简单描述符的定义。 SampleApp_epDesc.simpleDesc = (SimpleDescriptionFormat_t *)&SampleApp_SimpleDesc; // 采用默认值 noLatencyReqs 即可 SampleApp_epDesc.latencyReq = noLatencyReqs; // Register the endpoint description with the AF // 用 afRegister()函数向 AF 层注册端点描述符。 afRegister( &SampleApp_epDesc ); } 简单设备描述符的定义: typedef struct { uint8 EndPoint; // 端口号 uint16 AppProfId; // 应用规范ID uint16 AppDeviceId; // 应用设备ID uint8 AppDevVer:4; // 应用版本设备号 uint8 Reserved:4; // 保留 AF_V1_SUPPORT uses for AppFlags:4. uint8 AppNumInClusters; // 输入簇的个数 cId_t *pAppInClusterList; // 输入簇的列表 uint8 AppNumOutClusters; // 输出簇的个数 cId_t *pAppOutClusterList; // 输出簇的列表 } SimpleDescriptionFormat_t; 简单设备描述符的初始化: 宏定义在SampleApp.h文件中 #define SAMPLEAPP_ENDPOINT 20 // 端口号20 #define SAMPLEAPP_PROFID 0x0F08 #define SAMPLEAPP_DEVICEID 0x0001 #define SAMPLEAPP_DEVICE_VERSION 0 #define SAMPLEAPP_FLAGS 0 #define SAMPLEAPP_MAX_CLUSTERS 2 #define SAMPLEAPP_PERIODIC_CLUSTERID 1 #define SAMPLEAPP_FLASH_CLUSTERID 2 初始化在SampleApp.c文件中 const cId_t SampleApp_ClusterList[SAMPLEAPP_MAX_CLUSTERS] = { SAMPLEAPP_PERIODIC_CLUSTERID, SAMPLEAPP_FLASH_CLUSTERID }; const SimpleDescriptionFormat_t SampleApp_SimpleDesc = { SAMPLEAPP_ENDPOINT, // int Endpoint; 端口号 SAMPLEAPP_PROFID, // uint16 AppProfId[2]; 应用规范ID SAMPLEAPP_DEVICEID, // uint16 AppDeviceId[2]; 应用设备ID SAMPLEAPP_DEVICE_VERSION, // int AppDevVer:4; 应用设备版本号 SAMPLEAPP_FLAGS, // int AppFlags:4; 保留 SAMPLEAPP_MAX_CLUSTERS, // uint8 AppNumInClusters; 输入簇命令个数 (cId_t *)SampleApp_ClusterList, // uint8 *pAppInClusterList; 输入簇列表 SAMPLEAPP_MAX_CLUSTERS, // uint8 AppNumInClusters; 输出簇命令个数 (cId_t *)SampleApp_ClusterList // uint8 *pAppOutClusterList;输出簇列表 }; 发送数据函数详解: 【1】 afStatus_t AF_DataRequest( afAddrType_t *dstAddr, //包含目的节点的网络地址以及发送数据的格式,如广播、组播或单播。 endPointDesc_t *srcEP,//某一个节点上不同的端口 (endpoint) ,我们可以理解为 TCP/IP 中的端口。 uint16cID,//该参数主要是为了区分不同的命令,对应简单描述符中的输出群集 uint16 len,//该参数标识了发送数据的长度。 uint8 *buf,//该参数是指向发送缓冲区的指针。 uint8 *transID,//该参数是指向发送序号的指针。可以用来检测丢包率,由OSAL维护。 uint8 options,//取默认值 AF_DISCV_ROUTE 即可。 uint8 radius//取默认值 AF_DEFAULT_RADIUS 即可。 ) 【2】对于发送数据函数AF_DataRequest函数的具体实现, 只需要理解zigbee协议栈是通过发送函数实现广播、组播、单播的即可。 【3】这里重点关注AF_DataRequest函数的第一个参数,可以通过go to……的方式跳转到第一个参数的变量类型: 第一个参数是一个结构体:如下 typedef struct { union { uint16 shortAddr; //代表节点的网络地址 ZLongAddr_t extAddr; } addr; afAddrMode_t addrMode; //重点关注这个变量,他代表我的发送形式 uint8 endPoint; uint16 panId; // used for the INTER_PAN feature } afAddrType_t; afAddrMode_t变量是一个枚举类型: typedef enum { afAddrNotPresent = AddrNotPresent, afAddr16Bit = Addr16Bit, //代表单播 afAddr64Bit = Addr64Bit, afAddrGroup = AddrGroup, //代表组播 afAddrBroadcast = AddrBroadcast //代表广播 } afAddrMode_t; 上述使用到的Addr16Bit,AddrGroup,,AddrBroadcast是一个常数,在zigbee协议栈中具有定义:如下 enum { AddrNotPresent = 0, AddrGroup = 1, Addr16Bit = 2, Addr64Bit = 3, AddrBroadcast = 15 }; 接收数据函数详解: 当设备接收到无线数据后,操作系统会将该数据封装成一个消息然后放入消息队列中,同时设置系统事件SYS_EVENT_MSG ,应用层的事件处理函数 SampleApp_ProcessEvent 会处理这个事件,他首先会将消息从消息队列中取出,根据消息的 ID 判断该消息是否就是接收到的数据,标识接收到新数据的消息 ID 是 AF_INCOMING_MSG_CMD,其中 AF_ INCOMING_MSG_CMD 的值是 0x1a,这是在 ZigBee 协议栈中定义好的,用户不可更改。 具体的事件处理函数代码如下所示,这部分代码比较固定,我们只需要熟悉这种事件处理结构即可。 // 事件处理函数 uint16 SampleApp_ProcessEvent( uint8 task_id, uint16 events ) { afIncomingMSGPacket_t *MSGpkt; (void)task_id; // Intentionally unreferenced parameter if ( events & SYS_EVENT_MSG ) { // 获取消息 MSGpkt = (afIncomingMSGPacket_t *)osal_msg_receive( SampleApp_TaskID ); while ( MSGpkt ) { switch ( MSGpkt->hdr.event ) { // Received when a messages is received (OTA) for this endpoint case AF_INCOMING_MSG_CMD://接收数据事件,调用函数AF_DataRequest()接收数据 SampleApp_MessageMSGCB( MSGpkt );//调用回调函数对收到的数据进行处理 break; default: break; } // Release the memory 事件处理完了,释放消息占用的内存 osal_msg_deallocate( (uint8 *)MSGpkt ); // Next - if one is available 指针指向下一个放在缓冲区的待处理的事件, //返回while ( MSGpkt )重新处理事件,直到缓冲区没有等待处理事件为止 MSGpkt = (afIncomingMSGPacket_t *)osal_msg_receive( SampleApp_TaskID ); } // return unprocessed events 返回未处理的事件 return (events ^ SYS_EVENT_MSG); } // Discard unknown events return 0; } SampleApp_MessageMSGCB( MSGpkt );函数使用说明: // 接收到消息,消息处理回调函数 void SampleApp_MessageMSGCB( afIncomingMSGPacket_t *pkt ) { uint16 flashTime; switch ( pkt->clusterId ) { case SAMPLEAPP_PERIODIC_CLUSTERID: HalUARTWrite (0, (pkt->cmd).Data, ((pkt->cmd).DataLength)); break; case SAMPLEAPP_FLASH_CLUSTERID: flashTime = BUILD_UINT16(pkt->cmd.Data[1], pkt->cmd.Data[2] ); HalLedBlink( HAL_LED_4, 4, 50, (flashTime / 4) ); break; } } 思考两个问题: 为什么要根据SAMPLEAPP_ PERIODIC_CLUSTERID 才能得到正确的数据呢? 在 ZigBee 网络中进行通信时需要注意的,两者如果想进行通信,需要具有相同的 Cluster ID,而且一个选择“输入” ,另一个选择“输出”(在简单描述符中填充) 。 收到的数据在哪里? 在 pkt 指向的那个结构体里,我们去看下 afIncomingMSGPacket_t 的真面目了。 接收数据的存放位置: typedef struct { osal_event_hdr_t hdr; /* OSAL Message header */ uint16 groupId; /* Message's group ID - 0 if not set */ uint16 clusterId; /* Message's cluster ID */ afAddrType_t srcAddr; /* Source Address, if endpoint is STUBAPS_INTER_PAN_EP, it's an InterPAN message */ uint16 macDestAddr; /* MAC header destination short address */ uint8 endPoint; /* destination endpoint */ uint8 wasBroadcast; /* TRUE if network destination was a broadcast address */ uint8 LinkQuality; /* The link quality of the received data frame */ uint8 correlation; /* The raw correlation value of the received data frame */ int8 rssi; /* The received RF power in units dBm */ uint8 SecurityUse; /* deprecated */ uint32 timestamp; /* receipt timestamp from MAC */ uint8 nwkSeqNum; /* network header frame sequence number */ afMSGCommandFormat_t cmd; /* Application Data */ } afIncomingMSGPacket_t; afMSGCommandFormat_t结构体的声明: typedef struct { uint8 TransSeqNumber; //用于存储发送序列号; uint16 DataLength; //用于存储接收到的数据长度; uint8 *Data; //数据接收后放在一个缓冲区,该参数就是指向缓冲区的指针; } afMSGCommandFormat_t; |
热点新闻
讲师博文
透传的基本概念: 透传就是透明传输的简称。那么什么是透明传输呢?顾名思义,透明传输就是指在传输过程中,对外界完全透明,不需要关系传输过程以及传输协议,终目的是要把传输的内容原封不动的传递给被接收端,...
透传的基本概念: 透传就是透明传输的简称。那么什么是透明传输呢?顾名思义,透明传输就是指在传输过程中,对外界完全透明,不需要关系传输过程以及传输协议,终目的是要把传输的内容原封不动的传递给被接收端,发送和接收的内容完全一致。这就相当于把信息直接扔给你想要传输的人,只需要扔(也就是传输)这一个步骤,不需要其他的内容安排。 串口无线透传编程流程: 程序需要实现的功能: 1、 ZigBee 模块接收到从 PC 机发来的消息,然后无线发送出去 2、 ZigBee 模块接收到其他 ZigBee 模块发来的消息,然后发送给 PC 机 发送和接收数据的流程: 发送数据: 填充并注册端点描述符 配置发送模式及目的地址AF_DataRe quest()发送数据 接收数据: 填充并注册端点描述符处理系统事件 SYS_EVENT_MSG 中的AF_INCOMING _MSG_CMD 消息获得消息包中的无线数据 相关的API函数或结构体的介绍: 串口无线透传我们需要掌握以下重点: 端点描述符 简单描述符 如何发送数据 如何接收数据 我们重点分析四个函数: 任务的初始化函数 任务的事件处理函数 无线消息接收回调函数 无线消息发送函数 端口描述符的定义: 端点(Endpoint)是协议栈应用层入口,它通常为节点的一个通信部件或设备(如各种类型的传感器、开关、 LED 灯等)也是用户定义的应用对象驻留的地方。端点类似于在计算机 TCP/IP 网络通信中,为方便计算机中不同的进程进行通信,在传输层设置的端口(Port)概念。端点和 IEEE64 位扩展地址、16 位网络短地址一样,是 ZigBee 无线通信的一个重要地址参数,能够为多个应用对象提供逻辑子通道以进行通信。每个 ZigBee 设备支持多达 240 个端点,也就是说,每个设备多可以定义 240 个应用对象。端点 0 必须在ZigBee 设备中具有,它分配给 ZigBee 设备对象(ZD0)使用,端点 255 是端点广播地址,端点 241~254 保留,为以后扩展使用。端点描述符用来描述一个端点,Z-Stack 中的 AF.h 中有关于端点描述符的定义如下: typedef struct { uint8 endPoint; //端口号 uint8 *task_id; // 指向任务ID号 Pointer to location of the Application task ID. // 简单设备描述符 可以通过go to…的方式查看结构体变量的类型 SimpleDescriptionFormat_t *simpleDesc; afNetworkLatencyReq_t latencyReq; // 延时,采用默认值初始化即可 } endPointDesc_t; 端点描述符的初始化: 端点描述符需要在应用层 SampleApp.c 文件中的 SampleApp_Init()函数中进行端点填充,并向 AF 层注册端点描述符。第一次对话实验中填充端点描述符的过程如下,该部分代码比较固定。 void SampleApp_Init( uint8 task_id ) { // Fill out the endpoint description. // 以下四行是对节点描述符进行初始化 // 我们需要手动指定端口号,程序中 SAMPLEAPP_ENDPOINT 的宏值为20, // 可以使用的端口号范围:1~240,用户可根据需要进行修改。 SampleApp_epDesc.endPoint = SAMPLEAPP_ENDPOINT; //指定任务 ID,这里我们指向的是当前任务的 ID。 SampleApp_epDesc.task_id = &SampleApp_TaskID; // 指向简单描述符。我们下边会分析简单描述符的定义。 SampleApp_epDesc.simpleDesc = (SimpleDescriptionFormat_t *)&SampleApp_SimpleDesc; // 采用默认值 noLatencyReqs 即可 SampleApp_epDesc.latencyReq = noLatencyReqs; // Register the endpoint description with the AF // 用 afRegister()函数向 AF 层注册端点描述符。 afRegister( &SampleApp_epDesc ); } 简单设备描述符的定义: typedef struct { uint8 EndPoint; // 端口号 uint16 AppProfId; // 应用规范ID uint16 AppDeviceId; // 应用设备ID uint8 AppDevVer:4; // 应用版本设备号 uint8 Reserved:4; // 保留 AF_V1_SUPPORT uses for AppFlags:4. uint8 AppNumInClusters; // 输入簇的个数 cId_t *pAppInClusterList; // 输入簇的列表 uint8 AppNumOutClusters; // 输出簇的个数 cId_t *pAppOutClusterList; // 输出簇的列表 } SimpleDescriptionFormat_t; 简单设备描述符的初始化: 宏定义在SampleApp.h文件中 #define SAMPLEAPP_ENDPOINT 20 // 端口号20 #define SAMPLEAPP_PROFID 0x0F08 #define SAMPLEAPP_DEVICEID 0x0001 #define SAMPLEAPP_DEVICE_VERSION 0 #define SAMPLEAPP_FLAGS 0 #define SAMPLEAPP_MAX_CLUSTERS 2 #define SAMPLEAPP_PERIODIC_CLUSTERID 1 #define SAMPLEAPP_FLASH_CLUSTERID 2 初始化在SampleApp.c文件中 const cId_t SampleApp_ClusterList[SAMPLEAPP_MAX_CLUSTERS] = { SAMPLEAPP_PERIODIC_CLUSTERID, SAMPLEAPP_FLASH_CLUSTERID }; const SimpleDescriptionFormat_t SampleApp_SimpleDesc = { SAMPLEAPP_ENDPOINT, // int Endpoint; 端口号 SAMPLEAPP_PROFID, // uint16 AppProfId[2]; 应用规范ID SAMPLEAPP_DEVICEID, // uint16 AppDeviceId[2]; 应用设备ID SAMPLEAPP_DEVICE_VERSION, // int AppDevVer:4; 应用设备版本号 SAMPLEAPP_FLAGS, // int AppFlags:4; 保留 SAMPLEAPP_MAX_CLUSTERS, // uint8 AppNumInClusters; 输入簇命令个数 (cId_t *)SampleApp_ClusterList, // uint8 *pAppInClusterList; 输入簇列表 SAMPLEAPP_MAX_CLUSTERS, // uint8 AppNumInClusters; 输出簇命令个数 (cId_t *)SampleApp_ClusterList // uint8 *pAppOutClusterList;输出簇列表 }; 发送数据函数详解: 【1】 afStatus_t AF_DataRequest( afAddrType_t *dstAddr, //包含目的节点的网络地址以及发送数据的格式,如广播、组播或单播。 endPointDesc_t *srcEP,//某一个节点上不同的端口 (endpoint) ,我们可以理解为 TCP/IP 中的端口。 uint16cID,//该参数主要是为了区分不同的命令,对应简单描述符中的输出群集 uint16 len,//该参数标识了发送数据的长度。 uint8 *buf,//该参数是指向发送缓冲区的指针。 uint8 *transID,//该参数是指向发送序号的指针。可以用来检测丢包率,由OSAL维护。 uint8 options,//取默认值 AF_DISCV_ROUTE 即可。 uint8 radius//取默认值 AF_DEFAULT_RADIUS 即可。 ) 【2】对于发送数据函数AF_DataRequest函数的具体实现, 只需要理解zigbee协议栈是通过发送函数实现广播、组播、单播的即可。 【3】这里重点关注AF_DataRequest函数的第一个参数,可以通过go to……的方式跳转到第一个参数的变量类型: 第一个参数是一个结构体:如下 typedef struct { union { uint16 shortAddr; //代表节点的网络地址 ZLongAddr_t extAddr; } addr; afAddrMode_t addrMode; //重点关注这个变量,他代表我的发送形式 uint8 endPoint; uint16 panId; // used for the INTER_PAN feature } afAddrType_t; afAddrMode_t变量是一个枚举类型: typedef enum { afAddrNotPresent = AddrNotPresent, afAddr16Bit = Addr16Bit, //代表单播 afAddr64Bit = Addr64Bit, afAddrGroup = AddrGroup, //代表组播 afAddrBroadcast = AddrBroadcast //代表广播 } afAddrMode_t; 上述使用到的Addr16Bit,AddrGroup,,AddrBroadcast是一个常数,在zigbee协议栈中具有定义:如下 enum { AddrNotPresent = 0, AddrGroup = 1, Addr16Bit = 2, Addr64Bit = 3, AddrBroadcast = 15 }; 接收数据函数详解: 当设备接收到无线数据后,操作系统会将该数据封装成一个消息然后放入消息队列中,同时设置系统事件SYS_EVENT_MSG ,应用层的事件处理函数 SampleApp_ProcessEvent 会处理这个事件,他首先会将消息从消息队列中取出,根据消息的 ID 判断该消息是否就是接收到的数据,标识接收到新数据的消息 ID 是 AF_INCOMING_MSG_CMD,其中 AF_ INCOMING_MSG_CMD 的值是 0x1a,这是在 ZigBee 协议栈中定义好的,用户不可更改。 具体的事件处理函数代码如下所示,这部分代码比较固定,我们只需要熟悉这种事件处理结构即可。 // 事件处理函数 uint16 SampleApp_ProcessEvent( uint8 task_id, uint16 events ) { afIncomingMSGPacket_t *MSGpkt; (void)task_id; // Intentionally unreferenced parameter if ( events & SYS_EVENT_MSG ) { // 获取消息 MSGpkt = (afIncomingMSGPacket_t *)osal_msg_receive( SampleApp_TaskID ); while ( MSGpkt ) { switch ( MSGpkt->hdr.event ) { // Received when a messages is received (OTA) for this endpoint case AF_INCOMING_MSG_CMD://接收数据事件,调用函数AF_DataRequest()接收数据 SampleApp_MessageMSGCB( MSGpkt );//调用回调函数对收到的数据进行处理 break; default: break; } // Release the memory 事件处理完了,释放消息占用的内存 osal_msg_deallocate( (uint8 *)MSGpkt ); // Next - if one is available 指针指向下一个放在缓冲区的待处理的事件, //返回while ( MSGpkt )重新处理事件,直到缓冲区没有等待处理事件为止 MSGpkt = (afIncomingMSGPacket_t *)osal_msg_receive( SampleApp_TaskID ); } // return unprocessed events 返回未处理的事件 return (events ^ SYS_EVENT_MSG); } // Discard unknown events return 0; } SampleApp_MessageMSGCB( MSGpkt );函数使用说明: // 接收到消息,消息处理回调函数 void SampleApp_MessageMSGCB( afIncomingMSGPacket_t *pkt ) { uint16 flashTime; switch ( pkt->clusterId ) { case SAMPLEAPP_PERIODIC_CLUSTERID: HalUARTWrite (0, (pkt->cmd).Data, ((pkt->cmd).DataLength)); break; case SAMPLEAPP_FLASH_CLUSTERID: flashTime = BUILD_UINT16(pkt->cmd.Data[1], pkt->cmd.Data[2] ); HalLedBlink( HAL_LED_4, 4, 50, (flashTime / 4) ); break; } } 思考两个问题: 为什么要根据SAMPLEAPP_ PERIODIC_CLUSTERID 才能得到正确的数据呢? 在 ZigBee 网络中进行通信时需要注意的,两者如果想进行通信,需要具有相同的 Cluster ID,而且一个选择“输入” ,另一个选择“输出”(在简单描述符中填充) 。 收到的数据在哪里? 在 pkt 指向的那个结构体里,我们去看下 afIncomingMSGPacket_t 的真面目了。 接收数据的存放位置: typedef struct { osal_event_hdr_t hdr; /* OSAL Message header */ uint16 groupId; /* Message's group ID - 0 if not set */ uint16 clusterId; /* Message's cluster ID */ afAddrType_t srcAddr; /* Source Address, if endpoint is STUBAPS_INTER_PAN_EP, it's an InterPAN message */ uint16 macDestAddr; /* MAC header destination short address */ uint8 endPoint; /* destination endpoint */ uint8 wasBroadcast; /* TRUE if network destination was a broadcast address */ uint8 LinkQuality; /* The link quality of the received data frame */ uint8 correlation; /* The raw correlation value of the received data frame */ int8 rssi; /* The received RF power in units dBm */ uint8 SecurityUse; /* deprecated */ uint32 timestamp; /* receipt timestamp from MAC */ uint8 nwkSeqNum; /* network header frame sequence number */ afMSGCommandFormat_t cmd; /* Application Data */ } afIncomingMSGPacket_t; afMSGCommandFormat_t结构体的声明: typedef struct { uint8 TransSeqNumber; //用于存储发送序列号; uint16 DataLength; //用于存储接收到的数据长度; uint8 *Data; //数据接收后放在一个缓冲区,该参数就是指向缓冲区的指针; } afMSGCommandFormat_t; |
相关推荐
全国咨询热线:400-611-6270
?2004-2018华清远见教育科技集团 版权所有 京ICP备16055225号 京公海网安备11010802025203号