请选择 进入手机版 | 继续访问电脑版
查看: 6027|回复: 7

SerailAPP 多对一通信 方法

[复制链接]
神经火光 发表于 2012-8-17 11:28:37 | 显示全部楼层 |阅读模式
本帖最后由 神经火光 于 2012-8-17 11:33 编辑

     最近在使用SerailAPP 实现星形网,使用其串口通信功能,希望实现多对一的功能,愿望是好的,实现起来确实遇到写问题!

实现点对点通信很方便,实现多对一却遇到了阻碍,不是不能加入网络,而是,加入网络后无法实现数据传输。问题是,在很长一

段时间内只能有一个在通信,当然也会有两个一起通信的时候。

主要问题在与,SerailApp 帮我们实现串口无线收发的同时,也在串口程序中加入了 序列号,防止数据重发重收,具体如下:

首先,是串口接受,然后无线发送的程序(EndDevice):

static void SerialApp_SendData( uint8 *buf, uint8 len )
{
  afStatus_t stat;

  // Pre-pend sequence number to the start of the Rx buffer.
  *buf = ++SerialApp_SeqTx;

  otaBuf = buf;
  otaLen = len+1;

  stat = AF_DataRequest( &SerialApp_DstAddr,
                         (endPointDesc_t *)&SerialApp_epDesc,
                          SERIALAPP_CLUSTERID1,
                          otaLen, otaBuf,
                          &SerialApp_MsgID, 0, AF_DEFAULT_RADIUS );

  if ( (stat == afStatus_SUCCESS) || (stat == afStatus_MEM_FAIL) )
  {
    osal_start_timerEx( SerialApp_TaskID, SERIALAPP_MSG_RTRY_EVT,
                      SERIALAPP_MSG_RTRY_TIMEOUT );
    rtryCnt = SERIALAPP_MAX_RETRIES;
  }
  else
  {
    FREE_OTABUF();
  }
}


可以看到,在

  // Pre-pend sequence number to the start of the Rx buffer.
  *buf = ++SerialApp_SeqTx;


处为buf 加了一个序列号,这个序列号会在协调器接受之后进行判断

Coordinator 处处理程序:

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:
    seqnb = pkt->cmd.Data[0];

    // Keep message if not a repeat packet,控制是不是同一个包应该由硬件自己控制得把

   
  if ( (seqnb > SerialApp_SeqRx) ||                    // Normal
      ((seqnb < 0x80 ) && ( SerialApp_SeqRx > 0x80)) ) // Wrap-around

    {
      // Transmit the data on the serial port.
      if ( HalUARTWrite( SERIAL_APP_PORT, pkt->cmd.Data+1,
                                         (pkt->cmd.DataLength-1) ) )
      {
        // Save for next incoming message
        SerialApp_SeqRx = seqnb;

        stat = OTA_SUCCESS;
      }
      else
      {
        stat = OTA_SER_BUSY;
      }
    }
……
……
……


可以看到,条件判断语句:

if ( (seqnb > SerialApp_SeqRx) ||                    // Normal
      ((seqnb < 0x80 ) && ( SerialApp_SeqRx > 0x80)) ) // Wrap-around


这里,就是问题的关键所在,其一,seqnb 没有针对不同的终端定义不同的Seqnb,所以当不同的终端发数据的时候,协调器会

接受 seqnb 符合条件判断的那个,并发送给串口。所以多个终端发送数据时,只有一个能被协调器接收数据并串口发送。其

二,seqnb对与多个终端时,只要终端发来的序列好满足条件。seqnb都会为之改变。那么seqnb永远都是最新最大的值。

举个例子,比如在点对点的情况下,终端给协调器发送数据,seqnb从0x20开始,一段时间后,这个时候seqnb 假设等于 0x36

,那么关闭终端,再打开终端,则终端发给协调器的序列号从0x20开始,在在0x20~0x36 直接的数据,协调器都不会串口显

示。



这里通过 SerialApp_SeqRx  来判断是否接受数据,它的定义如下:

static uint8 SerialApp_SeqRx;
static uint8 SerialApp_SeqTx;

初始化在SerailApp_Init() 中,如下:

void SerialApp_Init( uint8 task_id )
{
  halUARTCfg_t uartConfig;

  SerialApp_MsgID = 0x00;
  SerialApp_SeqRx = 0xC3;
  SerialApp_TaskID = task_id;
……………………………………


一开始: SerialApp_SeqRx = 0xC3;

修改的方法,有两种,第一,要么将SerialApp_seqrx 设计为结构体,其中,加上网络地址,然后在条件判断中,对网络地址同

样进行判断,这样,就可以分别避免多对一造成的seqrx的问题。同时,加上flag标志,用于判断终端是否是重新加入网络。

第二,最简单,就是直接把条件判断去掉,即不使用seqrx 的信息,只需要在Coordinator中屏蔽条件判断即可。因为zigbee协议


栈自己会有硬件实现数据包是否重复判断,所以,我们不用去操心!



kings316 发表于 2012-8-18 14:05:45 | 显示全部楼层
你的意思   协议栈的例子对sequence的判断是多余的?
lizheng86312 发表于 2012-8-29 11:54:53 | 显示全部楼层
学到东西了。顶。。。
 楼主| 神经火光 发表于 2012-9-2 09:56:03 | 显示全部楼层
kings316 发表于 2012-8-18 14:05
你的意思   协议栈的例子对sequence的判断是多余的?

我一开始认为是多余的,因为我通信过程中,观察结果没出现什么问题,不过最近发现有些问题,这个序列号需要,但是如果想要实现多对一通信,需要修改一下,增加一些标志,用来区分,不同的终端发来的数据,以及同一个终端重新入网后发来的数据
憨不乎的 发表于 2012-11-28 21:23:39 | 显示全部楼层
楼主有没有试过协调器往多个终端发送数据啊
Tina721 发表于 2012-12-6 17:10:28 | 显示全部楼层
神经火光 发表于 2012-9-2 09:56
我一开始认为是多余的,因为我通信过程中,观察结果没出现什么问题,不过最近发现有些问题,这个序列号需 ...

请问楼主有没有实现多对一得通信?我也在弄这方面的项目,能交流吗?qq418241413
一月的萧邦 发表于 2012-12-7 16:40:59 | 显示全部楼层
Z-stack 需要在应用层手动添加一个序列号,否则会出现重帧。
楼主,你说的方法一试了吗?
wateras1 发表于 2013-7-30 17:09:49 | 显示全部楼层
一月的萧邦 发表于 2012-12-7 16:40
Z-stack 需要在应用层手动添加一个序列号,否则会出现重帧。
楼主,你说的方法一试了吗?

请问下你尝试过了嘛?
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

快速回复 返回顶部 返回列表