2012-12-06 17 views
20

Tôi đã đọc rất nhiều câu hỏi ở đây về cách đọc dữ liệu từ cổng nối tiếp bằng cách sử dụng lớp .NET SerialPort nhưng không có cách tiếp cận được giới thiệu nào đã chứng minh hiệu quả hoàn toàn đối với tôi.Cách chính xác để đọc cổng nối tiếp bằng cách sử dụng .NET framework là gì?

Đây là mã tôi đang sử dụng cho bây giờ:

SerialPort port = new SerialPort("COM1"); 
port.DataReceived += new SerialDataReceivedEventHandler(MyDataReceivedHandler); 

Và xử lý sự kiện:

void MyDataReceivedHandler(object sender, SerialDataReceivedEventArgs e) 
{ 
    int count = port.BytesToRead; 
    byte[] ByteArray = new byte[count]; 
    port.Read(ByteArray, 0, count); 
} 

Nhưng tôi vẫn còn thiếu một số dữ liệu đôi khi. Tôi đã thử cách khác nhau để đọc dữ liệu trong trình xử lý sự kiện nhưng không có may mắn. .NET 4.5 mang lại khả năng mới để thực hiện một số nhiệm vụ không đồng bộ, như với phương thức ReadAsync có vẻ có thể sử dụng trên luồng SerialPort, tôi tò mò muốn xem phương pháp được đề nghị để xử lý những trường hợp đó là gì.

+3

Câu hỏi của bạn thực sự mơ hồ. "Tôi vẫn còn thiếu một số dữ liệu đôi khi" cũng giống như nói với thợ máy của bạn "xe của tôi làm cho một tiếng ồn buồn cười đôi khi" và yêu cầu bao nhiêu nó sẽ có chi phí để sửa chữa. Có lẽ [câu trả lời này] (http://stackoverflow.com/a/2966357/62576) cho một câu hỏi liên quan có thể hữu ích. Tuy nhiên, tôi nghĩ bạn cần phải cụ thể hơn nhiều nếu bạn muốn được giúp đỡ; như vậy, không có nhiều câu trả lời bằng cách nhìn vào các câu hỏi khác về chủ đề này. –

+0

Bạn nói đúng, tôi sẽ đưa một ví dụ thực tế lại với nhau để minh họa rõ hơn những gì đang xảy ra ... –

+3

Thực hiện giao thức truyền thông nối tiếp qua RS232 hoặc 485 là một nhiệm vụ thực sự khó khăn. Nó đòi hỏi rất nhiều kinh nghiệm. Tôi đã thực hiện điều này kể từ ngày DOS cũ tốt và vẫn gặp khó khăn trong một số cạm bẫy phổ biến. Tại sao bạn không cố gắng tìm một sản phẩm đáng tin cậy của bên thứ ba để xử lý thông tin liên lạc nối tiếp? Họ sẽ có thể ironed ra tất cả nhiều, nhiều, nhiều lỗi bạn sẽ rơi vào chính mình :-) Nếu đây là một tập thể dục, sau đó đi trước, nó cho sự hài lòng tuyệt vời để cuối cùng chủ thông tin liên lạc nối tiếp! :-) – Loudenvier

Trả lời

14

Bạn có thể thử một cái gì đó như thế này ví dụ như tôi nghĩ rằng những gì bạn đang muốn sử dụng là port.ReadExisting() Phương pháp

class SerialPortProgram 
{ 
    // Create the serial port with basic settings 
    private SerialPort port = new SerialPort("COM1", 
     9600, Parity.None, 8, StopBits.One); 
    [STAThread] 
    static void Main(string[] args) 
    { 
     // Instatiate this 
     class new SerialPortProgram(); 
    } 

    private SerialPortProgram() 
    { 
     Console.WriteLine("Incoming Data:"); 
     // Attach a method to be called when there 
     // is data waiting in the port's buffer 
     port.DataReceived += new SerialDataReceivedEventHandler(port_DataReceived); 
     // Begin communications 
     port.Open(); 
     // Enter an application loop to keep this thread alive 
     Application.Run(); 
    } 

    private void port_DataReceived(object sender, SerialDataReceivedEventArgs e) 
    { 
     // Show all the incoming data in the port's buffer 
     Console.WriteLine(port.ReadExisting()); 
    } 
} 

Hoặc là bạn muốn làm điều đó dựa trên những gì bạn đã cố gắng để làm, bạn có thể thử này

public class MySerialReader : IDisposable 
{ 
    private SerialPort serialPort; 
    private Queue<byte> recievedData = new Queue<byte>(); 

    public MySerialReader() 
    { 
    serialPort = new SerialPort(); 
    serialPort.Open(); 
    serialPort.DataReceived += serialPort_DataReceived; 
    } 

    void serialPort_DataReceived(object s, SerialDataReceivedEventArgs e) 
    { 
    byte[] data = new byte[serialPort.BytesToRead]; 
    serialPort.Read(data, 0, data.Length); 
    data.ToList().ForEach(b => recievedData.Enqueue(b)); 
    processData(); 
    } 

    void processData() 
    { 
    // Determine if we have a "packet" in the queue 
    if (recievedData.Count > 50) 
    { 
     var packet = Enumerable.Range(0, 50).Select(i => recievedData.Dequeue()); 
    } 
    } 

    public void Dispose() 
    { 
     if (serialPort != null) 
     { 
      serialPort.Dispose(); 
     } 
    } 
+1

Cảm ơn sự giúp đỡ của bạn, cuối cùng tôi đã đi với 'ReadExisting' được sử dụng với một bộ sưu tập chặn. Tôi vẫn đang lên kế hoạch thử chức năng 'ReadAsync' mới mặc dù ... –

+0

phương thức processData() có cần một mutex không? Tôi có nghĩa là, các sự kiện datareceived có thể kích hoạt một lần nữa khi processData() vẫn chạy? phải không? Vì vậy, chúng tôi có thể kết thúc với hai (hoặc nhiều hơn?) Chủ đề chạy bên trong processData() phương pháp .... –

+0

Tôi đã không cố gắng nó đến mức độ đó và dựa trên những gì Yannick đã đề cập trong bình luận của mình ở trên tôi nghĩ rằng nó sẽ không tạo sự khác biệt nếu anh ta tiếp tục đọc không đồng bộ – MethodMan

4

tôi đã sử dụng mã tương tự như @MethodMan nhưng tôi đã phải theo dõi các dữ liệu của cổng nối tiếp được gửi và tìm kiếm một nhân vật chấm dứt để biết khi nào các cổng nối tiếp đã được thực hiện gửi dữ liệu.

private string buffer { get; set; } 
private SerialPort _port { get; set; } 

public Port() 
{ 
    _port = new SerialPort(); 
    _port.DataReceived += new SerialDataReceivedEventHandler(dataReceived); 
    buffer = string.Empty; 
} 

private void dataReceived(object sender, SerialDataReceivedEventArgs e) 
{  
    buffer += _port.ReadExisting(); 

    //test for termination character in buffer 
    if (buffer.Contains("\r\n")) 
    { 
     //run code on data received from serial port 
    } 
} 
0

Tôi nghĩ không sử dụng SerialDataReceivedEvent. Bộ hẹn giờ là một trong những lựa chọn tốt hơn và sau một thời gian không đổi, để nhận dữ liệu:

For i = 1 To Me.objSerialPort.BytesToRead 
    strReceiveData &= Convert.ToChar(Me.objSerialPort.ReadByte) 
Next i