首页 新闻 会员 周边 捐助

关于串口接收并解析数据

0
悬赏园豆:100 [已解决问题] 解决于 2014-11-19 18:12

接收就是在SerialPort类的rececivedata里面接收

 
 
 
                         
int a=comm.ByteToRead;
                             byte []buf=new byte[a];
                              comm.Read(buf,0,a);

    


现在的情况是,接收到数据是不固定的长度,协议是起始是AA AA    结束是DE D0
接收到的数据有可能是AA AA 08 56 82 44 DE DO
也可能是AA AA 08 56 82 44 AA AA 55 63 1A 55 AA AA 55 99 33 77  DE D0要做的是将接到的数据处理解析。
1、串口接收的数据不是一次性接完的。比如第一次buf收到了AA AA 08 56 第二次buf才收到82 44 DE DO
怎么把他们装到一个新数组里面。
我用的ArragList  LIST=new ArragList();为什么不行啊,因为我判断的是if(LIST[2]==0x69)调试提示object 和int不能。
2、解析时我想处理的AA AA 08 56 82 44    和AA AA 55 63 1A 55和 AA AA 66 99 33 77  DE D0分开处理。这个怎么做啊。
例如 if(buf[2]==0x08) {执行相应的事情}
if(buf[2]==0x55) {执行相应的事情}
求大神给个指导

yalunwang的主页 yalunwang | 初学一级 | 园豆:22
提问于:2014-11-12 15:35
< >
分享
最佳答案
1

这个必须要将数据进行缓存,因为一次来的数据可能并不是你所期望的一帧数据,可能多,也可能少,同时可能由于某种原因,一帧数据没有完,后一帧的数据又来了,会导致数据错乱,所以也要确定一帧数据到达的时间,超过了时间就丢弃。

 var msg = Encoding.Default.GetString(this.buf.ToArray());                         //2.完整性判断       

   while (msg.Length > BeginOfLine.Length + EndOfLine.Length)//至少要包含头(2字节)+长度(1字节)+校验(1字节)            

