2012-12-06 20 views
20

.NET SerialPort sınıfını kullanarak seri bağlantı noktalarından veri okuma konusunda birçok soru okudum, ancak önerilen yaklaşımların hiçbiri benim için tamamen etkili olmadı..NET çerçevesini kullanarak seri bağlantı noktasını okumak için doğru yol nedir?

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

Ve olay işleyicisi: Burada

şimdilik kullanıyorum kodudur

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

Ama hala bazen bazı verileri özlüyorum. Olay işleyicisindeki verileri farklı bir şekilde okumaya çalıştım ama şanssız.

.NET 4.5, SerialPort akışında kullanılabilir gibi görünen ReadAsync yönteminde olduğu gibi, bazı eşzamansız görevleri yapmak için yeni olanaklar getirdiğinden, bu durumları ele almak için önerilen yaklaşımın ne olacağını merak ediyorum.

+3

Sorunuz gerçekten belirsizdir. "Bazen bazı verileri eksik özlüyorum" diye anlatıyor makinanızı anlatmak "arabam bazen komik bir ses çıkarır" ve ne kadar maliyetinin düzeltileceğini sorar. Belki ilgili bir soruya [bu cevap] (http://stackoverflow.com/a/2966357/62576) yardımcı olabilir. Ancak, yardım istiyorsanız çok daha spesifik olmanız gerektiğini düşünüyorum; olduğu gibi, bu konuyla ilgili diğer sorulara bakarak cevaplanamayacak pek bir şey yok. –

+0

Haklısınız, neler olup bittiğini daha iyi göstermek için birlikte gerçek bir örnek koyacağım ... –

+3

RS232 veya 485 üzerinden bir seri iletişim protokolü uygulamak gerçekten çok zor bir iş. Çok fazla deneyim gerektirir. Bunu eski eski DOS günlerinden beri uyguluyorum ve hala bazı ortak tuzaklarda sıkışıp kaldım. Neden seri haberleşmeyle ilgili güvenilir bir üçüncü taraf teklifi bulmaya çalışmıyorsunuz? Muhtemelen kendinize düşecek olan çok fazla, çok sayıda böcekleri ütülemiş olacaklar :-) Eğer bu bir egzersiz ise, o zaman devam edin, son olarak seri haberleşmeye hakim olmak için büyük bir memnuniyet veriyor! :-) – Loudenvier

cevap

14

sana ne yararlanmak isteyen vardır port.ReadExisting() Yöntem

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()); 
    } 
} 

olduğunu Yoksa çalışıyorlardı ne dayalı yapmak istiyorum olduğunu düşünüyorum mesela böyle bir şey dener misin yapmaya, deneyebileceğiniz bu

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

Yardımlarınız için teşekkürler, nihayet engelleme koleksiyonuyla kullanılan 'ReadExisting' ile gittim. Yine de yeni ReadAsync işlevini denemeyi düşünüyorum ... –

+0

processData() yöntemi bir muteks gerektirmiyor mu? Demek istediğim, processData() hala çalışıyorsa, datareceived olayı tekrar tetikleyebilir mi? öyle değil mi Bu yüzden processData() yönteminin içinde çalışan iki (veya daha fazla?) Iş parçacığıyla sonuçlanabilirdik. –

+0

Bu konuda denemedim ve Yannick'in kendi yorumunda bahsettiği şeylere dayanarak bunun olacağını düşünüyorum. Asynchronously ile okumaya devam ederse bir fark yaratmamak – MethodMan

4

Ben @MethodMan benzer bir kod kullanılmış ama seri port gönderdiğini verileri takip ve seri port gönderme yapıldığını bilmeniz gereken sonlandırma karakteri aramak zorunda veri.

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

Sanırım SerialDataReceivedEvent kullanmayın. Zamanlayıcı, daha iyi bir seçenektir ve sabit bir süreden sonra, veriyi almak için:

İlgili konular