用.net 自带的serialport控件读出数据经常出现读出的数据不完整(以下是原代码)
请高手指点一下
        private SerialPort serialPort = new System.IO.Ports.SerialPort();
        private PDU_DeCoding SmsSend = new PDU_DeCoding();
        private PDUCoding sms=new PDUCoding();
        private void Form1_Load(object sender, EventArgs e)
        {
            f_BG.DoWork += new DoWorkEventHandler(f_BG_DoWork);
            f_BG.RunWorkerAsync();
            btnClose.Enabled = false;
            string[] portNames = SerialPort.GetPortNames();
            for (int i = 0; i < portNames.Length; i++)
            {
                cmbCom.Items.Add(portNames[i]);
            }
            if (portNames.Length > 0)
            {
                cmbCom.SelectedIndex = 0;
            }
        }
        public delegate void myDelegate(string text);
        
        public void updateTextBox(string text)
        {
            lbcontent.Items.Add(text);
                        
        }
        public StringBuilder sb = new StringBuilder();
        public void AddReceiveData(string text)
        {
            lock (sb)
            {
                sb.Append(text);
            }
        }
        private void serialPort_DataReceived(object sender,System.IO.Ports.SerialDataReceivedEventArgs e)
        {
            System.Threading.Thread.Sleep(1000);            System.IO.Ports.SerialPort serialPort = (System.IO.Ports.SerialPort)sender;
            string strReceive = string.Empty;
            string strCollect = string.Empty;            byte[] Buffer = new byte[serialPort.BytesToRead];
            serialPort.Read(Buffer, 0, Buffer.Length);
            strReceive = Encoding.ASCII.GetString(Buffer);
            lbcontent.BeginInvoke(new myDelegate(updateTextBox), "收到com口数据" + strReceive + "\n");
            strCollect += strReceive;
             BackgroundWorker bgWorker = new BackgroundWorker();
            bgWorker.DoWork += new DoWorkEventHandler(bgWorker_DoWork);
            bgWorker.RunWorkerAsync(strCollect);                       
        }         private void bgWorker_DoWork(object sender, DoWorkEventArgs e)
        {
            string  bs = (string)e.Argument;
            AddReceiveData(bs);
            
        }
        private void btnconnect_Click(object sender, EventArgs e)
        {
            serialPort.DataReceived -= new System.IO.Ports.SerialDataReceivedEventHandler(serialPort_DataReceived);
            if (serialPort.IsOpen)
            {
                serialPort.Close();
            }
            try
            {
                serialPort.PortName = cmbCom.SelectedItem.ToString();
                serialPort.BaudRate = 9600;
                serialPort.Parity = Parity.None;
                serialPort.DataBits = 8;
                serialPort.StopBits = System.IO.Ports.StopBits.One;
                serialPort.RtsEnable = true;
                serialPort.WriteBufferSize = 1024;
                serialPort.ReadBufferSize = 1024;
                serialPort.ReadTimeout = 2500;
                serialPort.Open();
                byte[] buffer = Encoding.ASCII.GetBytes("AT\r");
                serialPort.Write(buffer, 0, buffer.Length);
                System.Threading.Thread.Sleep(150);
                string Data = serialPort.ReadExisting();
                if (Data.IndexOf("OK") != -1)
                {
                    
                    lbcontent.Items.Add("COM口返回数据:" + Data);
                    lbcontent.Items.Add("连接" + serialPort.PortName + "成功\n");
                    buffer = Encoding.ASCII.GetBytes(txtmoblie.Text + "\r");
                    serialPort.Write(buffer, 0, buffer.Length);
                    lbcontent.Items.Add("向COM口发送数据:" + txtmoblie.Text + "\n");
                    System.Threading.Thread.Sleep(100);
                    string d = serialPort.ReadExisting();
                    // string d = "\r\n+CSCA: \"+8613800100500\",145\r\n\r\nOK\r\n";
                    //去掉\r\n
                    int start = d.IndexOf("86");
                    if (start != -1)
                    {
                        txtSMSCenter.Text = d.Substring(start, 13);
                        lbcontent.Items.Add("短信中心号码" + d.Substring(start, 13));
                        lbcontent.Items.Add("Com口返回数据" + d);                    }
                    btnconnect.Enabled = false;
                    btnClose.Enabled = true;
                    serialPort.DiscardInBuffer();
                }
                else
                {
                    MessageBox.Show("连接失败");
                }
            }
            catch (Exception ex)
            {
                lbcontent.Items.Add(ex.ToString());
            }
            finally
            {
                serialPort.DataReceived += new System.IO.Ports.SerialDataReceivedEventHandler(serialPort_DataReceived);
            }
        }        private void btnClose_Click(object sender, EventArgs e)
        {
            try
            {
                
                serialPort.Close();
                lbcontent.Items.Add("断开"+serialPort.PortName+"成功\n");
                btnClose.Enabled = false;
                btnconnect.Enabled = true;
            }catch(Exception ex)
            {
                lbcontent.Items.Add(ex.ToString());
            }        }
        
        private void btnSend_Click(object sender, EventArgs e)
        {
            serialPort.DataReceived -= new System.IO.Ports.SerialDataReceivedEventHandler   
(serialPort_DataReceived);
            string decodeSMS = SmsSend.smsDecodedsms(txtSMSCenter.Text,txtmoblie.Text.Trim(),txtcontent.Text);
            byte[] buf = Encoding.ASCII.GetBytes(String.Format("AT+CMGS={0}\r", SmsSend.nLength));
            serialPort.Write(buf,0,buf.Length);
            System.Threading.Thread.Sleep(200);
            string response = serialPort.ReadExisting();
            if (response.Length > 0 && response.EndsWith("> "))
            {
                buf = Encoding.ASCII.GetBytes(string.Format("{0}\x01a", decodeSMS));
                serialPort.Write(buf, 0, buf.Length);
                lbcontent.Items.Add("向手机号:"+txtmoblie.Text+";发送:"+txtcontent.Text+"成功\n");
            }
                       serialPort.DataReceived += new System.IO.Ports.SerialDataReceivedEventHandler(serialPort_DataReceived);
        }        private void f_BG_DoWork(object sender, DoWorkEventArgs e)
        {
            while (true)
            {
                System.Threading.Thread.Sleep(200);
                lock(sb)
                {
                string response = sb.ToString();
                
                if (response.Length > 0 && response.IndexOf("+CMT:") != -1)
                {
                    response = response.Replace("\r\n", "|");
                    int i = response.IndexOf("|");
                    if (i == 0)
                    {
                        i = 1;
                    }
                    else
                    {
                        i = 0;
                    }                    i = response.IndexOf("|", i);
                    response = response.Remove(0, i);
                    response = response.Replace("|", "");
                    string SendPhoneNumber = "";
                    string SendContent = "";
                    DateTime SendTime = new DateTime();                    string SCA = "";
                    PDUCoding.GSMCode code = new PDUCoding.GSMCode();
                    if (sms.DecodingMsg(response, ref SendPhoneNumber, ref SendContent, ref SendTime, ref code, ref SCA))
                    {
                        lbcontent.BeginInvoke(new myDelegate(updateTextBox), SendPhoneNumber.ToString() + "于" + SendTime.ToString() + "发来信息:" + SendContent.ToString());
                        if (SendContent.Substring(0, 2) == "查询")
                        {
                            //serialPort.DataReceived -= new System.IO.Ports.SerialDataReceivedEventHandler(serialPort_DataReceived);
                            string decodeSMS = SmsSend.smsDecodedsms(txtSMSCenter.Text, SendPhoneNumber.ToString(), "您的查询是");
                            byte[] buf = Encoding.ASCII.GetBytes(String.Format("AT+CMGS={0}\r", SmsSend.nLength));
                            serialPort.Write(buf, 0, buf.Length);
                            System.Threading.Thread.Sleep(200);
                            string response1 = serialPort.ReadExisting();
                            if (response1.Length > 0 && response1.EndsWith("> "))
                            {
                                buf = Encoding.ASCII.GetBytes(string.Format("{0}\x01a", decodeSMS));
                                serialPort.Write(buf, 0, buf.Length);
                                lbcontent.BeginInvoke(new myDelegate(updateTextBox), "向手机号:" + txtmoblie.Text + ";发送:" + txtcontent.Text + "成功\n");
                            }
                            //serialPort.DataReceived += new System.IO.Ports.SerialDataReceivedEventHandler(serialPort_DataReceived);
                        }
                    }
                    sb.Remove(0, sb.Length);
                    }
                }
            }
        }       
        

