2009-01-21 18 views
18

我正在嘗試創建一個小應用程序來收集從連接到COM10的外部傳感器收到的數據。我已經成功地創建了一個小型C#控制檯對象和應用程序,它使用for循環打開端口並將數據流傳輸到文件一段固定的時間。如何在C#中使用串口端口對象的dataReceived事件?

我想將此應用程序轉換爲使用dataReceived事件進行流式傳輸。看完Top 5 SerialPort Tips後,我仍然無法工作,也不知道自己錯過了什麼。我重寫了控制檯應用程序,以便所有代碼都在Main中並粘貼在下面。有人可以幫助啓發我,爲什麼事件處理程序port_OnReceiveDatazz沒有被調用,即使我知道有數據被硬件發送到端口?

感謝

阿齊姆

PS:感謝@Gabe@Jason Down,並且@abatishchev的所有建議。我很難過,似乎無法讓事件處理程序正常工作。也許它與設備有關。我只能在一個線程中讀取端口並將數據直接傳輸到文件中。


代碼


namespace serialPortCollection 
{ class Program 
    { 
     static void Main(string[] args) 
     { 

      const int bufSize = 2048; 
      Byte[] buf = new Byte[bufSize]; //To store the received data. 

      SerialPort sp = new SerialPort("COM10", 115200); 
      sp.DataReceived += port_OnReceiveDatazz; // Add DataReceived Event Handler 

      sp.Open(); 
      sp.WriteLine("$"); //Command to start Data Stream 

      // Wait for data or user input to continue. 
      Console.ReadLine(); 

      sp.WriteLine("!"); //Stop Data Stream Command 
      sp.Close(); 
     } 

     // My Event Handler Method 
     private static void port_OnReceiveDatazz(object sender, 
            SerialDataReceivedEventArgs e) 
     { 
      SerialPort spL = (SerialPort) sender; 
      const int bufSize = 12; 
      Byte[] buf = new Byte[bufSize]; 
      Console.WriteLine("DATA RECEIVED!"); 
      Console.WriteLine(spL.Read(buf, 0, bufSize)); 
     } 
    } 
} 
+0

什麼不工作? – 2009-01-21 18:53:14

+0

@Jon B:即使正在接收數據,事件處理程序也不會被調用。 – Azim 2009-01-21 19:05:38

回答

11

我覺得你的問題是該行: **

sp.DataReceived + = port_OnReceiveDatazz;

不是應該:

sp.DataReceived + =新SerialDataReceivedEventHandler(port_OnReceiveDatazz);

**沒關係,語法沒問題(當時我沒有意識到這個快捷方式我最初回答了這個問題)。

我也看到了建議,你應該打開下面的選項爲您的串行端口:

sp.DtrEnable = true; // Data-terminal-ready 
sp.RtsEnable = true; // Request-to-send 

您可能還設置握手RequestToSend(通過握手枚舉)。


UPDATE:

發現了一個建議,說你應該首先打開你的端口,然後分配事件處理程序。也許這是一個錯誤?

因此,不是這樣的:

sp.DataReceived += new SerialDataReceivedEventHandler (port_OnReceiveDatazz); 
sp.Open(); 

這樣做:

sp.Open(); 
sp.DataReceived += new SerialDataReceivedEventHandler (port_OnReceiveDatazz); 

讓我知道如何繼續下去。

+0

+ =新的SerialDataReceivedEventHandler – abatishchev 2009-01-21 18:58:23

+0

是的,固定了起來。謝謝。 – 2009-01-21 19:00:12

+0

是的,我也嘗試過。即使我確實知道正在接收數據,port_OnReceivedDatazz仍然不會被調用。 – Azim 2009-01-21 19:03:44

3

順便說一句,你可以在你的事件處理程序使用下面的代碼:

switch(e.EventType) 
{ 
    case SerialData.Chars: 
    { 
    // means you receives something 
    break; 
    } 
    case SerialData.Eof: 
    { 
    // means receiving ended 
    break; 
    } 
} 
8

首先,我建議你使用,而不是您目前使用的一個下面的構造函數:

new SerialPort("COM10", 115200, Parity.None, 8, StopBits.One); 

下一頁,你真的應該刪除這個代碼:

// Wait 10 Seconds for data... 
for (int i = 0; i < 1000; i++) 
{ 
    Thread.Sleep(10); 
    Console.WriteLine(sp.Read(buf,0,bufSize)); //prints data directly to the Console 
} 

而是隻是循環,直到用戶按下一個鍵或者像這樣:

