C#界面程序设计——05串口接收不连续数据处理

3 篇文章 0 订阅
1 篇文章 0 订阅

C#界面程序设计——05串口接收不连续数据处理


在处理数据交互时,无论单任务还是多任务,交互流程可概述为以下两种情况:
情况A:
情况A
情况B:
情况B
注:情况B是指电路板收到A并校验正确后才可接收B。
但是在数据交互过程中,无论是通过RS422/485还是通过RS232通信,经常会遇到断包的状态。
一般来说,每包的数据都是单独校验,使用CRC校验或是简单的和校验。当遇到断包时,会出现
数据包A被分开几次接收,而且可能会出现数据包A的结尾会和B一起被接收,这些情况我们在考虑到可用性和安全性的情况下,不能当做无效数据包处理。
本文针对这种情况,基于C#的串口接收触发函数给出一种解决方案。
在提出解决方案前,需要计算机与电路板的通信协议中包含如下元素作为前提:
1.每个数据包有标志位,可以通过某位或某字节的值的值该数据包的长度、类型等信息。
2.如果数据包长度不固定,则必须有足够长度的头尾标识。
3.上述数据包交互过程中不会在交互过程中被插入其他数据。如在一对多交互过程中数据包被掺杂。
首先,建立长度判断函数,本文案例是以数据包的第二个字节作为标识,即Data[1]。

/*
         * 函数:Zhen_type_Length
         * 参数:zhentype  帧类型 如0XA2
         * 功能:根据帧类型计算出各帧的数据长度
         * 返回值:各帧的数据长度
         * */
        public int Zhen_type_Length(byte zhentype)
        {
            int Zhen_type_L = 0;
            switch (zhentype)
            {
                case 0XA0:
                    Zhen_type_L = 138;
                    break;
                case 0X90:
                    Zhen_type_L = 20;
                    break;
                case 0X91:
                    Zhen_type_L = 25;
                    break;
                case 0XA4:
                    Zhen_type_L = 244;
                    break;
                case 0XA3:
                    Zhen_type_L = 30;
                    break;
                case 0XA1:
                    Zhen_type_L = 22;
                    break;
                case 0XA2:
                    Zhen_type_L = 22;
                    break;
                case 0X80:
                    Zhen_type_L = 546;
                    break;
                default:
                    Zhen_type_L = 0;
                    break;
            }

            return Zhen_type_L;
        }

然后设计接收部分,主要设计思路为根据接收到的第一条信息开始建立数据缓冲区,每次接收触发时判断长度是否足够,如此几次之后数据长度大于等于预期长度之后再处理,处理之后将缓冲区中有效数据与有效数据之前的数据清空,如果有效数据之后仍有数据则前移至缓冲区开头,前移之后需要再次判断剩余数据是否为有效数据。

/*
         * 函数:FaSPcom_DataReceived
         * 功能:串口接收信息处理,兼有接收触发、发送下一条帧数据、存入循环缓冲区并校验的功能
         * 循环缓冲区预分配
         * */
        int ZhenLength_Record = 0;//纪录当前缓冲区帧数据有效数据长度
        byte[] ZhenDataHuanChong = new byte[1000];//缓冲区
        private void FFSPcom_DataReceived(object sender, SerialDataReceivedEventArgs e)
        {
            byte[] Data_FaSPcom = new byte[FaSPcom.BytesToRead];            
            FaSPcom.Read(Data_FaSPcom, 0, Data_FaSPcom.Length);//接收数据,存入Data_FaSPcom   
            if (Data_FaSPcom.Length == 0 ) { return; }//防止空包
           // if (Data_FaSPcom[0] == 0 && Data_FaSPcom.Length == 1) { return; }//防止零包
            Array.Copy(Data_FaSPcom, 0, ZhenDataHuanChong, ZhenLength_Record, Data_FaSPcom.Length);
            ZhenLength_Record = ZhenLength_Record + Data_FaSPcom.Length;
            int ZhenLength = Zhen_type_Length(ZhenDataHuanChong[1]);//根据标识字节判断该包数据长度,注意判断依据是缓冲区数据,而不一定是刚刚接收到的数据包
            if (ZhenLength_Record < ZhenLength) { return; }//如果数据长度不足,返回,等待下一次接收数据
            bool Deal_Double = false;
            if (1<ZhenLength_Record - ZhenLength)//判断后面是否还跟了一包完整数据
            {
                if (Zhen_type_Length(ZhenDataHuanChong[ZhenLength + 1]) + ZhenLength < ZhenLength_Record)
                {
                    Deal_Double = true;
                }
            }
            byte[] Data = new byte[ZhenLength];
            Array.Copy(ZhenDataHuanChong, 0, Data, 0, ZhenLength);//将第一包有效数据提取
            //此处写校验与处理部分,处理参数为Data

            //无论校验通过与否,删除已处理部分,由于长度记录的变量、缓冲区均为全局,此处使用函数处理
            Clear_Data_HuanChong(ZhenLength);
            ZhenLength_Record = ZhenLength_Record - ZhenLength;
            if (true == Deal_Double)
            {
                ZhenLength = Zhen_type_Length(ZhenDataHuanChong[ZhenLength + 1]);
                //此处再提取缓冲区中的后一包数据,并校验、处理
            }
            Clear_Data_HuanChong(ZhenLength);
            ZhenLength_Record = ZhenLength_Record - ZhenLength;
        }
        public void Clear_Data_HuanChong(int ClearLength)//将缓冲区的前ClearLength个数据覆盖
        {
            byte[] BeiFen = new byte[ClearLength];
            for (int i = 0; i < ZhenDataHuanChong.Length - ClearLength; i++)
            {
                ZhenDataHuanChong[i] = ZhenDataHuanChong[ClearLength+i];
            }
        }
  • 0
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值