{

                if (msg.IndexOf(BeginOfLine) == 0)      

           {                    

                    if (msg.IndexOf(EndOfLine) > 0)  

                   {  

                       this.Raw = new byte[msg.IndexOf(EndOfLine) - BeginOfLine.Length + 1];

                   this.buf.CopyTo(BeginOfLine.Length, this.Raw, 0, msg.IndexOf(EndOfLine) - BeginOfLine.Length);   

                      this.buf.RemoveRange(0, msg.IndexOf(EndOfLine) + EndOfLine.Length);                         if (this.buf.Count > 0)

                        {

                            msg = Encoding.Default.GetString(this.buf.ToArray());

                        }

                        else msg = "";

                        this.OnGetNew(this.Raw);

                    }

                    else

                    {

                        break;

                    }  

               }

                else

                {

                    //这里是很重要的,如果数据开始不是头,则删除数据

                    int index = msg.IndexOf(BeginOfLine);

                    if (index > 0)

                    {

                        this.buf.RemoveRange(0, index);

                        msg = msg.Substring(index,msg.Length- index);

                                    }

                    else

                    {

                        if(this.buf.Count>0)this.buf.RemoveAt(0);

                        msg = "";

                    }

                }

收获园豆:50
东王 | 菜鸟二级 |园豆:252 | 2014-11-18 20:55

大家说的都不错,谢谢了。我就是用的list.removerange().自己也做成了。thank you,跟你说的差不多

yalunwang | 园豆:22 (初学一级) | 2014-11-19 18:06

我想问下,这怎么结贴啊,第一次发帖,以前都是在csdn上发的

yalunwang | 园豆:22 (初学一级) | 2014-11-19 18:09
其他回答(7)
0

if(int.Pares(buf[2].ToString())==0x08)

刘宏玺 | 园豆:14020 (专家六级) | 2014-11-12 15:52

第1个问题怎么解决啊,因为下位机向上位机发数据时,一帧完整的数据有可能是分几次往上位机发的啊。说白了就是怎么把接收缓冲区收到的数据完整存在一个byte暂存里面

支持(0) 反对(0) yalunwang | 园豆:22 (初学一级) | 2014-11-12 15:56

是一个byte[]

支持(0) 反对(0) yalunwang | 园豆:22 (初学一级) | 2014-11-12 15:57

@yalunwang: http://bbs.csdn.net/topics/350027199

这个问题?

支持(0) 反对(0) 刘宏玺 | 园豆:14020 (专家六级) | 2014-11-12 15:58
0
dudu | 园豆:29333 (高人七级) | 2014-11-12 16:32
0

可以了解下http://www.kacled.com/led/ludeng/147.html

hkuyu | 园豆:154 (初学一级) | 2014-11-12 17:02

广告?

支持(0) 反对(0) yalunwang | 园豆:22 (初学一级) | 2014-11-12 18:53
0

语言问题不应该程序处理逻辑在一起讨论.

女孩不哭 | 园豆:469 (菜鸟二级) | 2014-11-12 21:14
0

可以用list呀,将收到的数据放到里面,并且用另外一个线程来判断包头和包尾。不过,你的数据包,没有校验?没有指定数据长度吗?

收获园豆:10
ChuckLu | 园豆:514 (小虾三级) | 2014-11-13 08:41
0
 1 可以参考下
 2 private List<byte> _lstData = new List<byte> ();
 3 public void _serialPort_DataReceived (DataReceivedEventArgs e) {
4 //禁止接收事件时直接退出 5 if (!_serialPort.ReceiveEventFlag) { 6 var data = e.data; 7 _lstData.AddRange (data); 8 if (_lstData.Count >= 5) { 9 //MyMethod(_lstData); 10 }
11 }

12
}
收获园豆:10
huzl | 园豆:281 (菜鸟二级) | 2014-11-18 09:13
上面发的是处理后的数据,这里是直接接收数据处理
#region 接收数据
Thread.Sleep(300);
List<byte> _byteData = new List<byte>();
while (comPort.BytesToRead > 0)
{
        byte[] readBuffer = new byte[comPort.ReadBufferSize + 1];
        int count = comPort.Read(readBuffer, 0, comPort.ReadBufferSize);
        for (int i = 0; i < count; i++)
        {
            _byteData.Add(readBuffer[i]);
        }
}
//MyMethod(_byteData);//处理整条数据
#endregion
支持(0) 反对(0) huzl | 园豆:281 (菜鸟二级) | 2014-11-18 09:20
1

对于非队列的数据通讯,一般返回数据是比较容易混乱。这时候需要综合考虑问题。

1.返回数据的起始位(符)和结束位(符)

2.一般通讯协议应该有校验位,比对校验位是否正确

 1 BOOL CheckCheckSum(const BYTE *szString,BYTE iStrLen)
 2 {
 3     BYTE uCheck;
 4     if (iStrLen > 1)
 5     {
 6         uCheck = GetCheckSum(szString,iStrLen -1)&0xFF;
 7         return(uCheck == szString[iStrLen-1]);
 8     }
 9     return FALSE;
10 }
11 
12 BYTE GetCheckSum(const BYTE *szString,BYTE iStrLen)
13 {
14     BYTE i;
15     BYTE uCheck = 0;
16 
17     for ( i=0; i<iStrLen; i++ )
18     {
19         uCheck+=szString[i];
20     }
21 
22     return uCheck;
23 }

以上仅供参考。
3.返回数据长度是否固定,如你上面所述:当buf[2] == 0x08时,首先判断起始符和结束符,检验位,然后是数据长度,如果符合则执行操作,以下类似之。提醒你一下当十六进制为第三页,即大于0x80的时候,可能会存在大小端的问题,需要你注意一下。

收获园豆:20
万载一梦 | 园豆:222 (菜鸟二级) | 2014-11-18 16:00
清除回答草稿
   您需要登录以后才能回答,未注册用户请先注册