我是靠谱客的博主 迷你时光,最近开发中收集的这篇文章主要介绍zigbee协议栈应用(六)zigbee串口透传之无线QQ,觉得挺不错的,现在分享给大家,希望可以做个参考。

概述

由于协议栈代码量比较复杂繁多,直接理解的话可能会比较吃力,故开发时只对部分代码进行修改,适当时,理解一些底层的代码!

1.打开原先的串口的程序,Projectszstack目录下只需保留如下:


ProjectszstackUtilitiesSerialAppCC2530DB目录下打开工程

2.将命令添加到命令列表,增加协调器与终端握手的 ID,分别是请求与应答.
const cId_t SerialApp_ClusterList[SERIALAPP_MAX_CLUSTERS] =
{
SERIALAPP_CLUSTERID1,
SERIALAPP_CLUSTERID2,
SERIALAPP_CONNECTREQ_CLUSTER,  //请求
SERIALAPP_CONNECTRSP_CLUSTER   //应答
};
#define SERIALAPP_MAX_CLUSTERS  4//ID数

3.应用层初始化:SerialApp_Init 函数

void SerialApp_Init( uint8 task_id )
{
halUARTCfg_t uartConfig;  //串口配置结构体
SerialApp_TaskID = task_id;  //任务 ID
SerialApp_RxSeq = 0xC3;  //接收序列
SampleApp_NwkState = DEV_INIT;//网络状态
afRegister( (endPointDesc_t *)&SerialApp_epDesc ); //注册端口描述符
RegisterForKeys( task_id );  //注册按键事件
uartConfig.configured  = TRUE;  // 2x30 don't care - see uart
driver.
uartConfig.baudRate  = SERIAL_APP_BAUD;
uartConfig.flowControl = FALSE;
uartConfig.flowControlThreshold = SERIAL_APP_THRESH;// 流控
uartConfig.rx.maxBufSize = SERIAL_APP_RX_SZ; // 2x30 don't care - see uart driver.
uartConfig.tx.maxBufSize = SERIAL_APP_TX_SZ; // 2x30 don't care - see uart driver.
uartConfig.idleTimeout = SERIAL_APP_IDLE; // 2x30 don't care - see uart driver.
uartConfig.intEnable  = TRUE; // 2x30 don't care - see uart driver.
uartConfig.callBackFunc = SerialApp_CallBack; //接收回调函数
HalUARTOpen (SERIAL_APP_PORT, &uartConfig); //打开串口
#if defined ( LCD_SUPPORTED )
HalLcdWriteString( "SerialApp", HAL_LCD_LINE_2 );
#endif
ZDO_RegisterForZDOMsg( SerialApp_TaskID, End_Device_Bind_rsp ); //注册绑定
ZDO_RegisterForZDOMsg( SerialApp_TaskID, Match_Desc_rsp );  //相关的事件
}

typedef enum
{
  DEV_HOLD,               // Initialized - not started automatically
  DEV_INIT,               // Initialized - not connected to anything
  DEV_NWK_DISC,           // Discovering PAN's to join
  DEV_NWK_JOINING,        // Joining a PAN
  DEV_NWK_REJOIN,         // ReJoining a PAN, only for end devices
  DEV_END_DEVICE_UNAUTH,  // Joined but not yet authenticated by trust center
  DEV_END_DEVICE,         // Started as device after authentication
  DEV_ROUTER,             // Device joined, authenticated and is a router
  DEV_COORD_STARTING,     // Started as Zigbee Coordinator
  DEV_ZB_COORD,           // Started as Zigbee Coordinator
  DEV_NWK_ORPHAN          // Device has lost information about its parent..
} devStates_t;//网络状态枚举

4.事件处理:SerialApp_ProcessEvent 函数//当有事件传递到应用层的时候,执行此处

