ZStack-CC2530协议栈串口透传实验

协议栈Z-STACK 2007中广播通信的方法 实验内容:在协调器一方(串口助手发送窗口)将一字符通过广播的方式发送给路由器,并在它的串口助手接收窗口中显示出来,若为“1”,则点亮D2,若为“0”,则熄灭D2,若为其他字符,则助手中显示“error”。

  • 准备工作
    为了更好的清晰的,最好把ZStack-CC2530-2.5.1a文件夹赋值成两份,分别把协调器和路由器(CoordinatorEB和routerEB)如下图:
    ZStack-CC2530协议栈串口透传实验
    文章图片

  • 协调器编写
uint16 SampleApp_ProcessEvent( uint8 task_id, uint16 events ){ ........... case ZDO_STATE_CHANGE: SampleApp_NwkState = (devStates_t)(MSGpkt->hdr.status); if ( (SampleApp_NwkState == DEV_ZB_COORD)) { // Start sending the periodic message in a regular interval. HalLedSet (HAL_LED_1, HAL_LED_MODE_ON); HalLedSet (HAL_LED_2, HAL_LED_MODE_ON); } else { // Device is no longer in the network } break; ........... }

之所以把原来的:
if ( (SampleApp_NwkState == DEV_ZB_COORD)||(SampleApp_NwkState == DEV_ROUTER)||(SampleApp_NwkState == DEV_END_DEVICE))

改为上述的:
if ( (SampleApp_NwkState == DEV_ZB_COORD))

就是为了更为明确加入网络的是协调器。在if条件语句里面加入点亮两盏灯是为了判断当前设备网络状态是否为协调器。
若想在设备网络状态进入DEV_ZB_COORD状态就现实发送数据并且是每隔一段时间就发送数据,则在if判断语句加入一条语句:
osal_start_timerEx( SampleApp_TaskID,SAMPLEAPP_SEND_PERIODIC_MSG_EVT,SAMPLEAPP_SEND_PERIODIC_MSG_TIMEOUT );

SAMPLEAPP_SEND_PERIODIC_MSG_EVT事件里面包含语句有
if ( events & SAMPLEAPP_SEND_PERIODIC_MSG_EVT ) { // Send the periodic message SampleApp_SendPeriodicMessage(); // Setup to send message again in normal period (+ a little jitter) osal_start_timerEx( SampleApp_TaskID, SAMPLEAPP_SEND_PERIODIC_MSG_EVT, (SAMPLEAPP_SEND_PERIODIC_MSG_TIMEOUT + (osal_rand() & 0x00FF)) ); // return unprocessed events return (events ^ SAMPLEAPP_SEND_PERIODIC_MSG_EVT); }

但题目是要求是在协调器的对应的串口助手先发送一个字符然后路由器接受一个字符,所以不应该在if判断语句体里面加 osal_start_timerEx()函数而且 if ( events & SAMPLEAPP_SEND_PERIODIC_MSG_EVT )语句体里面也应该把osal_start_timerEx()函数注销(防止定期发送数据)。
正确方式:在串口事件函数加入。
void SampleApp_SerialCMD(mtOSALSerialData_t *cmdMsg){ ............ for(i=1; i<=len; i++) { SampleAppPeriodicCounter=*(str+i); osal_start_timerEx( SampleApp_TaskID,SAMPLEAPP_SEND_PERIODIC_MSG_EVT,SAMPLEAPP_SEND_PERIODIC_MSG_TIMEOUT ); //或不要osal_start_timerEx(0函数,直接使用SampleApp_SendPeriodicMessage(); 函数效率更快 break; } ...................... }

协调器到此结束,若不允许协调器接收数据应该把SampleApp_MessageMSGCB( MSGpkt ); 函数注销。
case AF_INCOMING_MSG_CMD: SampleApp_MessageMSGCB( MSGpkt );

  • 路由器
case AF_INCOMING_MSG_CMD: SampleApp_MessageMSGCB( MSGpkt ); break;

在协调器注销的SampleApp_MessageMSGCB( MSGpkt ); 在路由器这里要开启,让路由器可以接收数据。
下面这段代码的目的与协调器的一样,若两盏灯没有点亮,则说明设备的网络状态加入DEV_ROUTER失败。
解决办法:
1、在工作空间一点要选择RouterEB
ZStack-CC2530协议栈串口透传实验
文章图片
2、若执行步骤1仍然不行,继步骤1后,这直接手动改为路由器模式;修改如下:
case ZDO_STATE_CHANGE: SampleApp_NwkState = (devStates_t)(MSGpkt->hdr.status);

点击Edit–>File and Replace–>Find in Files寻找ZDO_STATE_CHANGE
ZStack-CC2530协议栈串口透传实验
文章图片

pMsg->event = ZDO_STATE_CHANGE; //把pMsg->status = state; 修改为pMsg->status = DEV_ROUTER; pMsg->status = state;

case ZDO_STATE_CHANGE: SampleApp_NwkState = (devStates_t)(MSGpkt->hdr.status); if ((SampleApp_NwkState == DEV_ROUTER)) { HalLedSet (HAL_LED_1, HAL_LED_MODE_ON); HalLedSet (HAL_LED_2, HAL_LED_MODE_ON); }

//这就是实现题目要求的函数
void SampleApp_MessageMSGCB( afIncomingMSGPacket_t *pkt ) { uint16 flashTime; switch ( pkt->clusterId ) { case SAMPLEAPP_PERIODIC_CLUSTERID: if((pkt->cmd.Data[0])=='0') { HalLedSet (HAL_LED_1, HAL_LED_MODE_OFF); } else if((pkt->cmd.Data[0])=='1') { HalLedSet (HAL_LED_1, HAL_LED_MODE_ON); } else { HalUARTWrite(0,"error\n",5); } 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; } }

  • 操作步骤
    分别把CoordinatorEB和routerEB下载到实验板上,在CoordinatorEB对应的串口助手上发送一个字符。若字符不是’0’或’1’则在routerEB串口助手上显示字符串"error"!
  • 【ZStack-CC2530协议栈串口透传实验】源码下载
    github源码下载连接

    推荐阅读