zigbee协议栈应用(四)广播组网-无线数据传输

来源:互联网 发布:毒性数据库 编辑:程序博客网 时间:2024/05/02 02:54

1.具体实现:终端通过无线把数据传给协调器,协调器再将数据通过串口传给电脑显示~

打开之前的串口程序,串口部分就不用讲了,直接进入无线的收发

2.代码的增加:

1).  接收数据 (红色字体为新增代码)
SampleApp_MessageMSGCB, , 在 函数 case SAMPLEAPP_PERIODIC_CLUSTERID: 下 面增 加 三
行代码,修改后如下:
void SampleApp_MessageMSGCB( afIncomingMSGPacket_t *pkt )  // 接收数据
{
uint16 flashTime;
switch ( pkt->clusterId )
{
case SAMPLEAPP_PERIODIC_CLUSTERID:
HalUARTWrite(0, "Rx:", 3);  // 提示信息
HalUARTWrite(0, pkt->cmd.Data, pkt->cmd.DataLength);  // 输出接收到的数据
HalUARTWrite(0, "\n", 1);  // 回车换行
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;
}
}
2).  发送数据 (红色字体为新增代码)
void SampleApp_SendPeriodicMessage( void )  // 周期发送函数
{
uint8 data[11]="0123456789";
// 调用  AF_DataRequest  将数据无线广播出去,在第一个实验详解里就不重复了。
if ( AF_DataRequest( &SampleApp_Periodic_DstAddr, &SampleApp_epDesc,
SAMPLEAPP_PERIODIC_CLUSTERID,
10,
data,
&SampleApp_TransID,
AF_DISCV_ROUTE,
AF_DEFAULT_RADIUS ) == afStatus_SUCCESS )
{
}
else
{
// Error occurred in request to send.
}
}

1).选择 CoodinatorEB, 下载到板 A;作为协调器,通过 USB 线跟电脑连接.
2).选择 EndDeviceEB, 下载到板 B;作为终端设备无线发送数据给协调器 

3).给两块开发板 上电,打开串口调试助手,设为:115200 8N1 ,协调器间隔 5S 会收到终端发过来的数据。

3.重点难点理解

接收部分: 接收数据主要工作:
1) 读取接收到的数据
2) 把数据通过串口发送给 C PC 机  在
SampleApp.c 中搜索 SampleApp_ProcessEvent ,找到如下代码处:
case AF_INCOMING_MSG_CMD:
SampleApp_MessageMSGCB( MSGpkt );
break;
其中  SampleApp_MessageMSGCB( MSGpkt );就是接收处理函数。
void SampleApp_MessageMSGCB( afIncomingMSGPacket_t *pkt )  // 接收数据
{
uint16 flashTime;
switch ( pkt->clusterId )
{
case SAMPLEAPP_PERIODIC_CLUSTERID:
HalUARTWrite(0, "Rx:", 3);  // 提示信息
HalUARTWrite(0, pkt->cmd.Data, pkt->cmd.DataLength);  //

HalUARTWrite(0, "\n", 1);  // 回车换行
break;
}
}

