9575|11

4996

帖子

19

TA的资源

裸片初长成(初级)

楼主
 

ZigBee 2007学习分享之串口透传<二> [复制链接]

本帖最后由 zhaojun_xf 于 2015-2-2 14:23 编辑

        ZigBee 2007的学习,想必都是从串口开始,既然是无线通信,当然我们就从串口透传开始吧,虽然这个是第二篇学习分享,但事实,这一篇涉及到的内容也还是非常之广的。

      对于串口透传,无外乎涉及到两个方面:一是串口的接收,二是通过无线发送。也可以从另外的角度来划分应用,一是网络连接,二是串口收发。下面我们就以第二种划分进行说明。


代码: Z-Stack透传.zip (13 MB, 下载次数: 1193)

此帖出自无线连接论坛

最新回复

楼主,真的太谢谢你了,帮了个大忙  详情 回复 发表于 2017-2-9 04:27
点赞 关注
个人签名我的博客
 

回复
举报

4996

帖子

19

TA的资源

裸片初长成(初级)

沙发
 
一. 网络连接

      首先需要在新的工作中填充一个事件处理函数,和一个初始化函数,这两个函数的添加位置在OSAL_SerialApp.c文件中,这一点在我们之前的《ZigBee 2007学习分享之从这里开始入门》中已经详细的说明了,在这里不再多说,这一贴我们只描述串口透传部分的内容。

1. 初始化

      在初始化函数中,我们只需要初始化串口相关的参数即可。串口初始化,有点像上位机中的串口初始化一样,通过对一个结构体变量进行赋值,再调用串口打开函数即可。

      要使用串口,必须要编译串口相关的代码,在IAR中通过对工程是设置进行,这添加HAL_UART=TRUE即可

  1. void SerialApp_Init( uint8 task_id )
  2. {
  3.   halUARTCfg_t uartConfig;

  4.   SerialApp_TaskID = task_id;
  5.   SerialApp_RxSeq = 0xC3;
  6.   SampleApp_NwkState = DEV_INIT;      
  7.   
  8.   afRegister( (endPointDesc_t *)&SerialApp_epDesc );

  9.   RegisterForKeys( task_id );

  10.   uartConfig.configured           = TRUE;              // 2x30 don't care - see uart driver.
  11.   uartConfig.baudRate             = SERIAL_APP_BAUD;
  12.   uartConfig.flowControl          = FALSE;
  13.   uartConfig.flowControlThreshold = SERIAL_APP_THRESH; // 2x30 don't care - see uart driver.
  14.   uartConfig.rx.maxBufSize        = SERIAL_APP_RX_SZ;  // 2x30 don't care - see uart driver.
  15.   uartConfig.tx.maxBufSize        = SERIAL_APP_TX_SZ;  // 2x30 don't care - see uart driver.
  16.   uartConfig.idleTimeout          = SERIAL_APP_IDLE;   // 2x30 don't care - see uart driver.
  17.   uartConfig.intEnable            = TRUE;              // 2x30 don't care - see uart driver.
  18.   uartConfig.callBackFunc         = SerialApp_CallBack;
  19.   HalUARTOpen (SERIAL_APP_PORT, &uartConfig);

  20. #if defined ( LCD_SUPPORTED )
  21.   HalLcdWriteString( "SerialApp", HAL_LCD_LINE_2 );
  22. #endif
  23.   
  24.   ZDO_RegisterForZDOMsg( SerialApp_TaskID, End_Device_Bind_rsp );
  25.   ZDO_RegisterForZDOMsg( SerialApp_TaskID, Match_Desc_rsp );
  26. }
复制代码