解决方案 »

  1.   

    我做过,但是
    ycui_hong
     
    等 级: 
    结帖率:50.00%等下吧
      

  2.   

    代码太长。下次记得用UBB标记一下。c系列代码没格式很难找括号对应关系。你的代码大致看了一下,因为没注解,只看了关键的Reveived方法,比较多的多余代码,不一定就会错,但是多一步不是100%正确的代码就有一点可能性。比如数据读取可以改为ReadExisting而不是搬到缓存中再处理。你的问题是什么?
      

  3.   

    我的问题是,我读到的数据不完整只读出来:+CMTI:"SM",40正常短信猫有短信应该读到的数据是下面这些
    +CMT: ,14\r\n0891683108100005F0240D91683193816129F621085040421201502368767D98864EBA751F51997167003A8D775F976BD49E2190FD65E9002C5E725F976BD49A7490FD7D2F002C54035F976BD4732A90FD5DEE002C4E0B73ED6BD45C0F59D090FD665A002C63235F976BD46C115DE590FD5C11002C770B8D7767656BD48C0190FD597D0021\r\n"
      

  4.   

    我用 serialport.close() 关闭串口,会出现“因为执行绪结束或应用程式要求,所以已中止I/O操作” 错误。看大家都是直接调用 serialport.close() 关闭串口,怎么都没出问题。请高手多指教
      

  5.   

    建议你直接DataReceived中用ReadLine,记得之前先设置SerialPort对象的NewLine属性为"\r\n"
      

  6.   

    终于睡醒了,你的问题我也曾经出现过这个问题,你往下面几个方面检查一下吧,你的代码太乱了,没心思看,就只看了接收数据的部分。
    1.接收缓冲区大小不够:看了一下你的代码,发现你的缓冲区是不断改变的,最好固定一下,给个例子吧private void serialPort1_DataReceived(object sender, SerialDataReceivedEventArgs e)
            {
                int bytes = serialPort1.BytesToRead;    //得到数据长度
                  buffer = new byte[2048];                  //接收缓冲区
                serialPort1.Read(buffer, 0, bytes);     //读取数据
                string str_pass = "";
                str_pass = Encoding.ASCII.GetString(buffer, 0, bytes);
                setText1(str_pass);                  //
                if (bRecievemsg)                     //
                {                                    //处理数据
                    msg.Add(str_pass);               //
                    setText2(msg);                    //
                }
            }
    2.发送端发送太快,以致接收端来不及处理,这个,你好像是做短信的,一般没有这个问题;
    3.硬件问题,如果硬件有问题,会出现接收乱码或其它一系列问题;
    4.其它:与接收无太大关系,可能是其它处理导致的。例如,看到你的接收方法中有System.Threading.Thread.Sleep(1000);一句,当然我不是说这句一定有问题,我是想说,每一句都应该有它的作用,在必要的时候选用合适的语句是个很好的编程方式,也就是,不要滥用语句,由于代码太长太乱,我就不仔细看了哈。