如何处理串口通讯数据重合与分批到达的问题

重合:
指示设备工作时,设备返回ok;而此时设备主动上报数据,这两个数据可能发生重合;因此串口同时可能有多个消息到达


分批到达:
一个回复由于干扰信号的关系,分两次到达,第一次到达了11个字节的前5个字节,第二次到达了11个字节的后6个字节。
在接收事件中(On_Comm)需要对数据进行整理,将这两种问题解决后(借助于数据包头,数据包尾),还有校验码的问题

下面是我的解决方案,由于是第一编写这样的程序,没什么经验,所以希望大家能提出意见.

private static Logger logger = LogManager.GetCurrentClassLogger();      //

MSCommLib.MSCommClass mc = new MSCommLib.MSCommClass();     //实例化MSCOMM

System.Timers.Timer timer = null;    //定时器

ArrayList m_bytelist = new ArrayList();   //全局变量来存放接收到的数据

byte[] m_data = new byte[11];    //一个完整的消息指令数组长度为11

private int m_second = 0;     //超时时间

private void InitCommonPort()
  {
   
   try
   {
    mc.CommPort = 3;

    mc.Settings = "38400,n,8,1";
   
    mc.RThreshold = 1;   //每接收一个字符则激发OnComm()事件

    mc.DTREnable = true;

    mc.Handshaking = MSCommLib.HandshakeConstants.comNone;    

    mc.InputMode = MSCommLib.InputModeConstants.comInputModeBinary;   //二进制

    mc.InBufferSize = 1024;

    mc.InputLen = 0;      //决定每次Input读入的字符个数,缺省为0,表示读取接收缓冲区的全部内容
    //mc.InputLen = 1;    //一次读取一个
 
    mc.NullDiscard = false;

    mc.PortOpen = true;  //打开串口

    mc.OnComm +=new MSCommLib.DMSCommEvents_OnCommEventHandler(mc_OnComm);
   
    Console.WriteLine("串口已打开!");

    logger.Debug("串口已打开!");
   }
   catch
   {
    logger.Debug("串口打开失败!");
   }
  }

  /// <summary>
  /// 初始化定时器
  /// </summary>
  private void InitTimer()
  {
   timer = new System.Timers.Timer(1000);
   timer.AutoReset = true;
   timer.Enabled = true;
   timer.Elapsed +=new ElapsedEventHandler(timer_Elapsed);
  }

  /// <summary>
  /// 处理接收的数据
  /// </summary>
  private void checkByteList()
  {
   byte[] t_byte = new byte[11];

   int j = 0;

   if(m_bytelist.Count == 0)
   {
    return;
   }
   else
   {
    for(int i=0;i<m_bytelist.Count;i++)
    {
     t_byte[j] = (byte)m_bytelist[i];

     if(t_byte[0] == 0x82)
     {
      if(j==10)
      {
       if(t_byte[10] == 0x83)
       {
        sendMail(t_byte);

        j = 0;

        this.clearArray(ref t_byte);

        m_bytelist.RemoveRange(0,11);
       }
       else //如果包尾不是以83开头,数据不合法,丢弃
       {
        j=0;

        logger.Debug("/n错误的指令 : [" + Utilities.ByteArrayToHexString(t_byte) + "] 已被丢弃! ");

        this.clearArray(ref t_byte);

        m_bytelist.RemoveRange(0,11);
       }
      }
      else  
      {
       j++;

       this.InitTimer(); //初始化定时器

       if(m_second == 5) //5秒后停止
       {
        logger.Debug("不完整的指令 : ["+Utilities.ByteArrayToHexString(t_byte) + "]");
       
        this.clearArray(ref t_byte);

        m_bytelist.RemoveRange(0,j);

        j=0;
       }
      }
     }
     else   //如果包头不是以82开头,数据不合法,丢弃
     {
      j=0;

      logger.Debug("/n错误的指令 : [" + Utilities.ByteArrayToHexString(t_byte) + "] 已被丢弃! ");

      this.clearArray(ref t_byte);

      m_bytelist.RemoveRange(0,1);
     }
    }
   }
  } 

 /// <summary>
  /// clear array
  /// </summary>
  /// <param name="o_data"></param>
  private void clearArray(ref byte[]o_data)
  {
   for(int i=0;i<o_data.Length;i++)
   {
    o_data[i] =0;
   }
  }

  /// <summary>
  /// 将消息发给上层
  /// </summary>
  /// <param name="inData"></param>
  private void sendMail(byte[] inData)
  {

  }
   

  /// <summary>
  /// 从串口接收数据

  /// </summary>
  private void mc_OnComm()
  {
   byte [] t_byte = (byte[])mc.Input;  //receive data and clear buffer

   for(int i = 0;i<t_byte.Length;i++)
   {
    m_bytelist.Add(t_byte[i]);
   }
  }

  private void timer_Elapsed(object sender, ElapsedEventArgs e)
  {
   DateTime now = DateTime.Now;
   m_second = now.Second;
  }

 /// <summary>
  /// 接收MCU主动发送的消息、解析、封装成对象消息发送给Session层
  /// </summary>
  protected override void process()
  {
   checkByteList();
  }

 

主要的代码就这么多了,没有整理比较乱,有空的时候再整理一下了.

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值