UINT16 SerialApp_ProcessEvent( uint8 task_id, UINT16 events )
{
(void)task_id; // Intentionally unreferenced parameter
if ( events & SYS_EVENT_MSG )
{
afIncomingMSGPacket_t *MSGpkt;
while  (  (MSGpkt  =  (afIncomingMSGPacket_t
*)osal_msg_receive( SerialApp_TaskID )) )
{
switch ( MSGpkt->hdr.event )
{
case AF_INCOMING_MSG_CMD:
SerialApp_ProcessMSGCmd( MSGpkt );
break;
case ZDO_STATE_CHANGE:
SampleApp_NwkState = (devStates_t)(MSGpkt->hdr.status);
if ( (SampleApp_NwkState == DEV_ZB_COORD)
|| (SampleApp_NwkState == DEV_ROUTER)
|| (SampleApp_NwkState == DEV_END_DEVICE) )
{
// Start sending the periodic message in a regular interval.
HalLedSet(HAL_LED_1, HAL_LED_MODE_ON);
if(SampleApp_NwkState != DEV_ZB_COORD)//当网络状态不是处于协调器状态,则连接设备
SerialApp_DeviceConnect();//路由器或终端设备连接协调器


}
else
{
// Device is no longer in the network
}
break;
default:
break;
}
osal_msg_deallocate( (uint8 *)MSGpkt );
}
return ( events ^ SYS_EVENT_MSG );
}
if ( events & SERIALAPP_SEND_EVT )
{
SerialApp_Send();  //串口发送
return ( events ^ SERIALAPP_SEND_EVT );
}
if ( events & SERIALAPP_RESP_EVT )
{
SerialApp_Resp();  //串口响应
return ( events ^ SERIALAPP_RESP_EVT );
}
return ( 0 ); // Discard unknown events.
}

//路由器或终端设备连接协调器

void  SerialApp_DeviceConnect(void)              
{
#if ZDO_COORDINATOR
  
#else
  
  uint16 nwkAddr;
  uint16 parentNwkAddr;
  char buff[30] = {0};
  
  HalLedBlink( HAL_LED_2, 3, 50, (1000 / 4) );
  
  nwkAddr = NLME_GetShortAddr();
  parentNwkAddr = NLME_GetCoordShortAddr();
  sprintf(buff, "parent:%d   self:%drn", parentNwkAddr, nwkAddr);
  HalUARTWrite ( 0, (uint8*)buff, strlen(buff));
  
  SerialApp_TxAddr.addrMode = (afAddrMode_t)Addr16Bit;
  SerialApp_TxAddr.endPoint = SERIALAPP_ENDPOINT;
  SerialApp_TxAddr.addr.shortAddr = parentNwkAddr;
  
  buff[0] = HI_UINT16( nwkAddr );
  buff[1] = LO_UINT16( nwkAddr );
  
  if ( AF_DataRequest( &SerialApp_TxAddr, &SerialApp_epDesc,//向协调器发送
                       SERIALAPP_CONNECTREQ_CLUSTER,
                       2,
                       (uint8*)buff,
                       &SerialApp_MsgID, 
                       0, 
                       AF_DEFAULT_RADIUS ) == afStatus_SUCCESS )
  {
  }
  else
  {
    // Error occurred in request to send.
  }
  
#endif    //ZDO_COORDINATOR
}

5.串口发送SerialApp_Send 函数

static void SerialApp_Send(void)
{
#if SERIAL_APP_LOOPBACK //回路测试 不会执行
if (SerialApp_TxLen < SERIAL_APP_TX_MAX)
{
SerialApp_TxLen  +=  HalUARTRead(SERIAL_APP_PORT,
SerialApp_TxBuf+SerialApp_TxLen+1,
SERIAL_APP_TX_MAX-SerialApp_TxLen);
}
if (SerialApp_TxLen)
{
(void)SerialApp_TxAddr;
if (HalUARTWrite(SERIAL_APP_PORT, SerialApp_TxBuf+1, SerialApp_TxLen))
{
SerialApp_TxLen = 0;
}
else
{
}
}
#else
osal_set_event(SerialApp_TaskID, SERIALAPP_SEND_EVT);
// SerialApp_TxLen 不为 0 时 代表有数据要发送或者正在发送
// SerialApp_TxLen 为 0 时 代表没有数据发送或者已经发送完了。发送端接收到接收端的
确认信息后,确定本次数据已经被接收到会将 SerialApp_TxLen 置 0 为接收下次数据作准备
if (!SerialApp_TxLen &&
(SerialApp_TxLen  =  HalUARTRead(SERIAL_APP_PORT,  SerialApp_TxBuf+1,
SERIAL_APP_TX_MAX)))
{
// Pre-pend sequence number to the Tx message.
SerialApp_TxBuf[0] = ++SerialApp_TxSeq;
}
if (SerialApp_TxLen) // 如果接收到内容
{
//将串口接收到的数据无线发送出去
if  (afStatus_SUCCESS  !=  AF_DataRequest(&SerialApp_TxAddr,
(endPointDesc_t *)&SerialApp_epDesc,
SERIALAPP_CLUSTERID1,
SerialApp_TxLen+1, SerialApp_TxBuf,
&SerialApp_MsgID, 0, AF_DEFAULT_RADIUS))
{
osal_set_event(SerialApp_TaskID, SERIALAPP_SEND_EVT); //发送失败则重发
}
}
#endif
}