namespace serialPortCollection 
{ class Program 
    { 
     static void Main(string[] args) 
     { 
      SerialPort sp = new SerialPort("COM10", 115200); 
      sp.DataReceived += port_OnReceiveDatazz; // Add DataReceived Event Handler 

      sp.Open(); 
      sp.WriteLine("$"); //Command to start Data Stream 

      Console.ReadLine(); 

      sp.WriteLine("!"); //Stop Data Stream Command 
      sp.Close(); 
     } 

     // My Event Handler Method 
     private static void port_OnReceiveDatazz(object sender, 
            SerialDataReceivedEventArgs e) 
     { 
      SerialPort spL = (SerialPort) sender; 
      byte[] buf = new byte[spL.BytesToRead]; 
      Console.WriteLine("DATA RECEIVED!"); 
      spL.Read(buf, 0, buf.Length); 
      foreach (Byte b in buf) 
      { 
       Console.Write(b.ToString()); 
      } 
      Console.WriteLine(); 
     } 
    } 
} 

此外,請注意數據接收事件處理程序的修訂,它應該實際上現在打印緩衝區。

UPDATE 1


我只是跑下面的代碼成功地在我的機器(使用COM33和COM34之間空調制解調器電纜)

namespace TestApp 
{ 
    class Program 
    { 
     static void Main(string[] args) 
     { 
      Thread writeThread = new Thread(new ThreadStart(WriteThread)); 
      SerialPort sp = new SerialPort("COM33", 115200, Parity.None, 8, StopBits.One); 
      sp.DataReceived += port_OnReceiveDatazz; // Add DataReceived Event Handler 

      sp.Open(); 
      sp.WriteLine("$"); //Command to start Data Stream 

      writeThread.Start(); 

      Console.ReadLine(); 

      sp.WriteLine("!"); //Stop Data Stream Command 
      sp.Close(); 
     } 

     private static void port_OnReceiveDatazz(object sender, 
            SerialDataReceivedEventArgs e) 
     { 
      SerialPort spL = (SerialPort) sender; 
      byte[] buf = new byte[spL.BytesToRead]; 
      Console.WriteLine("DATA RECEIVED!"); 
      spL.Read(buf, 0, buf.Length); 
      foreach (Byte b in buf) 
      { 
       Console.Write(b.ToString() + " "); 
      } 
      Console.WriteLine(); 
     } 

     private static void WriteThread() 
     { 
      SerialPort sp2 = new SerialPort("COM34", 115200, Parity.None, 8, StopBits.One); 
      sp2.Open(); 
      byte[] buf = new byte[100]; 
      for (byte i = 0; i < 100; i++) 
      { 
       buf[i] = i; 
      } 
      sp2.Write(buf, 0, buf.Length); 
      sp2.Close(); 
     } 
    } 
} 

UPDATE 2


最近給出了關於這個問題的所有流量。我開始懷疑你的串口配置不正確,或者設備沒有響應。

我強烈建議您嘗試使用其他方式與設備進行通信(我經常使用超級終端)。然後,您可以使用所有這些設置(比特率,奇偶校驗,數據位,停止位,流量控制),直到找到可用的設置。設備的文檔也應指定這些設置。一旦我明白了這些,我會確保我的.NET SerialPort配置正確,以使用這些設置。

上配置串口一些提示:

注意,當我說,你應該使用下面的構造,我的意思是使用該功能,並不一定是那些參數!您應該填寫設備的參數,以下設置是常見的,但對於您的設備可能會有所不同。

new SerialPort("COM10", 115200, Parity.None, 8, StopBits.One); 

將.NET串行端口設置爲使用與您的設備相同的流量控制(正如其他人之前所述)也很重要。你可以在這裏找到更多的信息:

http://www.lammertbies.nl/comm/info/RS-232_flow_control.html

4

我在與曾經工作且然後有一天剛剛停止提高DataReceived事件檢索調制解調器非常相同的問題。

在我的情況下,非常隨機的解決方案是使RTS例如

sp.RtsEnable = true; 

不知道爲什麼,關於包的特定位工作(而不是通訊科人都是真的),也沒有說明爲什麼它的工作,然後停止,但它可以幫助別人12:29人的日子,所以只是發表它只是在case ...

1

我相信這不起作用,因爲您正在使用控制檯應用程序,並且沒有運行Event Loop。用於事件處理的事件循環/消息泵在創建Winforms應用程序時自動設置,但不能用於控制檯應用程序。

1

事實上,很可能是Console.ReadLine阻止了你的回調Console.Writeline。 MSDN上的示例看起來幾乎相同,只是它們使用ReadKey(不鎖定控制檯)。

0

請注意使用.NET/C#和任何COM端口比COM9更高的問題。

參見:HOWTO: Specify Serial Ports Larger than COM9

有一個在格式解決方法:「\\?\ COM10」,即在底層的CreateFile方法的支持,但.NET防止使用替代方法格式; SerialPort構造函數和PortName屬性都不允許以「\」開頭的端口名稱我一直在努力使用C#/ .NET獲得與COM10的可靠通信。例如,如果我在COM9和COM10上有設備,則用於COM10的通信將發送到COM9上的設備!如果我在COM9上移除設備,則COM10流量將進入COM10上的設備。

我還沒有想過如何使用CreateFile返回的句柄來創建C#/ .NET風格的SerialPort對象,如果我知道如何做到這一點,那麼我認爲我可以在C#中使用COM10 +。