在用串口收发数据时我想1043个字节触发一次中断;发送数据时设置: serialPort1.ReceivedBytesThreshold = 1043;
以下为串口中断代码:        private void serialPort1_DataReceived(object sender, System.IO.Ports.SerialDataReceivedEventArgs e)
        {
            Thread.Sleep(2000);
            //Console.Write("/n" + "串口中断时实际字节:" + SerialPortIO.ReceivedBytesThreshold.ToString());
            byte[] RS_SerialData = new byte[serialPort1.BytesToRead];
            serialPort1.Read(RS_SerialData, 0, serialPort1.BytesToRead);
            if (RS_SerialData.Length == 1043)
            {//这里做处理
            }可是实际情况与预期不符;在不延时2秒的情况下,串口缓存只收到400字节左右就出发了。我加了延时后只有40%几率能正好1043字节触发。另一个通讯要接收70多个字节一中断也有这种情况,不延时的情况下有10%的几率收不全。以前用vb6.0一直正常。
还请高手指点!

解决方案 »

  1.   

    .NET 的serialPort1 与VB6.0的MSCom 用法是不一样的!串口每次传过来的数据都是1043 吗?
      

  2.   

    恩,每次传输都是1043个字节。非常固定。
    变通的方法:我可以每次读一个字节,然后判断本次数据是否传输完成。
    只是,想知道为什么会这样,有没有解决的办法。ReadBufferSize 属性忽略任何小于 4096 的值。//默认为4096,接收缓冲区够用
      

  3.   


    试试这样子的读取方法呢!
    /****************************************************************** 
    * Copyright(c)  : Tangxu 
    * Description  : 
    * CreateDate    : 2006-9-01 04:53:08 
    * Creater      : Tang.xu 
    * LastChangeDate: 
    * LastChanger  : 
    * Version Info  : 1.0.0 
    * ******************************************************************/ 
    using System; 
    using System.IO.Ports; 
    using System.Threading; 
    using System.Text; namespace Tangxu.Common 

        public class ReadCom 
        { 
            public ReadCom() 
            { 
                _ReadConfig = new ReadConfigure(System.Environment.CurrentDirectory + "\\Com_Info.xml"); 
            }         public ReadCom(string sCom,int nBaud):this() 
            { 
            
            }         private byte[] _ReadBuffer; 
            private SerialPort ss_port = new SerialPort(); 
            private static int nReadCount = 0; 
            private ReadConfigure _ReadConfig;         #region Initialize com port         public bool InitCom()//初始化建串口类实例 
            { 
              // return true; 
                try 
                { 
                    ss_port.PortName = _ReadConfig.GetNodeValue("PORT");// _sComPort; 
                    ss_port.BaudRate = int.Parse(_ReadConfig.GetNodeValue("BAUD"));//_nBaud; 
                    ss_port.ReadBufferSize = 10240; 
                    ss_port.DataBits = int.Parse(_ReadConfig.GetNodeValue("DATA"));//8; 
                    switch (_ReadConfig.GetNodeValue("PARITY")) 
                    { 
                        case "None": 
                            ss_port.Parity = Parity.None; 
                            break; 
                        case "Even": 
                            ss_port.Parity = Parity.Even; 
                            break; 
                        case "Mark": 
                            ss_port.Parity = Parity.Mark; 
                            break; 
                        case "Odd": 
                            ss_port.Parity = Parity.Odd; 
                            break; 
                        case "Space": 
                            ss_port.Parity = Parity.Mark; 
                            break; 
                    } 
                    switch (_ReadConfig.GetNodeValue("STOP")) 
                    { 
                        case "1": 
                            ss_port.StopBits = StopBits.One; 
                            break; 
                        case "1.5": 
                            ss_port.StopBits = StopBits.OnePointFive; 
                            break; 
                        case "2": 
                            ss_port.StopBits = StopBits.Two; 
                            break; 
                    } 
                    ss_port.ReadTimeout = 600; 
                    ss_port.WriteTimeout = 700;                 ss_port.Open();//打开串口 
                    return true; 
                } 
                catch (Exception ex) 
                { 
                    throw new Exception("打开串口失败!\r\n错误信息:" + ex.Message); 
                } 
            } 
            #endregion         #region FreeDrv 
            /// <summary> 
            /// free opw 
            /// </summary> 
            public void FreeDrv() 
            { 
                try 
                { 
                    if (ss_port != null) 
                    {                  
                        ss_port.Close();  
                    } 
                } 
                catch 
                { } 
            } 
            #endregion         #region Write command to OPW 
            /// <summary> 
            /// 发操作命令给OPW设备 
            /// 并返回状态 
            /// </summary> 
            /// <param name="sCommand"> </param> 
            /// <returns> </returns> 
            public string WriteCommand(string sCommand) 
            { 
                StringBuilder sb = new StringBuilder(); 
                bool bRead = true; 
                try 
                { 
                    ss_port.DiscardInBuffer(); 
                    ss_port.Write(sCommand); 
                    Thread.Sleep(1500); 
                    while (bRead) 
                    { 
                        _ReadBuffer = new byte[ss_port.BytesToRead]; 
                        ss_port.Read(_ReadBuffer, 0, _ReadBuffer.Length); 
                        sb.Append(Encoding.ASCII.GetString(_ReadBuffer)); 
                        Thread.Sleep(500); 
                        if (ss_port.BytesToRead <= 0) 
                        { 
                            bRead= false; 
                        } 
                    } 
                    if (sb.ToString().Length== 0) 
                    { 
                        nReadCount++; 
                    }                 if (nReadCount == 3) 
                    { 
                        nReadCount = 0; 
                        throw new Exception("设置不正确或没有联接设备!"); 
                    }              
                } 
                catch (Exception ex) 
                { 
                    throw new Exception("从设备获取数据失败!\r\n错误信息:" + ex.Message); 
                } 
                return sb.ToString(); ; 
            }         public string WriteCommand(byte[] bCommand) 
            { 
                StringBuilder sb = new StringBuilder(); 
                bool bRead = true; 
                try 
                { 
                    ss_port.DiscardInBuffer(); 
                    ss_port.Write(bCommand,0,bCommand.Length); 
                    Thread.Sleep(1500); 
                    while (bRead) 
                    { 
                        _ReadBuffer = new byte[ss_port.BytesToRead]; 
                        ss_port.Read(_ReadBuffer, 0, _ReadBuffer.Length); 
                        sb.Append(Encoding.ASCII.GetString(_ReadBuffer)); 
                        Thread.Sleep(500); 
                        if (ss_port.BytesToRead <= 0) 
                        { 
                            bRead = false; 
                        } 
                    } 
                    if (sb.ToString().Length == 0) 
                    { 
                        nReadCount++; 
                    }                 if (nReadCount == 3) 
                    { 
                        nReadCount = 0; 
                        throw new Exception("设置不正确或没有联接设备!"); 
                    }              
                } 
                catch (Exception ex) 
                { 
                    throw new Exception("从设备获取数据失败!\r\n错误信息:" + ex.Message); 
                } 
                return sb.ToString(); 
            } 
            #endregion         #region Get All COM Port 
            public string[] GetAllComPort() 
            { 
                string[] sAllPort = null; 
                try 
                { 
                    sAllPort = SerialPort.GetPortNames(); 
                } 
                catch (Exception ex) 
                { 
                    throw new Exception("获取计算机COM口列表失败!\r\n错误信息:" + ex.Message); 
                } 
                return sAllPort; 
            } 
            #endregion 
        } } 
      

  4.   

    这样的方法可以等到数据接收完,可是要sleep()等。在vb 下 sleep 就停了如果循环时间长了cpu占用太高。所以我尽量避免用这样的方法。针对 微软的这个串口类,有合适的用法或说法吗?
    如果实在不行再考虑 等够字节数。我要很及时的把数据通讯完,因为下边设备不等我。
      

  5.   


    现更改设置如下:
    serialPort1.ReceivedBytesThreshold = 3000;中断照常响应。照样不到1043字节就提前中断,而且把所有字节都读上来中断还响应,再读就是0。中断疯了................................
      

  6.   

    private void serialPort1_DataReceived(object sender, System.IO.Ports.SerialDataReceivedEventArgs e)
    {            SerialPort port = (SerialPort)sender;
                List<byte> Lb = new List<byte>();
                
                //ポートのデータを全て読み込む。
                while (port.BytesToRead > 0)
                {
                    byte[] buf = new byte[1024];
                    int len = port.Read(buf, 0, 1024);
                    Lb.AddRange(buf.Take(len));
                    System.Threading.Thread.Sleep(100);
                }
               if (Lb.Count== 1043)
                {//这里做处理
                }
    ...
    }
      

  7.   

    DataReceived在两种情况下触发,一是ReceivedBytesThreshold达到指定字节数,一是在输入流中检测到EOF字符,这个可以通过检测e.EventType属性是否等于SerialData.EOF来判断。.net的串口控件好像没办法设置接受到EOF时不触发事件,你可以尝试在事件处理函数中检测到SerialData.EOF而触发事件时不读取输入缓存,不作任何处理
      

  8.   


    当初我在msdn上确实看到这个提示了,没在意。
    看来确实要验证一下了!
      

  9.   

    未能解决我的问题;绝大多数时候提前中断时,e.EventType 属性不等于 Eof.
      

  10.   

    结贴:    最终结论:我不能很好的运用c#下的这个控件,现已改用vb重写该程序。还是这个思路用vb重写后运行良好。               网上好多人也不能熟练应用这个类看来由vb转到c#微软对这个做的还是不够好
      

  11.   


       while (flag)
                {
                    StringBuilder build = new StringBuilder();
                    intBytes = serialPort1.BytesToRead;
                    byte[] bytes = new byte[intBytes + 1];
                    serialPort1.Read(bytes, 0, intBytes);
                    build.Append(Encoding.ASCII.GetString(bytes, 0, intBytes));
                    string str = build.ToString();
                    System.Threading.Thread.Sleep(100);
            }

    我这样写的没有问题
    以前也碰到读不全的问题
    最后就是System.Threading.Thread.Sleep(100);
    将问题解决的.
      

  12.   

    郁闷,这么多人也没说出个所以然来,看来是bug,只能用笨办法了
      

  13.   

    18楼的
     Lb.AddRange(buf.Take(len));中的Take是什么方法?能写详细些吗?