6.SerialApp_ProcessMSGCmd函数  在收到空中的信号后,通过串口传递给PC显示

void SerialApp_ProcessMSGCmd( afIncomingMSGPacket_t *pkt )
{
uint8 stat;
uint8 seqnb;
uint8 delay;
switch ( pkt->clusterId )
{
// A message with a serial data block to be transmitted on the serial port.
case SERIALAPP_CLUSTERID1: //收到发送过来的数据通过串口输出到电脑显示
// Store the address for sending and retrying.
osal_memcpy(&SerialApp_RxAddr, &(pkt->srcAddr), sizeof( afAddrType_t ));
seqnb = pkt->cmd.Data[0];
// Keep message if not a repeat packet
if ( (seqnb > SerialApp_RxSeq) ||  // Normal
((seqnb < 0x80 ) && ( SerialApp_RxSeq > 0x80)) ) // Wrap-around
{
// Transmit the data on the serial port. // 通过串口发送数据到 PC 机
if  (  HalUARTWrite(  SERIAL_APP_PORT,  pkt->cmd.Data+1,
(pkt->cmd.DataLength-1) ) )
{
// Save for next incoming message
SerialApp_RxSeq = seqnb;
stat = OTA_SUCCESS;
}
else
{
stat = OTA_SER_BUSY;
}
}
else
{
stat = OTA_DUP_MSG;
}
// Select approproiate OTA flow-control delay.
delay = (stat == OTA_SER_BUSY) ? SERIALAPP_NAK_DELAY : SERIALAPP_ACK_DELAY;
// Build & send OTA response message.
SerialApp_RspBuf[0] = stat;
SerialApp_RspBuf[1] = seqnb;
SerialApp_RspBuf[2] = LO_UINT16( delay );
SerialApp_RspBuf[3] = HI_UINT16( delay );
//收到数据后,发送一个响应事件
osal_set_event( SerialApp_TaskID, SERIALAPP_RESP_EVT );
osal_stop_timerEx(SerialApp_TaskID, SERIALAPP_RESP_EVT);
break;
// 接到响应消息
case SERIALAPP_CLUSTERID2:
if ((pkt->cmd.Data[1] == SerialApp_TxSeq) &&
((pkt->cmd.Data[0] == OTA_SUCCESS) || (pkt->cmd.Data[0] == OTA_DUP_MSG)))
{
SerialApp_TxLen = 0;
osal_stop_timerEx(SerialApp_TaskID, SERIALAPP_SEND_EVT);
}
else
{
// Re-start timeout according to delay sent from other device.
delay = BUILD_UINT16( pkt->cmd.Data[2], pkt->cmd.Data[3] );
osal_start_timerEx( SerialApp_TaskID, SERIALAPP_SEND_EVT, delay );
}
break;
case SERIALAPP_CONNECTREQ_CLUSTER:
SerialApp_ConnectReqProcess((uint8*)pkt->cmd.Data);
case SERIALAPP_CONNECTRSP_CLUSTER:
SerialApp_DeviceConnectRsp((uint8*)pkt->cmd.Data);
default:
break;
}
}

最后实现如下:


最后

以上就是迷你时光为你收集整理的zigbee协议栈应用(六)zigbee串口透传之无线QQ的全部内容,希望文章能够帮你解决zigbee协议栈应用(六)zigbee串口透传之无线QQ所遇到的程序开发问题。

如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。

本图文内容来源于网友提供,作为学习参考使用,或来自网络收集整理,版权属于原作者所有。
点赞(53)

评论列表共有 0 条评论

立即
投稿
返回
顶部