我的软件是与PDA通过串口通讯。
我用的是C#语言,串口通讯用的.NET的SerialPort类。
我的SerialPort打开了,为什么有时候我的软件接收不到PDA发送的数据呢?
用串口调试助手与PDA连接成功后,我的软件就能接受到PDA发送的数据了。但是有时候我的软件也能正常的接受PDA发送的数据。
配置参数如下:
BaudRate = 19200;
DataBits = 8;
DisCardNull = False;
DtrEnable = False;
Handshake = None;
Parity = None;
ParityReplace = 63;
PortName = COM1;
ReadBufferSize = 4096;
ReadTimeout = 1000;
ReceiveBytesThreshold = 1;
RtsEnable = False;
StopBits = One;
WriteBufferSize = 2048;
WriteTimeout = 1000;

解决方案 »

  1.   

    请参考下面的方法。
    技术要点: 
    (1).首先,SerialPort的ReceivedBytesThreshold先设置成1,表示只要有1个字符送达端口时便触发DataReceived事件 
    (2).当DataReceived触发时,先把ReceivedBytesThreshold设置成一个比较大的值,达到读取本次端口数据时,不再触发DataReceived. 
    (3).循环读取端口中的数据,直至读完。 
    (4).移除读取数据中的非法字符。 
    (5).触发一个后台线程处理收到的数据。 
    (6).在finally中把ReceivedBytesThreshold重置回1         private void serialPort1_DataReceived(object sender, System.IO.Ports.SerialDataReceivedEventArgs e) 
            { 
                if (sender.GetType() != typeof(System.IO.Ports.SerialPort)) 
                { 
                    return; 
                } 
                string strReceive = string.Empty; 
                string strCollect = string.Empty; 
                System.IO.Ports.SerialPort comPort = (System.IO.Ports.SerialPort)sender;             try 
                { 
                    comPort.ReceivedBytesThreshold = comPort.ReadBufferSize; 
                    while (true) 
                    { 
                        strReceive = comPort.ReadExisting(); 
                        if (string.Equals(strReceive, string.Empty)) 
                        { 
                            break; 
                        } 
                        else 
                        { 
                            strCollect += strReceive; 
                            Application.DoEvents(); 
                            Thread.Sleep(100); 
                        } 
                    } 
                    strCollect = strCollect.Replace("\0", string.Empty); 
                    strCollect = strCollect.Replace("\r\n", string.Empty); 
                    strCollect = strCollect.Replace("\r", string.Empty); 
                    strCollect = strCollect.Replace("\n", string.Empty);                 if (!this.bIsHandleCom) 
                    { 
                        this.bIsHandleCom = true; 
                        mReceiveData = strCollect; 
                        if (ReceiveDataParserEvent != null) 
                            ReceiveDataParserEvent(mReceiveData); 
                        if (ThreadReceiveParser != null && !ThreadReceiveParser.IsAlive) 
                        { 
                            ThreadReceiveParser.Start(); 
                        } 
                    }             } 
                catch (Exception ex) 
                { 
                    MessageBox.Show(this, ex.ToString(), Application.ProductName, MessageBoxButtons.OK, MessageBoxIcon.Error); 
                } 
                finally 
                { 
                    comPort.ReceivedBytesThreshold = 1; 
                } 
            } 
      

  2.   

    private SerialPort _com = new SerialPort();//串口对象 
      /// <summary> 
            /// 打开串口 
            /// </summary> 
            /// <param name="strCom">串口名“COM1” </param> 
            /// <param name="nBot">波特率 </param> 
            /// <param name="nThreshold">引发消息事件的字节数 </param> 
            public void OpenPort(string strCom, int nBot) 
            { 
                try 
                { 
                    //串口设置与打开 
                    //_com.DataReceived += new System.IO.Ports.SerialDataReceivedEventHandler(DataReceivedAddress); 
                    _com.PortName = strCom; 
                    _com.BaudRate = nBot; 
                    _com.DataBits = 8; 
                    _com.StopBits = StopBits.One; 
                    _com.Parity = Parity.Even; 
                    _com.Open(); 
                } 
                catch (Exception ex) 
                { 
                    //Application.Exit();//退出应用程序 
                    //System.Diagnostics.Process.Start("JT.exe");//启动程序 
                  MessageBox.Show("“" + ex.Message + "”设置硬件功能将不可用,如要使用该功能,请到主窗体的系统设置中选择正确的串口信息,并重新打开该模块!", "提示", MessageBoxButtons.OK, MessageBoxIcon.Warning);             }         } 
    OpenPort(com1, 9600); 
    _com.DataReceived += new System.IO.Ports.SerialDataReceivedEventHandler(DataReceivedAddress); 
    public void DataReceivedAddress(object sender, SerialDataReceivedEventArgs e) 
            { 
                byte[] data = new byte[_com.BytesToRead]; 
                _com.Read(data, 0, data.Length); 
                if (data.Length != 0) 
                {                 DisposeRecvDataAddress(data);             } 
            } 
      public void DisposeRecvDataAddress(byte[] data) 
            { 
                string strReceive = ""; 
                //MessageBox.Show("进来了"); 
                try 
                { 
                    for (int i = 0; i < data.Length; i++) 
                    { 
                        strReceive += TenToHex(data[i].ToString()); 
                        //strReceive +=  data[i].ToString(); 
                    } 
                然后把接收到的数据按照协议来处理 
                } 
      

  3.   

    这是.NET的SerialPort类的一个bug吧,我以前也碰到过,在一般的台式电脑还可以,但在笔记本上最容易发生,建议不要用SerialPort,效率又低,还有这么大的一个bug,你最好用windowsAPI吧,我现在都改成用API了,受不了SerialPort,特别是在半双工高速通讯的时候
      

  4.   

    void __fastcall TForm1::Button2Click(TObject *Sender)
    {
     if (hComm!=INVALID_HANDLE_VALUE) CloseHandle(hComm);
      exit(EXIT_SUCCESS);}
    //---------------------------------------------------------------------------void __fastcall TForm1::Button1Click(TObject *Sender)
    {
     char *ComNo; 
      DCB dcb;
      String Temp;
      //取得要打开的通讯端口。 
      Temp = "COM"+IntToStr(1);
      //转换至指针类型Char。 
      ComNo = Temp.c_str();
      hComm = CreateFile(ComNo,GENERIC_READ | GENERIC_WRITE,
          0, NULL, OPEN_EXISTING, 0, 0); 
      if (hComm == INVALID_HANDLE_VALUE) // 如果通讯端口未打开 
      { 
        MessageBox(0, "打开通讯端口错误!!","Comm Error",MB_OK); 
        return; 
      } 
      // 
      GetCommState(hComm,&dcb);                        // 获得当前通讯端口状态。
      dcb.BaudRate = CBR_9600;                          // 设置速率为9600 
      dcb.ByteSize = 8;                                  // 字节为8 bit 
      dcb.Parity = NOPARITY;                            // Parity 为 None 
      dcb.StopBits = ONESTOPBIT;                      // 1 个 Stop bit 
      //端口设置。 
      if (!SetCommState(hComm, &dcb)) {      // 设置通讯端口状态
        MessageBox (0, "通讯端口错误!!!","Set Error",MB_OK); 
        CloseHandle(hComm);
        return; 
      } 
        
    }
    //---------------------------------------------------------------------------
    void __fastcall TForm1::Button3Click(TObject *Sender)
    {
    String Temp; 
      char *SendData; 
      int  ln; 
      unsigned long lrc,BS; 
      if (hComm==0) return; //检查Handle值 
      Temp = mSend->Text;//取得要发送的字符串 
      SendData = Temp.c_str(); //字符串转换 
      //取得要发送的字符串数。 
      BS = Temp.Length(); 
      //BS = StrLen(SendData);  //也可以用此方法取得要发送的字符串长度。 
      //实际的发送动作。 
      WriteFile(hComm,SendData,BS, &lrc,NULL); // 发送数据。
        
    }
    //---------------------------------------------------------------------------
    void __fastcall TForm1::Button4Click(TObject *Sender)
    {
    String Temp; 
      char inbuff[1024]; 
      DWORD nBytesRead, dwEvent, dwError; 
      COMSTAT cs; 
        //取得状态 
      ClearCommError(hComm,&dwError,&cs); 
      // 数据是否大于我们准备的缓冲区 
      if (cs.cbInQue > sizeof(inbuff)) 
      { 
        PurgeComm(hComm, PURGE_RXCLEAR);  // 清除通讯端口数据。 
        return; 
        } 
      ReadFile(hComm, inbuff,cs.cbInQue,&nBytesRead,NULL); //接收通讯端口的数据。 
      //数组中的字符串接尾处接上\0. 
      inbuff[cs.cbInQue]= '\0'; 
      //将数组显示在MEMO1上。 
      mReceive->Text = inbuff; 
        
    }
    //---------------------------------------------------------------------------
    我这里有一个其他编程语言的API,不过API的编程几乎都一样,你参考一下!!
      

  5.   

    你的笔记本上有串口?笔记本上有BUG,说明是USB转串口不稳定
      

  6.   

    笔记本有串口,这也是怪事,虽然这年头带串口的笔记本不多了,但并不代表没有,dell d630就有串口的,我们公司是做硬件的,一般都会买带串口的电脑,usb转rs232一般都不好用,特别是在进行长时间大量数据通讯时
      

  7.   

    我碰到这个问题并不是在一两台笔记本上,而是多台,而且我在一台防爆电脑上也碰到过,其实说白了,就是serialPort在串参数设置时有问题
      

  8.   

    我用serialport还可以,
    偶尔有错位的情况,自己处理下就行了
    是不是硬件有问题啊,发指令没有响应
      

  9.   

    在台式机上,一般都不会出问题(我没碰到过),笔记本上,也不是每个都有问题,在有问题的笔记本上,用串口调试助手后就不会出问题了,但重启电脑又会出现,这是因为SerialPort在进行串口参数设置时有bug
      

  10.   

    串口通信本来就是不可靠的通信方式,要进行拆包,组包的操作,而且一般还要加上crc验证。这是串口通信的设计特点。假设都不按照路子走,就只能做些特别处理1. 接收事件里不能立刻就操作接收的数据,因为很可能触发事件时,数据并没有接收完全。
    2. 接收事件里加上适当的延时,可以提高数据填满缓冲区的几率。 可提高通信质量
    假设10次丢5次的话(数据未接收完全),适当延时几乎可以保证10次都收到,这是我实际的测试结果。(环境为长距离串口通信)
      

  11.   

    1、首先用串口助手之类的工具,确保PDA的串口是通畅的。
    2、再用串口助手测试你的程序可以正确的发送数据。
    3、程序与PDA互发数据。看是否通畅。
    我原来做这个也遇到过类似问题,基本这样解决的。主要原因是PDA的串口通信不稳定。所以你有时候儿会认为你的程序有问题,当然也可能是真得有问题。
      

  12.   

    哥们,串口调试助手连接PDA之后,你的软件就能接收到数据了?你的意思是必须先用串口调试助手打开串口,关闭串口后再启用你的程序嘛?
    代码整两盘上来看看?
      

  13.   

    有时候,用串口调试助手打开串口,向PDA发送响应命令后,PDA会显示连接成功,然后关闭串口调试助手,打开我的程序就能和PDA正常通讯了。
    而用我的程序发送响应命令,PDA上也会显示连接成功,但有时候会接受不到PDA发送的数据。
    是不是PDA的问题?
      

  14.   

    按照你的做法。
    用串口调试助手,PDA的串口时流畅的,能够正常发送和接受数据。
    用我的程序,也能与PDA进行正常的通讯。一直都能正常发送数据。因为我的程序发送命令后,PDA会显示连接成功,但有时候即使发送成功,连接成功,但还是接收不到数据。