2. 网络连接
     网络连接由两个事件组成,一是网络请求,二是网络响应。在网络变化事件中,端点请求网络连接,并发送网络请求事件SERIALAPP_CONNECTREQ_CLUSTER。如果网络连接正常,同时发送一个响应事件SERIALAPP_CONNECTRSP_CLUSTER,从而完成网络连接。

  1. void  SerialApp_DeviceConnect()              
  2. {
  3. #if ZDO_COORDINATOR
  4.   
  5. #else
  6.   
  7.   uint16 nwkAddr;
  8.   uint16 parentNwkAddr;
  9.   char buff[30] = {0};
  10.   
  11.   HalLedBlink( HAL_LED_2, 3, 50, (1000 / 4) );
  12.   
  13.   nwkAddr = NLME_GetShortAddr();
  14.   parentNwkAddr = NLME_GetCoordShortAddr();
  15.   sprintf(buff, "parent:%d   self:%d\r\n", parentNwkAddr, nwkAddr);
  16.   HalUARTWrite ( 0, (uint8*)buff, strlen(buff));
  17.   
  18.   SerialApp_TxAddr.addrMode = (afAddrMode_t)Addr16Bit;
  19.   SerialApp_TxAddr.endPoint = SERIALAPP_ENDPOINT;
  20.   SerialApp_TxAddr.addr.shortAddr = parentNwkAddr;
  21.   
  22.   buff[0] = HI_UINT16( nwkAddr );
  23.   buff[1] = LO_UINT16( nwkAddr );
  24.   
  25.   if ( AF_DataRequest( &SerialApp_TxAddr, &SerialApp_epDesc,
  26.                        SERIALAPP_CONNECTREQ_CLUSTER,
  27.                        2,
  28.                        (uint8*)buff,
  29.                        &SerialApp_MsgID,
  30.                        0,
  31.                        AF_DEFAULT_RADIUS ) == afStatus_SUCCESS )
  32.   {
  33.   }
  34.   else
  35.   {
  36.     // Error occurred in request to send.
  37.   }
  38.   
  39. #endif    //ZDO_COORDINATOR
  40. }
复制代码

3. 网络事件的处理

    网络事件保护请求连接、连接响应,数据接收等。这些事件的处理函数为SerialApp_ProcessMSGCmd。

  1. void SerialApp_ProcessMSGCmd( afIncomingMSGPacket_t *pkt )
  2. {
  3.   uint8 stat;
  4.   uint8 seqnb;
  5.   uint8 delay;

  6.   switch ( pkt->clusterId )
  7.   {
  8.   // A message with a serial data block to be transmitted on the serial port.
  9.   case SERIALAPP_CLUSTERID1: //收到发送过来的数据通过串口输出到电脑显示
  10.     // Store the address for sending and retrying.
  11.     osal_memcpy(&SerialApp_RxAddr, &(pkt->srcAddr), sizeof( afAddrType_t ));

  12.     seqnb = pkt->cmd.Data[0];

  13.     // Keep message if not a repeat packet
  14.     if ( (seqnb > SerialApp_RxSeq) ||                    // Normal
  15.         ((seqnb < 0x80 ) && ( SerialApp_RxSeq > 0x80)) ) // Wrap-around
  16.     {
  17.         // Transmit the data on the serial port. // 通过串口发送数据到PC机
  18.         if ( HalUARTWrite( SERIAL_APP_PORT, pkt->cmd.Data+1, (pkt->cmd.DataLength-1) ) )
  19.         {
  20.           // Save for next incoming message
  21.           SerialApp_RxSeq = seqnb;
  22.           stat = OTA_SUCCESS;
  23.         }
  24.         else
  25.         {
  26.           stat = OTA_SER_BUSY;
  27.         }
  28.     }
  29.     else
  30.     {
  31.         stat = OTA_DUP_MSG;
  32.     }

  33.     // Select approproiate OTA flow-control delay.
  34.     delay = (stat == OTA_SER_BUSY) ? SERIALAPP_NAK_DELAY : SERIALAPP_ACK_DELAY;

  35.     // Build & send OTA response message.
  36.     SerialApp_RspBuf[0] = stat;
  37.     SerialApp_RspBuf[1] = seqnb;
  38.     SerialApp_RspBuf[2] = LO_UINT16( delay );
  39.     SerialApp_RspBuf[3] = HI_UINT16( delay );
  40.     osal_set_event( SerialApp_TaskID, SERIALAPP_RESP_EVT ); //收到数据后,发送一个响应事件
  41.     osal_stop_timerEx(SerialApp_TaskID, SERIALAPP_RESP_EVT);
  42.     break;

  43.   // A response to a received serial data block.   // 接到响应消息
  44.   case SERIALAPP_CLUSTERID2:
  45.     if ((pkt->cmd.Data[1] == SerialApp_TxSeq) &&
  46.        ((pkt->cmd.Data[0] == OTA_SUCCESS) || (pkt->cmd.Data[0] == OTA_DUP_MSG)))
  47.     {
  48.       SerialApp_TxLen = 0;
  49.       osal_stop_timerEx(SerialApp_TaskID, SERIALAPP_SEND_EVT);
  50.     }
  51.     else
  52.     {
  53.       // Re-start timeout according to delay sent from other device.
  54.       delay = BUILD_UINT16( pkt->cmd.Data[2], pkt->cmd.Data[3] );
  55.       osal_start_timerEx( SerialApp_TaskID, SERIALAPP_SEND_EVT, delay );
  56.     }
  57.     break;

  58.     case SERIALAPP_CONNECTREQ_CLUSTER:
  59.       SerialApp_ConnectReqProcess((uint8*)pkt->cmd.Data);
  60.       
  61.     case SERIALAPP_CONNECTRSP_CLUSTER:
  62.       SerialApp_DeviceConnectRsp((uint8*)pkt->cmd.Data);
  63.       
  64.     default:
  65.       break;
  66.   }
  67. }
