当前位置: 代码迷 >> C# >> 问一个关于数据接收的有关问题
  详细解决方案

问一个关于数据接收的有关问题

热度:27   发布时间:2016-05-05 04:09:37.0
问一个关于数据接收的问题。
我采用的是SerialPort类的DateReceived方法接收数据,思路是:先将数值转化为字节发送到串口接收端,之后根据接收端的字节转为数据。具体代码如下:
初始化:
int x1=0; int x2=0;...........................int x100=0;
定义数据字节转换类:
public class SetParameter
    {
              这里主要定义字节和数据的转换,例如 :  A的攻击力:100
              发送时将100转化成十六进制,根据要求 结果是 88 01 00 64 65
              然后接收数据时根据上面的字节存入ListBox1中显示正确的数据 
    }

发送所有数据按钮:(可能这里的Thread.sleep()有问题)
 progressBar1.Value = 0;
                for (listBox1.SelectedIndex = 0; listBox1.SelectedIndex <= 100; listBox1.SelectedIndex++)
                {
                        SetParameter sp = new SetParameter();//设置参数
                        double p0 = 0;//将具体的参数赋值给p0
                        int n = listBox1.SelectedIndex;//ListBox1的选中行位置,后面主要把位置转化为序号
                        string p1 = sp.SetP1();//定义字节1
                        string p2 = sp.SetP2(n);//定义字节2(序号)

                        #region 代入ListBox1的参数值
                        switch (n)
                        {
                            case 1:
                                {
                                    p0 = x1;
                                    break;
                                }
           ..........................................................
                            case 100:
                                {
                                    p0 = x100;
                                    break;
                                }

                        }
                        #endregion

                        double x = sp.Parameters(p0, p2);
                        string p3 = sp.SetP3(x);//定义字节3
                        string p4 = sp.SetP4(x);//定义字节4
                        string p5 = sp.SetP5(n, x);//定义字节5
                    
                        /*发送数据开始*/
                        serialPort1.Write(p1);
                        progressBar1.Value += progressBar1.Step;
                        Thread.Sleep(20);

                        serialPort1.Write(p2);
                        progressBar1.Value += progressBar1.Step;
                        Thread.Sleep(20);

                        serialPort1.Write(p3);
                        progressBar1.Value += progressBar1.Step;
                        Thread.Sleep(20);

                        serialPort1.Write(p4);
                        progressBar1.Value += progressBar1.Step;
                        Thread.Sleep(20);

                        serialPort1.Write(p5);
                        progressBar1.Value += progressBar1.Step;
                        Thread.Sleep(50);
             }

接收数据 :
为了方便查看,我创建了一个文本框 名称为 richReceiveText1
private void serialPort1_DataReceived(object sender, SerialDataReceivedEventArgs e)
        {
            if (Closing) return;//如果正在关闭,忽略操作,直接返回,尽快的完成串口监听线程的一次循环  
            try
            {
                int len = serialPort1.BytesToRead;//定义字节数组的长度:每接收一次数据读取的字符串长度
                Byte[] bytes = new Byte[len];//建立字节数组对象
                serialPort1.Read(bytes, 0, len);//读取接收的字节
                builder.Clear();//接收数据时清除之前的残余字符串

                //定义异步线程判断字符串的内容
                this.Invoke((EventHandler)delegate
                {
                    builder.Append(Encoding.ASCII.GetString(bytes));
                    richReceiveText1.AppendText(builder.ToString().Replace(" ", ""));
                    int d1 = Convert.ToInt32(richReceiveText1.Text.Substring(0, 2), 16);
                    if (d1 == 136 && richReceiveText1.Text.Length == 10)
                    {
                        int d2 = Convert.ToInt32(richReceiveText1.Text.Substring(2, 2), 10);
                        int d3 = Convert.ToInt32(richReceiveText1.Text.Substring(4, 2), 16);
                        int d4 = Convert.ToInt32(richReceiveText1.Text.Substring(6, 2), 16);
                        int d5 = Convert.ToInt32(richReceiveText1.Text.Substring(8, 2), 16);
                        if (1 <= d2 && d2 <= 96)
                        {
                            #region 字节转为数据
                            switch (d2)
                            {
                                case 1:
                                    {
                                        x1 = (d4 * 256 + d3) / 32; listBox1.Items[1] = " A的攻击力:" + x1;
                                        richReceiveText1.Clear(); listBox1.SelectedIndex = 1;
                                        break;
                                   }
                         ......................................
                                case 96:
                                    {
                                        aux_cont_vol = (d4 * 256 + d3) / 64; listBox1.SelectedIndex = 110;
                                        listBox1.Items[110] = "Z的魔法攻击必杀率:" + x110 + "%"; richReceiveText1.Clear();
                                        break;
                                    }
                            }
                            #endregion
                        }

                    }
                });
            }finally
            {
                Listening = false;
            }
        }

但问题出现了:
问题1:
当listBox1的高度设置的很大,看不到垂直滚动栏时,数据都可以完美接收
但是listBox1的高度不太高时,每次移动到当前屏幕最低端的时候(比如listbox1.selectedindex=35)数据就接收失败
失败的现象就是listBox1显示到那行时,richReceiveText1的内容不会想往常那样清空,从而ListBox1收不到数据。
但我把Thread.sleep的参数定义到100以上时,此问题的出现率会减少很多,但我们要求是20ms间隔。
问题2:
我把DataReceive方法绑定到一个按钮里了,当这个按钮没开,发送端发送数据时,正常没数据。但再次发送数据时,之前全部发送的数据的十六进制都会在richReceiveText1里出现。

希望大神们帮忙看哪里有问题呢?求助~~谢谢。如果有需要贴出其他代码可以贴
------解决思路----------------------
网络通信就是这样子的,收发不是一一对应的,
可能一次收到多个包,也可能多次才收全一个包。

不是定长的包,就得加包头,说明包长度。最好再加包尾验证。
  相关解决方案