问题描述
通过C#的serialport控件,读取串口数据。解析得到的数据位和数据都和串口助手数据对不上。如:023130202020202020302020202020300D——助手 02313F3F20202020203F3F202020203F3F300D——serialportvoidcomm_DataReceived(objectsender,SerialDataReceivedEventArgse){#regionoldSrcif(Closing)return;//如果正在关闭,忽略操作,直接返回,尽快的完成串口监听线程的一次循环try{Listening=true;//设置标记,说明我已经开始处理数据,一会儿要使用系统UI的。intn=comm.BytesToRead;//先记录下来,避免某种原因,人为的原因,操作几次之间时间长,缓存不一致byte[]buf=newbyte[n];//声明一个临时数组存储当前来的串口数据received_count+=n;//增加接收计数comm.Read(buf,0,n);//读取缓冲数据///////////////////////////////////////////////////////////////////////////////////////////////////////////////<协议解析>booldata_1_catched=false;//缓存记录数据是否捕获到//1.缓存数据buffer.AddRange(buf);//2.完整性判断while(buffer.Count>=18)//至少要包含头(2字节)+长度(1字节)+校验(1字节){//请不要担心使用>=,因为>=已经和>,<,=一样,是独立操作符,并不是解析成>和=2个符号//2.1查找数据头if(buffer[0]==0x02){//2.2探测缓存数据是否有一条数据的字节,如果不够,就不用费劲的做其他验证了//前面已经限定了剩余长度>=4,那我们这里一定能访问到buffer[2]这个长度intlen=buffer[2];//数据长度//数据完整判断第一步,长度是否足够//len是数据段长度,4个字节是while行注释的3部分长度if(buffer.Count<18)break;//数据不够的时候什么都不做//这里确保数据长度足够,数据头标志找到,我们开始计算校验//////2.3校验数据,确认数据正确//////异或校验,逐个字节异或得到校验码////bytechecksum=0;////for(inti=0;i<17;i++)//len+3表示校验之前的位置////{////checksum^=buffer[i];////}////if(checksum!=buffer[len+3])//如果数据校验失败,丢弃这一包数据////{////buffer.RemoveRange(0,len+4);//从缓存中删除错误数据////continue;//继续下一次循环////}//至此,已经被找到了一条完整数据。我们将数据直接分析,或是缓存起来一起分析//我们这里采用的办法是缓存一次,好处就是如果你某种原因,数据堆积在缓存buffer中//已经很多了,那你需要循环的找到最后一组,只分析最新数据,过往数据你已经处理不及时//了,就不要浪费更多时间了,这也是考虑到系统负载能够降低。buffer.CopyTo(0,binary_data_1,0,18);//复制一条完整数据到具体的数据缓存data_1_catched=true;buffer.RemoveRange(0,18);//正确分析一条数据,从缓存中移除数据。}else{//这里是很重要的,如果数据开始不是头,则删除数据buffer.RemoveAt(0);}}////try////{////buffer.CopyTo(0,binary_data_1,0,17);//复制一条完整数据到具体的数据缓存////data_1_catched=true;////buffer.RemoveRange(0,17);//正确分析一条数据,从缓存中移除数据。////}////catch(Exceptionex)////{////MessageBox.Show("错误:"+ex.ToString());////}//分析数据if(data_1_catched){//我们的数据都是定好格式的,所以当我们找到分析出的数据1,就知道固定位置一定是这些数据,我们只要显示就可以了stringdata=binary_data_1[4].ToString("X2")+""+binary_data_1[5].ToString("X2")+""+binary_data_1[6].ToString("X2")+""+binary_data_1[7].ToString("X2")+""+binary_data_1[8].ToString("X2")+""+binary_data_1[9].ToString("X2");//更新界面//stringdata="";//for(inti=0;i<binary_data_1.Length;i++)//{//data+=binary_data_1[i].ToString();//}this.Invoke((EventHandler)(delegate{txData.Text=data;}));}//如果需要别的协议,只要扩展这个data_n_catched就可以了。往往我们协议多的情况下,还会包含数据编号,给来的数据进行//编号,协议优化后就是:头+编号+长度+数据+校验//</协议解析>/////////////////////////////////////////////////////////////////////////////////////////////////////////////builder.Clear();//清除字符串构造器的内容//因为要访问ui资源,所以需要使用invoke方式同步ui。this.Invoke((EventHandler)(delegate{//判断是否是显示为16进制if(checkBoxHexView.Checked){//依次的拼接出16进制字符串foreach(bytebinbuf){builder.Append(b.ToString("X2")+"");}}else{//直接按ASCII规则转换成字符串builder.Append(Encoding.ASCII.GetString(buf));}//追加的形式添加到文本框末端,并滚动到最后。this.txGet.AppendText(builder.ToString());//修改接收计数labelGetCount.Text="Get:"+received_count.ToString();}));}finally{Listening=false;//我用完了,ui可以关闭串口了。}#endregion}
解决方案
解决方案二:
大家没有你的环境,不可能给你测试,自力更生吧
解决方案三:
那你知道哪个数据是准确的么?
解决方案四:
你首先要有个模拟的串口服务器上面能显示当前串口的真实值这样你才能知道到底是助手正确还是你的数据正确。。还有,也许都正确,,因为在不同的时间发送的请求。。不同的时间返回不同的值也是正常。。。。