复制代码



此帖出自无线连接论坛
个人签名我的博客
 
 
 

回复

4996

帖子

19

TA的资源

裸片初长成(初级)

板凳
 
二、串口收发

       串口数据的接收来自串口函数的回调,回调函数为SerialApp_CallBack,我们的代码并没有直接调用这个函数,二是OSAL系统通过定时扫描并调用。而这个回调函数中的内容需要我们去填写。


1. 串口数据的发送

    串口数据的接收是系统周期性的扫描得到。如果缓冲中有数据,那么我们通过网络发送函数AF_DataRequest进行数据发送,同时产生一个SERIALAPP_CLUSTERID1事件。而另外一个设备则通过这个事件进行数据的接收。

  1. static void SerialApp_Send(void)
  2. {
  3. #if SERIAL_APP_LOOPBACK
  4.     if (SerialApp_TxLen < SERIAL_APP_TX_MAX)
  5.     {
  6.         SerialApp_TxLen += HalUARTRead(SERIAL_APP_PORT, SerialApp_TxBuf+SerialApp_TxLen+1,
  7.                                                       SERIAL_APP_TX_MAX-SerialApp_TxLen);
  8.     }
  9.   
  10.     if (SerialApp_TxLen)
  11.     {
  12.       (void)SerialApp_TxAddr;
  13.       if (HalUARTWrite(SERIAL_APP_PORT, SerialApp_TxBuf+1, SerialApp_TxLen))
  14.       {
  15.         SerialApp_TxLen = 0;
  16.       }
  17.       else
  18.       {
  19.         osal_set_event(SerialApp_TaskID, SERIALAPP_SEND_EVT);
  20.       }
  21.     }
  22. #else
  23.     if (!SerialApp_TxLen &&
  24.         (SerialApp_TxLen = HalUARTRead(SERIAL_APP_PORT, SerialApp_TxBuf+1, SERIAL_APP_TX_MAX)))
  25.     {
  26.       // Pre-pend sequence number to the Tx message.
  27.       SerialApp_TxBuf[0] = ++SerialApp_TxSeq;
  28.     }
  29.   
  30.     if (SerialApp_TxLen)
  31.     {
  32.       if (afStatus_SUCCESS != AF_DataRequest(&SerialApp_TxAddr,
  33.                                              (endPointDesc_t *)&SerialApp_epDesc,
  34.                                               SERIALAPP_CLUSTERID1,
  35.                                               SerialApp_TxLen+1, SerialApp_TxBuf,
  36.                                               &SerialApp_MsgID, 0, AF_DEFAULT_RADIUS))
  37.       {
  38.         osal_set_event(SerialApp_TaskID, SERIALAPP_SEND_EVT);
  39.       }
  40.     }
  41. #endif
  42. }
复制代码


