我最近在做一个RS232的程序,遇到一个问题,就是我接收的数据有时候是对的,有时候是错的,比如我每次发送三个字节,但是接收的时候有的是只受到一个字节。
这是部分代码 string ComportName = "COM1";
                comPort = new SerialPort(ComportName, 14400, Parity.None, 8, StopBits.One);
                comPort.ReadTimeout = 100;
                comPort.WriteTimeout = 100;
                comPort.DataReceived += ByteReceived;
                //comPort.ReceivedBytesThreshold = 1;
               // comPort.WriteBufferSize = 3;
                comPort.Open();
这是接收事件: int byteToRead = comPort.BytesToRead;
            byte[] resultByte = new byte[byteToRead];
            comPort.Read(resultByte, 0, byteToRead);

解决方案 »

  1.   

    我又Bitsbaund调到最高,倒是可以了。
      

  2.   

    好像用byte[] resultByte,会出现一些问题,我是刚学所以也不知道问题出现在哪;用string temp,的话就没有出现这个问题
      

  3.   

    你两端的COM设置是否相同?
    接收的字节数为什么要与发送的字节数相同?这很奇怪。接收的字节数应该是看设备的设置返回给你什么信息,跟你发送的字节数又不一样。
      

  4.   

    缺少的是在后面,发送端没问题,因为用lookRS232这个软件查看的接收到的数据是没有问题的。
      

  5.   

    先讲一个概念问题,串口通信的特点是不可靠的,是面向缓冲区的操作,这个一定要明白
    a->b , a 发送了n个字节, b 串口接收、添加到缓冲区。comPort.DataReceived += ByteReceived;
    这个接收事件激活的条件,并不是全部接收后激活,这就是你的问题表现。
    有时接收几个就激活,有时接收1个就激活,这时候缓冲区里有几个,你就能读出几个。 这并不是bug或者问题,这就是因为数据没有接收完成。 这就是串口通信的特点你可以在接收事件的方法第一行假如thread.sleep(500-1000 适当值), 适当延时来增加串口缓冲的填充率,来保证每次接收数据完整。 但是这个方法只能面向内容十分短小的通信。 大数据量的要按字节读取。 根据通信包做首尾判断。
      

  6.   

    其实我在int byteToRead = comPort.BytesToRead;
    这个地方加入断点的话,看到的comport的bytesToRead确实是正确的,但是在赋值给int byteToRead就变少了,真是太郁闷了。
      

  7.   

    接收到的是没错的,就是在获取接收到的字节数组长度时候出错,就是在int byteToRead = comPort.BytesToRead这一句话中,加入断点到这里,单步执行是正确的,但是直接运行前面的int就变少了。
      

  8.   

    线程睡眠一下是可以,只要睡眠的milSecond大于要收到的字节数就行。但是还有没有更好的方法呢。
      

  9.   

    加一个死循环,private void SerialPort1_DataReceived(object sender, System.IO.Ports.SerialDataReceivedEventArgs e)//Getting data from Comm Port
            {
                
                try
                {
          
                    int n = SerialPort1.BytesToRead;
                    byte[] buf = new byte[n];
                    SerialPort1.Read(buf, 0, n);//读取缓冲数据     
                    bool data_1_catched = false;//缓存记录数据是否捕获到    
                    buffer.AddRange(buf);
                    while (buffer.Count >= 12)
                    {
                        byte CRCH, CRCL;
                        byte[] crcTemp = new byte[10];
                        buffer.CopyTo(0, crcTemp, 0, 10);                    CRCData.CalculateCrc16(crcTemp, out CRCH, out CRCL);
                        if (buffer[10] != CRCH && buffer[11] != CRCL)
                        {
                            buffer.RemoveAt(0);
                            continue;//继续下一次循环   
                        }
                        buffer.CopyTo(0, binary_data_1, 0, 12);//复制一条完整数据到具体的数据缓存   
                        data_1_catched = true;
                        buffer.RemoveRange(0, 12);//正确分析一条数据,从缓存中移除数据。     
                    }自己看吧
      

  10.   

    复制的Code不是死循的,COde是有数据就接,接了放在一个List里,从List里取数据处理
      

  11.   

    代码不完整吧,buffer在哪里定义的呀,代表什么?
      

  12.   


            private List<byte> buffer = new List<byte>(256);//默认分配1/16页内存,并始终限制不允许超过   
            private byte[] binary_data_1 = new byte[12];//
      

  13.   

    偶觉得应该用String接收数据,然后再转成你需要的,灌水
      

  14.   

    C# 串口操作系列(1) -- 入门篇,一个标准的,简陋的串口例子。 
    C# 串口操作系列(2) -- 入门篇,为什么我的串口程序在关闭串口时候会死锁 ? 
    C# 串口操作系列(3) -- 协议篇,二进制协议数据解析 
      

  15.   

    我两端确实设置的是一致的,把波特率设置到最高也只是我调试过程中的一个方法而已,我也知道那样是不能从本质上解决问题的。现在我的问题还是怎么能获取所有要读取的字节数。虽然Thread.sleep()方法可以,但是效率太低了,而且你不知道需要sleep多久。不知道您明白了我的问题没有。
      

  16.   

    请问代码里的CRCDATA是什么呀?
      

  17.   

    没有,我就直接读取需要读的字节数,然后直接comPort.Read(resultByte, 0, intByteToRead);
      

  18.   

    通信需要一定的延时的,不可能是不停的发不停的收,不然到时候会爆掉的,我觉得500ms或者1000ms都是可以的。
      

  19.   

    我发现如果是发过来100个字节的话,Sleep(100)就可以了,但是如果发送过来的字节数大于100,这样还是会丢失一些字节的。假如我Sleep(1000)那就是1S钟呀,影响效率,而且也不能从根本上解决问题呀,如果发送来的数据是成千上万,那不还是丢失吗?
      

  20.   

    不要直接用sleep(1000)这样会让人感觉程序假死在那里,什么都动不了。
            //系统延时
            public void Delay(int ys)
            {
                for (int i = 1; i <= ys; i++)
                {
                    //使用sleep(1)会比sleep(1000)好,因为让进程循环1000休息1ms=1s比直接让系统休眠1s好
                    //如果直接让进程休眠1s,让人感觉进程好像卡了,反应很慢。
                    System.Threading.Thread.Sleep(1);
                    Application.DoEvents();
                }
            }
      

  21.   

                    while (buffer.Count >= 12)
                    {
                        byte CRCH, CRCL;    //这个是我CRC校验用的,
                        byte[] crcTemp = new byte[10];
                        buffer.CopyTo(0, crcTemp, 0, 10);                    CRCData.CalculateCrc16(crcTemp, out CRCH, out CRCL);//一直到这 这个是我CRC校验用的,                    if (buffer[10] != CRCH && buffer[11] != CRCL)//如果CRC校验不对,做下面的处理
                        {
                            buffer.RemoveAt(0);//删除BUFF中的第一个数据。
                            continue;//继续下一次循环   
                        }
    清楚没?