SAMPLEAPP_PERIODIC_CLUSTERID 这个宏定义是不是有点眼熟?没错,这就是我们前面
发送函数定义的数据包的 ID 号,它的作用很明显了,如果收到的 ID 号相同说明是我们自己
定 义的周期性广播包。所有的数据和信息都在函数传入来的 afIncomingMSGPacket_t *pkt里
面, 进入 afIncomingMSGPacket_t 的定义,它是一个结构体,内容如下:
typedef struct
{
osal_event_hdr_t hdr; /* OSAL Message header OSAL 消息头 */
uint16 groupId;  /* Message's group ID - - 0 0 if not set 消息组  ID */
uint16 clusterId;  /* Message's cluster ID 消息族  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 C MAC  物理地址 */
uint8 endPoint;  /* destination endpoint MAC 目的端点 */
uint8 wasBroadcast;  /* 广播地址 */
uint8 LinkQuality;  /* 接收数据帧的链路质量 */
uint8 correlation;  /* 接收数据帧的未加工相关值 */
int8 rssi;  /* The received RF power in units m dBm  接收的射频功率 */
uint8 SecurityUse;  /* deprecated 弃用 */
uint32 timestamp;  /* receipt timestamp from C MAC  收到时间标记 */
afMSGCommandFormat_t cmd; /* Application Data  应用程序数据*/
} afIncomingMSGPacket_t;  // 无线数据包格式结构体
那么数据在哪里呢?在红色那行,又是一个结构体,继续进入。
// Generalized MSG Command Format
typedef struct
{ {
byte TransSeqNumber;
uint16 DataLength; // Number of bytes in TransData
byte *Data;
} } afMSGCommandFormat_t; 千呼万唤始出来,现在就可以通过程序将数据读出了。通过
osal_memcpy 复制到数据中处理了, 如:osal_memcpy( buf, MSGpkt->cmd.Data, MSGpkt-
>cmd.DataLength );
二、 发送部分 发送部分主要工作:设置发送内容,启动定时器,周
期性地发送。同样在 SampleApp_ProcessEven 函数找到如下代码:
1. case ZDO_STATE_CHANGE: // 当网络状态改变,所有节点都会发生
2. SampleApp_NwkState = = (devStates_t)(MSGpkt- - >hdr.status);
3. if ( ( //(SampleApp_NwkState == DEV_ZB_COORD) || // 协议器不用发送所以屏蔽
4. (SampleApp_NwkState == DEV_ROUTER) // 路由器

5. || (SampleApp_NwkState == DEV_END_DEVICE) ) ) // 终端设备
6. { {
7. // Start sending the periodic message in a a regular interval.
8. osal_start_timerEx( SampleApp_TaskID,
SAMPLEAPP_SEND_PERIODIC_MSG_EVT,
SAMPLEAPP_SEND_PERIODIC_MSG_TIMEOUT );
9. } }
第 8 行:红色字体标出的为关键代码。osal_start_timerEx 三个参数决定着周期性发送数据的
命脉。我们逐一分析。
Sample e App_ _ TaskID D :任务 ID,函数 SampleApp_Init ()开头定义了 SampleApp_TaskID = task_id;
也就是 SampleApp 初始化的任务 ID 号。
SAMPLEAPP_AA_PERIODIC_MSG_EVT :
#define SAMPLEAPP_SEND_PERIODIC_MSG_EVT 0x0001
同一个任务下可以有多个事件,这个是事件的编号。我们可以定义自己的事件,但是编号不
能重复。
SAMPLEAPP_AA_PERIODIC_MSG_TIMEOUT :
#define SAMPLEAPP_SEND_PERIODIC_MSG_TIMEOUT 5000
事件重复执行的时间。这里以毫秒为单位,所以是 5s,也就是刚刚实验为什么间隔约 5s 收到数
据的原因。这里可以改成你需要发送的时间间隔。 注意:ZDO_STATE_CHANGE 只有当设
备网络发生改变后才会触发,所以在此处可做一些 初始化工作;如果网络一直连接的就不会
再次进入这个函数了,只执行 1 次。 在同一函数内找到如下代码:
// 判断 T SAMPLEAPP_SEND_PERIODIC_MSG_EVT  有没有发生,如果有的就执行下面函数
1. if ( ( events & & SAMPLEAPP_SEND_PERIODIC_MSG_EVT ) )
2. { {
3. // Send the periodic message
4. SampleApp_SendPeriodicMessage();
5. // Setup to send message again in normal period (+ a a little jitter)
6. osal_start_timerEx( SampleApp_TaskID, SAMPLEAPP_SEND_PERIODIC_MSG_EVT,
7. (SAMPLEAPP_SEND_PERIODIC_MSG_TIMEOUT + + (osal_rand() & & 0x00FF)) );
8. // return unprocessed events
9. return (events ^ ^ SAMPLEAPP_SEND_PERIODIC_MSG_EVT);
10. } }
第 4 行: SampleApp_SendPeriodicMessage();是我们发送数据的函数:
void SampleApp_SendPeriodicMessage( void ) )
{ {
uint8 data[11]="0123456789";
if ( ( AF_DataRequest( &SampleApp_Periodic_DstAddr, &SampleApp_epDesc,

{ {
} }
else
{ {
SAMPLEAPP_PERIODIC_CLUSTERID, //簇 簇  ID
10, // 发送数据的长度
data, // 数据的缓冲区
&SampleApp_TransID,
AF_DISCV_ROUTE,
AF_DEFAULT_RADIUS ) ) == afStatus_SUCCESS ) )
// Error occurred in request to send.
} }
} }
如果想修改发送的字符,只需修改 data 和 len 即可

0 0