2. 串口数据的接收

    到有数据从空中发送被设备接收到后,设备将产生一个网络事件,通过这个事件我们可以判断是否有数据接收。如果有这样的数据,我们需要对这个事件进行处理,并把相应的数据通过串口发送给PC,从而实现这个透传功能。

  1.   case SERIALAPP_CLUSTERID1: //收到发送过来的数据通过串口输出到电脑显示
  2.     // Store the address for sending and retrying.
  3.     osal_memcpy(&SerialApp_RxAddr, &(pkt->srcAddr), sizeof( afAddrType_t ));

  4.     seqnb = pkt->cmd.Data[0];

  5.     // Keep message if not a repeat packet
  6.     if ( (seqnb > SerialApp_RxSeq) ||                    // Normal
  7.         ((seqnb < 0x80 ) && ( SerialApp_RxSeq > 0x80)) ) // Wrap-around
  8.     {
  9.         // Transmit the data on the serial port. // 通过串口发送数据到PC机
  10.         if ( HalUARTWrite( SERIAL_APP_PORT, pkt->cmd.Data+1, (pkt->cmd.DataLength-1) ) )
  11.         {
  12.           // Save for next incoming message
  13.           SerialApp_RxSeq = seqnb;
  14.           stat = OTA_SUCCESS;
  15.         }
  16.         else
  17.         {
  18.           stat = OTA_SER_BUSY;
  19.         }
  20.     }
  21.     else
  22.     {
  23.         stat = OTA_DUP_MSG;
  24.     }

  25.     // Select approproiate OTA flow-control delay.
  26.     delay = (stat == OTA_SER_BUSY) ? SERIALAPP_NAK_DELAY : SERIALAPP_ACK_DELAY;

  27.     // Build & send OTA response message.
  28.     SerialApp_RspBuf[0] = stat;
  29.     SerialApp_RspBuf[1] = seqnb;
  30.     SerialApp_RspBuf[2] = LO_UINT16( delay );
  31.     SerialApp_RspBuf[3] = HI_UINT16( delay );
  32.     osal_set_event( SerialApp_TaskID, SERIALAPP_RESP_EVT ); //收到数据后,发送一个响应事件
  33.     osal_stop_timerEx(SerialApp_TaskID, SERIALAPP_RESP_EVT);
  34.     break;
复制代码



此帖出自无线连接论坛
个人签名我的博客
 
 
 

回复

4996

帖子

19

TA的资源

裸片初长成(初级)

4
 
可能大家刚开始在看这个串口透传工程时很难看清其具体的工作流程。这主要是Zstack采用了操作系统的方式编写代码,我们实际上只是做了些填空题而已。

其次,很多功能,Zstack是通过回调和事件进行的,而且它把协调器、路由和终端代码用一个工程统一管理,容易把人绕进去。

实际上如果要来简单理解这个应用,其实并不难。我们值需要把网络上接收的数据通过串口发送到PC,同时把从PC中接收的数据通过网络发送出去即可。而其他的只不过添加了一下重复机制而已。
此帖出自无线连接论坛
个人签名我的博客
 
 
 

回复

6105

帖子

4

TA的资源

版主

5
 
OK ,很好,很好。赞一个!
此帖出自无线连接论坛
 
 
 

回复

86

帖子

1

TA的资源

一粒金砂(中级)

6
 
问下楼主,如果串口发送数据过快,串口数据就发送不出来了是什么情况。
此帖出自无线连接论坛
 
 
 

回复

136

帖子

0

TA的资源

一粒金砂(中级)

7
 
mark下 ~ 学习了 !
此帖出自无线连接论坛
 
 
 

回复

7

帖子

0

TA的资源

一粒金砂(初级)

8
 
好东西,绝对顶起
此帖出自无线连接论坛
 
 
 

回复

1

帖子

0

TA的资源

一粒金砂(初级)

9
 
可以对多个节点实现透传吗?
此帖出自无线连接论坛
 
 
 

回复

10

帖子

0

TA的资源

一粒金砂(初级)

10
 
谢谢分享
此帖出自无线连接论坛
 
 
 

回复

22

帖子

0

TA的资源

一粒金砂(中级)

11
 
多谢分享,目前正在做这部分工作
此帖出自无线连接论坛
 
 
 

回复

3

帖子

0

TA的资源

一粒金砂(初级)

12
 
楼主,真的太谢谢你了,帮了个大忙
此帖出自无线连接论坛
 
 
 

回复
您需要登录后才可以回帖 登录 | 注册

随便看看
查找数据手册?

EEWorld Datasheet 技术支持

相关文章 更多>>
关闭
站长推荐上一条 1/9 下一条

 
EEWorld订阅号

 
EEWorld服务号

 
汽车开发圈

About Us 关于我们 客户服务 联系方式 器件索引 网站地图 最新更新 手机版

站点相关: 国产芯 安防电子 汽车电子 手机便携 工业控制 家用电子 医疗电子 测试测量 网络通信 物联网

北京市海淀区中关村大街18号B座15层1530室 电话:(010)82350740 邮编:100190

电子工程世界版权所有 京B2-20211791 京ICP备10001474号-1 电信业务审批[2006]字第258号函 京公网安备 11010802033920号 Copyright © 2005-2025 EEWORLD.com.cn, Inc. All rights reserved
快速回复 返回顶部 返回列表